6
6
from .blob import unpack
7
7
from . import DataJointError
8
8
from . import key as PRIMARY_KEY
9
+ import warnings
9
10
10
11
11
12
def update_dict (d1 , d2 ):
@@ -25,9 +26,13 @@ def __init__(self, arg):
25
26
26
27
def copy (self ):
27
28
"""
29
+ DEPRECATED
30
+
28
31
Creates and returns a copy of this object
29
32
:return: copy FetchBase derivatives
30
33
"""
34
+ warnings .warn ('Use of `copy` on `fetch` object is deprecated' , stacklevel = 2 )
35
+
31
36
return self .__class__ (self )
32
37
33
38
def _initialize_behavior (self ):
@@ -37,9 +42,15 @@ def _initialize_behavior(self):
37
42
@property
38
43
def squeeze (self ):
39
44
"""
45
+ DEPRECATED
46
+
40
47
Changes the state of the fetch object to squeeze the returned values as much as possible.
41
48
:return: a copy of the fetch object
42
49
"""
50
+
51
+ warnings .warn ('Use of `squeeze` on `fetch` object is deprecated. Please use `squeeze=True` keyword arguments '
52
+ 'in the call to `fetch`/`keys` instead' , stacklevel = 2 )
53
+
43
54
ret = self .copy ()
44
55
ret .ext_behavior ['squeeze' ] = True
45
56
return ret
@@ -60,6 +71,9 @@ def _prepare_attributes(item):
60
71
raise DataJointError ("Index must be a sequence or a string." )
61
72
return item , attributes
62
73
74
+ def __len__ (self ):
75
+ return len (self ._relation )
76
+
63
77
64
78
65
79
@@ -76,6 +90,8 @@ def _initialize_behavior(self):
76
90
77
91
def order_by (self , * args ):
78
92
"""
93
+ DEPRECATED
94
+
79
95
Changes the state of the fetch object to order the results by a particular attribute.
80
96
The commands are handed down to mysql.
81
97
:param args: the attributes to sort by. If DESC is passed after the name, then the order is descending.
@@ -85,6 +101,8 @@ def order_by(self, *args):
85
101
>>> my_relation.fetch.order_by('language', 'name DESC')
86
102
87
103
"""
104
+ warnings .warn ('Use of `order_by` on `fetch` object is deprecated. Please use `order_by` keyword arguments in '
105
+ 'the call to `fetch`/`keys` instead' , stacklevel = 2 )
88
106
self = Fetch (self )
89
107
if len (args ) > 0 :
90
108
self .sql_behavior ['order_by' ] = args
@@ -93,71 +111,103 @@ def order_by(self, *args):
93
111
@property
94
112
def as_dict (self ):
95
113
"""
114
+ DEPRECATED
115
+
96
116
Changes the state of the fetch object to return dictionaries.
97
117
:return: a copy of the fetch object
98
118
Example:
99
119
100
120
>>> my_relation.fetch.as_dict()
101
121
102
122
"""
123
+ warnings .warn ('Use of `as_dict` on `fetch` object is deprecated. Please use `as_dict` keyword arguments in the '
124
+ 'call to `fetch`/`keys` instead' , stacklevel = 2 )
103
125
ret = Fetch (self )
104
126
ret .sql_behavior ['as_dict' ] = True
105
127
return ret
106
128
107
129
def limit (self , limit ):
108
130
"""
131
+ DEPRECATED
132
+
109
133
Limits the number of items fetched.
110
134
111
135
:param limit: limit on the number of items
112
136
:return: a copy of the fetch object
113
137
"""
138
+ warnings .warn ('Use of `limit` on `fetch` object is deprecated. Please use `limit` keyword arguments in '
139
+ 'the call to `fetch`/`keys` instead' , stacklevel = 2 )
114
140
ret = Fetch (self )
115
141
ret .sql_behavior ['limit' ] = limit
116
142
return ret
117
143
118
144
def offset (self , offset ):
119
145
"""
146
+ DEPRECATED
147
+
120
148
Offsets the number of itms fetched. Needs to be applied with limit.
121
149
122
150
:param offset: offset
123
151
:return: a copy of the fetch object
124
152
"""
153
+
154
+ warnings .warn ('Use of `offset` on `fetch` object is deprecated. Please use `offset` keyword arguments in '
155
+ 'the call to `fetch`/`keys` instead' , stacklevel = 2 )
125
156
ret = Fetch (self )
126
157
if ret .sql_behavior ['limit' ] is None :
127
158
warnings .warn ('You should supply a limit together with an offset,' )
128
159
ret .sql_behavior ['offset' ] = offset
129
160
return ret
130
161
131
- def __call__ (self , ** kwargs ):
162
+ def __call__ (self , * attrs , * *kwargs ):
132
163
"""
133
164
Fetches the relation from the database table into an np.array and unpacks blob attributes.
134
165
166
+ :param attrs: OPTIONAL. one or more attributes to fetch. If not provided, the call will return
167
+ all attributes of this relation. If provided, returns tuples with an entry for each attribute.
135
168
:param offset: the number of tuples to skip in the returned result
136
169
:param limit: the maximum number of tuples to return
137
170
:param order_by: the list of attributes to order the results. No ordering should be assumed if order_by=None.
138
171
:param as_dict: returns a list of dictionaries instead of a record array
139
172
:return: the contents of the relation in the form of a structured numpy.array
140
173
"""
174
+ # if 'order_by' passed in a string, make into list
175
+ if isinstance (kwargs .get ('order_by' ), str ):
176
+ kwargs ['order_by' ] = [kwargs ['order_by' ]]
177
+
141
178
sql_behavior = update_dict (self .sql_behavior , kwargs )
142
179
ext_behavior = update_dict (self .ext_behavior , kwargs )
180
+ total_behavior = dict (sql_behavior )
181
+ total_behavior .update (ext_behavior )
143
182
144
183
unpack_ = partial (unpack , squeeze = ext_behavior ['squeeze' ])
145
184
146
185
if sql_behavior ['limit' ] is None and sql_behavior ['offset' ] is not None :
147
186
warnings .warn ('Offset set, but no limit. Setting limit to a large number. '
148
187
'Consider setting a limit explicitly.' )
149
188
sql_behavior ['limit' ] = 2 * len (self ._relation )
150
- cur = self ._relation .cursor (** sql_behavior )
151
- heading = self ._relation .heading
152
- if sql_behavior ['as_dict' ]:
153
- ret = [OrderedDict ((name , unpack_ (d [name ]) if heading [name ].is_blob else d [name ])
154
- for name in heading .names )
155
- for d in cur .fetchall ()]
156
- else :
157
- ret = list (cur .fetchall ())
158
- ret = np .array (ret , dtype = heading .as_dtype )
159
- for blob_name in heading .blobs :
160
- ret [blob_name ] = list (map (unpack_ , ret [blob_name ]))
189
+
190
+ if len (attrs ) == 0 : # fetch all attributes
191
+ cur = self ._relation .cursor (** sql_behavior )
192
+ heading = self ._relation .heading
193
+ if sql_behavior ['as_dict' ]:
194
+ ret = [OrderedDict ((name , unpack_ (d [name ]) if heading [name ].is_blob else d [name ])
195
+ for name in heading .names )
196
+ for d in cur .fetchall ()]
197
+ else :
198
+ ret = list (cur .fetchall ())
199
+ ret = np .array (ret , dtype = heading .as_dtype )
200
+ for blob_name in heading .blobs :
201
+ ret [blob_name ] = list (map (unpack_ , ret [blob_name ]))
202
+
203
+ else : # if list of attributes provided
204
+ attributes = [a for a in attrs if a is not PRIMARY_KEY ]
205
+ result = self ._relation .proj (* attributes ).fetch (** total_behavior )
206
+ return_values = [
207
+ list (to_dicts (result [self ._relation .primary_key ]))
208
+ if attribute is PRIMARY_KEY else result [attribute ]
209
+ for attribute in attrs ]
210
+ ret = return_values [0 ] if len (attrs ) == 1 else return_values
161
211
162
212
return ret
163
213
@@ -193,6 +243,8 @@ def keys(self, **kwargs):
193
243
194
244
def __getitem__ (self , item ):
195
245
"""
246
+ DEPRECATED
247
+
196
248
Fetch attributes as separate outputs.
197
249
datajoint.key is a special value that requests the entire primary key
198
250
:return: tuple with an entry for each element of item
@@ -201,6 +253,10 @@ def __getitem__(self, item):
201
253
>>> a, b = relation['a', 'b']
202
254
>>> a, b, key = relation['a', 'b', datajoint.key]
203
255
"""
256
+
257
+ warnings .warn ('Use of `rel.fetch[a, b]` notation is deprecated. Please use `rel.fetch(a, b) for equivalent '
258
+ 'result' , stacklevel = 2 )
259
+
204
260
behavior = dict (self .sql_behavior )
205
261
behavior .update (self .ext_behavior )
206
262
@@ -222,8 +278,7 @@ def __repr__(self):
222
278
["\t {key}:\t {value}" .format (key = k , value = str (v )) for k , v in behavior .items () if v is not None ])
223
279
return repr_str
224
280
225
- def __len__ (self ):
226
- return len (self ._relation )
281
+
227
282
228
283
229
284
class Fetch1 (FetchBase , Callable ):
@@ -233,28 +288,43 @@ class Fetch1(FetchBase, Callable):
233
288
:param relation: relation the fetch object fetches data from
234
289
"""
235
290
236
- def __call__ (self , ** kwargs ):
291
+ def __call__ (self , * attrs , * *kwargs ):
237
292
"""
238
293
This version of fetch is called when self is expected to contain exactly one tuple.
239
294
:return: the one tuple in the relation in the form of a dict
240
295
"""
241
296
heading = self ._relation .heading
242
297
243
- #sql_behavior = update_dict(self.sql_behavior, kwargs)
298
+ # sql_behavior = update_dict(self.sql_behavior, kwargs)
244
299
ext_behavior = update_dict (self .ext_behavior , kwargs )
245
300
246
301
unpack_ = partial (unpack , squeeze = ext_behavior ['squeeze' ])
247
302
303
+ if len (attrs ) == 0 : # fetch all attributes
304
+ cur = self ._relation .cursor (as_dict = True )
305
+ ret = cur .fetchone ()
306
+ if not ret or cur .fetchone ():
307
+ raise DataJointError ('fetch1 should only be used for relations with exactly one tuple' )
308
+ ret = OrderedDict ((name , unpack_ (ret [name ]) if heading [name ].is_blob else ret [name ])
309
+ for name in heading .names )
310
+ else :
311
+ attributes = [a for a in attrs if a is not PRIMARY_KEY ]
312
+ result = self ._relation .proj (* attributes ).fetch (** ext_behavior )
313
+ if len (result ) != 1 :
314
+ raise DataJointError ('fetch1 should only return one tuple. %d tuples were found' % len (result ))
315
+ return_values = tuple (
316
+ next (to_dicts (result [self ._relation .primary_key ]))
317
+ if attribute is PRIMARY_KEY else result [attribute ][0 ]
318
+ for attribute in attrs )
319
+ ret = return_values [0 ] if len (attrs ) == 1 else return_values
320
+
248
321
249
- cur = self ._relation .cursor (as_dict = True )
250
- ret = cur .fetchone ()
251
- if not ret or cur .fetchone ():
252
- raise DataJointError ('fetch1 should only be used for relations with exactly one tuple' )
253
- return OrderedDict ((name , unpack_ (ret [name ]) if heading [name ].is_blob else ret [name ])
254
- for name in heading .names )
322
+ return ret
255
323
256
324
def __getitem__ (self , item ):
257
325
"""
326
+ DEPRECATED
327
+
258
328
Fetch attributes as separate outputs.
259
329
datajoint.key is a special value that requests the entire primary key
260
330
:return: tuple with an entry for each element of item
@@ -265,10 +335,13 @@ def __getitem__(self, item):
265
335
>>> a, b, key = relation['a', 'b', datajoint.key]
266
336
267
337
"""
338
+ warnings .warn ('Use of `rel.fetch[a, b]` notation is deprecated. Please use `rel.fetch(a, b) for equivalent '
339
+ 'result' , stacklevel = 2 )
340
+
268
341
behavior = dict (self .sql_behavior )
269
342
behavior .update (self .ext_behavior )
270
343
271
- single_output = isinstance (item , str ) or item is PRIMARY_KEY or isinstance ( item , int )
344
+ single_output = isinstance (item , str ) or item is PRIMARY_KEY
272
345
item , attributes = self ._prepare_attributes (item )
273
346
result = self ._relation .proj (* attributes ).fetch (** behavior )
274
347
if len (result ) != 1 :
0 commit comments