queries.py 4.79 KB
Newer Older
Franziska Koehn's avatar
Franziska Koehn committed
1
2
3
4
5
6
7
"""
:Author: Franziska Koehn
:Created: 2015/01/13

This module includes functions around sending and defining queries.
"""

Franziska Koehn's avatar
Franziska Koehn committed
8
9
10
from threading import Lock
requests_lock = Lock()

11
def get_query_methods():
Franziska Koehn's avatar
Franziska Koehn committed
12
    """Returns all applicable methods for creating a query."""
13
14
15
    return ["AND", "OR"]

def get_operators():
Franziska Koehn's avatar
Franziska Koehn committed
16
    """Returns all applicable Operators for creating a query."""
17
18
    return ["LIKE", ">", "<", "<=", ">=", "="]

Franziska Koehn's avatar
Franziska Koehn committed
19
20
#TODO download_async and download as one function???

21
def download_async(result, host, creds, rest, dest_folder='', cb=(lambda *_: None), cb_args=()):
Franziska Koehn's avatar
Franziska Koehn committed
22
23
24
25
26
27
28
29
30
31
32
33
    """
    Downloads file by using threads (So the GUI will not be bocked while downloading).

    **Parameters**
        :result: resultset, from which will be downloaded
        :host: address of host
        :creds: credentials (including user-name and -password)
        :rest: REST-API definition
        :dest_folder: folder where the downloaded files will be saved
        :cb: function for moving spinners
        :cb_args: args for function cb
    """
Franziska Koehn's avatar
Franziska Koehn committed
34
    from threading import Thread
35
    download_thread = Thread(target=download, args=(result, host, creds, rest, dest_folder, cb, cb_args))
Franziska Koehn's avatar
Franziska Koehn committed
36
37
    download_thread.start()
    return download_thread
Franziska Koehn's avatar
Franziska Koehn committed
38

39
def download(result, host, creds, rest, dest_folder='', cb=(lambda *_: None), cb_args=()):
Franziska Koehn's avatar
Franziska Koehn committed
40
41
42
43
44
45
46
47
48
49
50
51
52
    """
    Downloads a file.

    **Parameters**
        :result: resultset, from which will be downloaded
        :host: address of host
        :creds: credentials (including user-name and -password)
        :rest: REST-API definition
        :dest_folder: folder where the downloaded files will be saved
        :cb: function for moving spinners
        :cb_args: args for function cb
    """

Franziska Koehn's avatar
Franziska Koehn committed
53
    requests_lock.acquire()
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

    import re
    import os

    names=[]
    def subfunc(f):
        key = f.group(0).strip("{}")
        r = result[key]
        names.append(r)
        return r
    ret = re.sub('\{\w+\}', subfunc, rest)

    path = os.path.join(dest_folder, '-'.join(names))
    url = "%s%s" % (host, ret)

    download_file(url, creds, path)
Franziska Koehn's avatar
Franziska Koehn committed
70
71
    requests_lock.release()
    cb(*cb_args)
72

73
def download_file(url, creds, path):
Franziska Koehn's avatar
Franziska Koehn committed
74
75
76
77
78
79
80
81
82
    """
    Downloads a file.

    **Parameters**
        :url: host/REST-API with filled values
        :creds: credentials (including user-name and -password)
        :path: folder where the downloaded files will be saved
    """

Franziska Koehn's avatar
Franziska Koehn committed
83
84
85
86
    import requests
    from base64 import b64encode
    from requests.auth import HTTPBasicAuth

87
88
    if not path.endswith(".zip"):
        path += ".zip"
Franziska Koehn's avatar
Franziska Koehn committed
89

90
    user, passw = creds
Franziska Koehn's avatar
Franziska Koehn committed
91
92

    try:
93
        with open(path, 'wb') as handle:
Franziska Koehn's avatar
Franziska Koehn committed
94
95
96
97
98
99
100
101
            response = requests.get(url, stream=True, auth=HTTPBasicAuth(user, passw))
            if not response.ok:
                raise ValueError(response.status_code)
            for block in response.iter_content(1024):
                if not block:
                    break
                handle.write(block)
    except IOError as e:
102
        print "Error writing file %s, %s" % (path, e)
Franziska Koehn's avatar
Franziska Koehn committed
103
104
105
106
    except ValueError as e:
        print "Error downloading file %s, Status Code %s" % (url, e)


107
def search_for(host, root_element, constraints, search_fields, user, passw):
Franziska Koehn's avatar
Franziska Koehn committed
108
109
110
111
112
113
114
115
116
117
118
    """
    Does a search for given values. raises xsa -Exceptions

    **Parameters**
        :host: host-address
        :root_element: root-element of search
        :constraints: constraints of query
        :search_fields: fields which will be returned from server
        :user: user-name
        :passw:user-password
    """
119
120
    import xsa.errors as xsa_errors

121
122
    from pyxnat.core import errors
    from httplib2 import ServerNotFoundError
123
124
125
    from httplib import ResponseNotReady

    from tempfile import mkdtemp
126
    tmp_dir=mkdtemp()
127

128
    from pyxnat import Interface
129
    try:
130
131
132
133
134
        central = Interface(server=host,
                            user=user,
                            password=passw,
                            cachedir=tmp_dir)
    except IndexError as e:
Franziska Koehn's avatar
Franziska Koehn committed
135
        raise xsa_errors.ServerNotFoundError("Server not found, check your host-address.")
136

137
138
139
140
    result = []

    try:
        result =  central.select(root_element,search_fields).where(constraints)
141
142
143
    except errors.DatabaseError as e:
        if '401' in str(e):
            raise xsa_errors.UnauthorizedError("Unauthorizied attempt. Check your User and Password")
144
    except ServerNotFoundError:
145
146
147
148
149
150
        raise xsa_errors.ServerNotFoundError("Server not found, check your host-address.")
    except ResponseNotReady:
        raise xsa_errors.ResponseNotReady("Please check your Host-Address")

    if result == []:
        raise xsa_errors.QueryError("Please check your query.")
151
152
153
154
155
156
157
158
159
160
161

    try:
        central.disonnect()
    except AttributeError:
        print "can\'t close connection (wrong pyxnat version?)"

    try:
        from shutil import rmtree
        rmtree(tmp_dir)
    except:
        pass
162

163
    return result