deriva 1.7.1__py3-none-any.whl → 1.7.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -448,14 +448,8 @@ class HatracStore(DerivaBinding):
448
448
  """Retrieve a namespace.
449
449
  """
450
450
  headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
451
- try:
452
- resp = self.get(namespace_path, headers)
453
- namespaces = resp.json()
454
- return namespaces
455
- except requests.HTTPError as e:
456
- if e.response.status_code == requests.codes.not_found:
457
- return None
458
- raise
451
+ resp = self.get(namespace_path, headers)
452
+ return resp.json()
459
453
 
460
454
  def create_namespace(self, namespace_path, parents=True):
461
455
  """Create a namespace.
@@ -485,18 +479,13 @@ class HatracStore(DerivaBinding):
485
479
  url += '/' + urlquote(role)
486
480
  elif role:
487
481
  raise ValueError('Do not specify "role" if "access" mode is not specified.')
488
- try:
489
- resp = self.get(url, headers)
490
- if role:
491
- return {access: [role]}
492
- elif access:
493
- return {access: resp.json()}
494
- else:
495
- return resp.json()
496
- except requests.HTTPError as e:
497
- if e.response.status_code == requests.codes.not_found:
498
- return None
499
- raise
482
+ resp = self.get(url, headers)
483
+ if role:
484
+ return {access: [role]}
485
+ elif access:
486
+ return {access: resp.json()}
487
+ else:
488
+ return resp.json()
500
489
 
501
490
  def set_acl(self, resource_name, access, roles, add_role=False):
502
491
  """Set the object or namespace ACL resource.
deriva/core/mmo.py ADDED
@@ -0,0 +1,379 @@
1
+ """Model management operations.
2
+ """
3
+ import logging
4
+ from collections import namedtuple
5
+
6
+ from deriva.core import tag as tags
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+ Match = namedtuple('Match', 'anchor tag context container mapping')
11
+
12
+ __search_box__ = 'search-box'
13
+
14
+
15
+ def replace(model, symbol, replacement):
16
+ """Replaces `symbol` with `replacement` where symbol is found in mappings.
17
+
18
+ See the 'find' function for notes on what are 'symbols' and how symbols are found in the model.
19
+
20
+ The `symbol` and its `replacement` must be of the same type (i.e., columns or constraints). For columns, only the
21
+ column name may differ. For constraints, the whole name or just the schema part may be replaced.
22
+ """
23
+ logger.debug(f'Replacing symbol "{symbol}" with "{replacement}".')
24
+ assert len(symbol) == len(replacement), "symbol and replacement must have same length"
25
+ assert len(symbol) != 3 or symbol[0:2] == replacement[0:2], "column symbols may only differ in the column name"
26
+
27
+ # step 1: find all matches
28
+ for anchor, tag, context, container, mapping in find(model, symbol):
29
+ # step 2: replace symbol in each matching mapping found in model
30
+
31
+ # case: mapping is a `str` column name in a vizcol context _or_ a source-defs columns `list`
32
+ if isinstance(mapping, str) and isinstance(container, list):
33
+ assert mapping == symbol[-1], "expected mapping to match the column name"
34
+ for idx, val in enumerate(container):
35
+ if val == mapping:
36
+ container[idx] = replacement[-1]
37
+
38
+ # case: mapping is a `dict` pseudo-column and `source` is a `str` column name
39
+ elif isinstance(mapping, dict) and isinstance(mapping.get('source'), str):
40
+ assert mapping['source'] == symbol[-1], "expected pseudo-column `source` to match the column name"
41
+ mapping['source'] = replacement[-1]
42
+
43
+ # case: mapping is a `dict` pseudo-column and `source` is a source path `list`
44
+ elif isinstance(mapping, dict) and isinstance(mapping.get('source'), list):
45
+ _replace_symbol_in_source_path(anchor, mapping['source'], symbol, replacement)
46
+
47
+ # case: mapping is a `str` sourcekey in a source-defs source `dict`
48
+ elif isinstance(mapping, str) and isinstance(container, dict):
49
+ assert mapping in container, "expected to find sourcekey `mapping` in sources `container`"
50
+ assert isinstance(container[mapping], dict), "expected `container[mapping]` to be a source definition dict"
51
+ _replace_symbol_in_source_path(anchor, container[mapping]['source'], symbol, replacement)
52
+
53
+ # case: mapping is a `list` constraint name in a vizcol or vizfkey context _or_ a source-defs fkeys `list`
54
+ elif isinstance(mapping, list) and isinstance(container, list):
55
+ assert _is_constraint_match(mapping, symbol), "expected mapping to match the constraint name"
56
+ for idx, val in enumerate(container):
57
+ if val == mapping:
58
+ container[idx] = _rewrite_constraint_name(val, replacement)
59
+ else:
60
+ logger.warning(f'Unhandled case for replace operation')
61
+
62
+
63
+ def prune(model, symbol):
64
+ """Prunes mappings from a model where symbol found in mapping.
65
+
66
+ See the 'find' function for notes on what are 'symbols' and how symbols are found in the model.
67
+
68
+ **Note on pruning source definitions**
69
+ When this methods prunes a `source-definitions` entry from the model, it will also prune
70
+ `visible-{columns|foreign-keys}` that reference its `sourcekey` directly or as a "path prefix" in a pseudo-column
71
+ definition. It will prune any references found in `wait_for` display attributes. Also, it will recurse over the
72
+ source definitions repeating the above pruning for each sourcekey dependent on the originally affected sourcekey.
73
+ """
74
+ logger.debug(f'Pruning symbol "{symbol}".')
75
+ # step 1: find all matches
76
+ for anchor, tag, context, container, mapping in find(model, symbol):
77
+ # step 2: remove mapping from model, for each mapping found
78
+ if tag in [tags.visible_columns, tags.visible_foreign_keys]:
79
+ container.remove(mapping)
80
+ elif tag == tags.source_definitions:
81
+ logger.debug(f'Removing "{tag}" mapping "{mapping}" from container "{container}".')
82
+ if isinstance(container, list):
83
+ # step 2.a. match found in 'columns' or 'fkeys' lists, remove item and continue
84
+ container.remove(mapping)
85
+ else:
86
+ # step 2.b. match found in 'sources' dictionary, remove then search for dependencies
87
+ assert isinstance(container, dict), "Expected dictionary typed container"
88
+ del container[mapping]
89
+
90
+ # step 2.c. find all dependencies on sourcekey in anchor's annotations and remove them
91
+ for match in _find_sourcekey(anchor, mapping):
92
+ logger.debug(f'Removing "{mapping}" sourcekey dependency; mapping "{match.mapping}" from "{match.tag}".')
93
+ if match.tag in [tags.visible_columns, tags.visible_foreign_keys]:
94
+ match.container.remove(match.mapping)
95
+ elif match.tag == tags.citation:
96
+ del match.anchor.annotations[match.tag]
97
+ elif match.tag == tags.source_definitions:
98
+ del match.container[match.mapping]
99
+ else:
100
+ logger.warning(f'Unexpected tag "{match.tag}".')
101
+ else:
102
+ logger.warning(f'Unhandled tag "{tag}".')
103
+
104
+
105
+ def find(model, symbol):
106
+ """Finds mappings within a model where the mapping contains a given symbol.
107
+
108
+ Searches the following annotation tags:
109
+ - source-definitions
110
+ - visible-columns
111
+ - visible-foreign-keys
112
+
113
+ Presently, there are two forms of symbols:
114
+ - constraint: `[schema_name, constraint_name]` may refer to a key or fkey. If `constraint_name` is None then the
115
+ match is based only on `schema_name`
116
+ - column: `[schema_name, table_name, column_name]`
117
+
118
+ returns: list containing Match(anchor, tag, context, container, mapping) tuples
119
+ - anchor: the model object that anchors the mapping
120
+ - tag: the annotation tag where the mapping was found
121
+ - context: the annotation context where the mapping was found
122
+ - container: the parent container of the mapping
123
+ - mapping: the mapping in which the symbol was found
124
+ """
125
+ # [NOTE] If/when table must be supported, the ambiguity could be addressed as:
126
+ # - table [schema_name, table_name, None] where the final None in the column category implies that we are removing
127
+ # not a single column but the whole table (and hence all of its columns)
128
+ matches = []
129
+
130
+ # At present, mappings only reside in model elements: table and column.
131
+ for schema in model.schemas.values():
132
+ for table in schema.tables.values():
133
+ for tag in table.annotations:
134
+
135
+ # case: visible-columns or visible-foreign-keys
136
+ if tag == tags.visible_columns or tag == tags.visible_foreign_keys:
137
+ for context in table.annotations[tag]:
138
+ if context == 'filter':
139
+ vizsrcs = table.annotations[tag][context].get('and', [])
140
+ else:
141
+ vizsrcs = table.annotations[tag][context]
142
+
143
+ for vizsrc in vizsrcs: # vizsrc is a vizcol or vizfkey entry
144
+ # case: constraint form of vizsrc
145
+ if isinstance(vizsrc, list) \
146
+ and _is_constraint_match(vizsrc, symbol):
147
+ matches.append(Match(table, tag, context, vizsrcs, vizsrc))
148
+ # case: pseudo-column form of vizsrc
149
+ elif isinstance(vizsrc, dict) and 'source' in vizsrc \
150
+ and _is_symbol_in_source(table, vizsrc['source'], symbol):
151
+ matches.append(Match(table, tag, context, vizsrcs, vizsrc))
152
+ # case: column form of vizsrc
153
+ elif isinstance(vizsrc, str) \
154
+ and [table.schema.name, table.name, vizsrc] == symbol:
155
+ matches.append(Match(table, tag, context, vizsrcs, vizsrc))
156
+
157
+ # case: source-definitions
158
+ elif tag == tags.source_definitions:
159
+ # search 'columns'
160
+ cols = table.annotations[tag].get('columns')
161
+ if isinstance(cols, list) \
162
+ and len(symbol) == 3 \
163
+ and [table.schema.name, table.name] == symbol[0:2] \
164
+ and symbol[-1] in cols:
165
+ matches.append(Match(table, tag, 'columns', cols, symbol[-1]))
166
+
167
+ # search 'fkeys'
168
+ fkeys = table.annotations[tag].get('fkeys')
169
+ if isinstance(fkeys, list):
170
+ for fkey in fkeys:
171
+ if _is_constraint_match(fkey, symbol):
172
+ matches.append(Match(table, tag, 'fkeys', fkeys, fkey))
173
+
174
+ # search 'sources'
175
+ sources = table.annotations[tag].get('sources')
176
+ for sourcekey in sources:
177
+ if _is_symbol_in_source(table, sources[sourcekey].get('source', []), symbol):
178
+ matches.append(Match(table, tag, 'sources', sources, sourcekey))
179
+
180
+ # search 'search-box'
181
+ search_box = table.annotations[tag].get(__search_box__)
182
+ if isinstance(search_box, dict) and isinstance(search_box.get('or'), list):
183
+ for search_col in search_box['or']:
184
+ if _is_symbol_in_source(table, search_col.get('source'), symbol):
185
+ matches.append(Match(table, tag, __search_box__, search_box['or'], search_col))
186
+
187
+ return matches
188
+
189
+
190
+ def _is_constraint_match(constraint_name, symbol):
191
+ """Tests if the constraint name matches the given symbol.
192
+
193
+ :param constraint_name: a constraint name pair
194
+ :param symbol: either a constraint name part or a schema name
195
+ """
196
+ if not (isinstance(constraint_name, list) and len(constraint_name) == 2):
197
+ # case: malformed constraint name
198
+ return False
199
+ if not isinstance(symbol, list) or len(symbol) != 2:
200
+ # case: symbol not a constraint name
201
+ return False
202
+ elif symbol[1]:
203
+ # case: symbol is a complete constraint name
204
+ return constraint_name == symbol
205
+ else:
206
+ # case: symbol is a schema name only
207
+ return constraint_name[0] == symbol[0]
208
+
209
+
210
+ def _is_symbol_in_source(table, source, symbol):
211
+ """Finds symbol in a source mapping.
212
+ """
213
+
214
+ # case: source is a column name
215
+ if isinstance(source, str):
216
+ return [table.schema.name, table.name, source] == symbol
217
+
218
+ # case: source is a path, symbol is a constraint
219
+ if isinstance(source, list) and isinstance(symbol, list):
220
+
221
+ # case: symbol is a constraint
222
+ if len(symbol) == 2:
223
+ for pathelem in source:
224
+ if isinstance(pathelem, dict):
225
+ constraint_name = pathelem.get('inbound') or pathelem.get('outbound')
226
+ if _is_constraint_match(constraint_name, symbol):
227
+ return True
228
+
229
+ # case: symbol is a column name
230
+ # -- start with column in path and test if matches last value of source path
231
+ # -- then determine if the table reference matches (last fkey in/out points to correct table)
232
+ # -- isinstance(source[-1], str) and source[-1] == symbol[-1]
233
+ # -- isinstance(source[-2], dict) -- ie, a constraint
234
+ # -- lookup fkey = model.fkeys(*source[-2].get('inbound' or 'outbound')
235
+ # -- if 'inbound' and fkey.table == symbol's table
236
+ # -- if 'outbound' and fkey.pk_table == symbol's table
237
+ if len(symbol) == 3 \
238
+ and len(source) >= 2 \
239
+ and source[-1] == symbol[-1] \
240
+ and isinstance(source[-2], dict):
241
+
242
+ # case: inbound fkey
243
+ if 'inbound' in source[-2]:
244
+ fkey = table.schema.model.fkey(source[-2]['inbound'])
245
+ return [fkey.table.schema.name, fkey.table.name] == symbol[0:2]
246
+
247
+ # case: outbound fkey
248
+ elif 'outbound' in source[-2]:
249
+ fkey = table.schema.model.fkey(source[-2]['outbound'])
250
+ return [fkey.pk_table.schema.name, fkey.pk_table.name] == symbol[0:2]
251
+
252
+ return False
253
+
254
+
255
+ def _find_sourcekey(table, sourcekey):
256
+ """Find usages of `sourcekey` in `table`'s annotations.
257
+ """
258
+ matches = []
259
+
260
+ # case: source-definitions
261
+ # sources, <sourcekey>, display, wait_for (markdown_pattern)
262
+ # source, [0], sourcekey
263
+ #
264
+ # case: citation
265
+ # wait_for (*_pattern)
266
+ #
267
+ # case: visible-columns or visible-foreign-keys
268
+ # <context>, <pseudocolumn>, sourcekey
269
+ # source, [0], sourcekey
270
+ # display, wait_for (markdown_pattern)
271
+
272
+ # step 1: find all references to sourcekey in source-definitions (recursively)
273
+ sources = table.annotations[tags.source_definitions].get('sources', {})
274
+ sourcekeys = _find_dependent_sourcekeys(sourcekey, sources)
275
+ matches.extend([
276
+ Match(table, tags.source_definitions, None, sources, sourcekey)
277
+ for sourcekey in sourcekeys
278
+ ])
279
+
280
+ # step 2: find all other references to the set of {sourcekeys} | {sourcekey} found in first step
281
+ sourcekeys.add(sourcekey)
282
+
283
+ # 2.a.: find sourcekey in citations
284
+ citation = table.annotations.get(tags.citation)
285
+ if citation:
286
+ for sourcekey in sourcekeys:
287
+ if sourcekey in citation.get('wait_for', []):
288
+ matches.append(Match(table, tags.citation, None, None, None))
289
+ break
290
+
291
+ # 2.b.: find sourcekey in visible-columns or visible-foreign-keys
292
+ for tag in (tags.visible_columns, tags.visible_foreign_keys):
293
+ for context in table.annotations.get(tag, {}):
294
+ vizcols = table.annotations[tag][context]
295
+ for vizcol in vizcols:
296
+ for sourcekey in sourcekeys:
297
+ if _is_dependent_on_sourcekey(sourcekey, vizcol):
298
+ matches.append(Match(table, tag, context, vizcols, vizcol))
299
+
300
+ return matches
301
+
302
+
303
+ def _find_dependent_sourcekeys(sourcekey, sources, deps=None):
304
+ """Find 'sourcekey' dependencies in 'sources' source definitions.
305
+ """
306
+ # initialize deps to empty set
307
+ deps = deps or set()
308
+
309
+ # remove self from sources
310
+ if sourcekey in sources:
311
+ sources = sources.copy()
312
+ sources.pop(sourcekey)
313
+
314
+ # test if each 'candidate' source is dependent on this 'sourcekey'
315
+ for candidate in sources:
316
+ # case: source 'search-box', need to check sources in its `or` block, but do not recurse
317
+ if candidate == __search_box__:
318
+ for source_def in sources[__search_box__].get('or', []):
319
+ if _is_dependent_on_sourcekey(sourcekey, source_def):
320
+ # add 'search-box' to deps, continue
321
+ deps.add(__search_box__)
322
+ break
323
+ # case: all other sources
324
+ if _is_dependent_on_sourcekey(sourcekey, sources[candidate]):
325
+ # add to deps
326
+ deps.add(candidate)
327
+ # union with deps of the candidate
328
+ deps.union(_find_dependent_sourcekeys(candidate, sources, deps=deps))
329
+
330
+ return deps
331
+
332
+
333
+ def _is_dependent_on_sourcekey(sourcekey, source_def):
334
+ """Tests if 'source_def' is dependent on 'sourcekey'.
335
+ """
336
+ # case: source_def is not a pseudo-column
337
+ if not isinstance(source_def, dict):
338
+ return False
339
+ # case: sourcekey referenced directly
340
+ if sourcekey == source_def.get('sourcekey'):
341
+ return True
342
+ # case: sourcekey in path prefix
343
+ if not isinstance(source_def.get('source'), str) and sourcekey == source_def.get('source', [{}])[0].get('sourcekey'):
344
+ return True
345
+ # case: sourcekey in wait_for
346
+ if sourcekey in source_def.get('display', {}).get('wait_for', []):
347
+ return True
348
+ # not dependent
349
+ return False
350
+
351
+
352
+ def _rewrite_constraint_name(constraint_name, replacement):
353
+ """Rewrites constraint name according to replacement symbol.
354
+ """
355
+ return [
356
+ replacement[0],
357
+ replacement[1] if replacement[1] else constraint_name[1]
358
+ ]
359
+
360
+
361
+ def _replace_symbol_in_source_path(anchor, source, symbol, replacement):
362
+ """Replaces `symbol` with `replacement` in `source`.
363
+ """
364
+ assert isinstance(source, list), 'expected source to be a list'
365
+ assert source, 'expected source to be non-empty'
366
+
367
+ if len(symbol) == 3: # case: column symbol replacement
368
+ assert source[-1] == symbol[-1], "expected source path to terminate in symbol column name"
369
+ source[-1] = replacement[-1]
370
+
371
+ if len(symbol) == 2: # case: constraint name replacement
372
+ assert _is_symbol_in_source(anchor, source, symbol), "expected to find symbol in mapping source"
373
+ for i, pathelem in enumerate(source):
374
+ if not isinstance(pathelem, dict):
375
+ continue
376
+ for direction in ('inbound', 'outbound'):
377
+ if _is_constraint_match(pathelem.get(direction), symbol):
378
+ pathelem[direction] = _rewrite_constraint_name(pathelem[direction], replacement)
379
+ break
@@ -52,7 +52,7 @@ class GlobusAuthUtil:
52
52
  client_id = kwargs.get("client_id")
53
53
  client_secret = kwargs.get("client_secret")
54
54
  if not (client_id and client_secret):
55
- cred_file = kwargs.get("credential_file", CLIENT_CRED_FILE)
55
+ cred_file = kwargs.get("credential_file", CLIENT_CRED_FILE) or CLIENT_CRED_FILE
56
56
  if os.path.isfile(cred_file):
57
57
  creds = read_config(cred_file)
58
58
  if creds:
@@ -60,6 +60,8 @@ class GlobusAuthUtil:
60
60
  if client:
61
61
  client_id = client.get('client_id')
62
62
  client_secret = client.get('client_secret')
63
+ else:
64
+ logging.warning("No Globus client credential file found at: %s" % cred_file)
63
65
 
64
66
  if not (client_id and client_secret):
65
67
  logging.warning("Client ID and secret not specified and/or could not be determined.")
@@ -128,12 +128,12 @@ class Boto3UploadPostProcessor(UploadPostProcessor):
128
128
  object_qualifier = compute_hashes(
129
129
  identity.encode() if identity else
130
130
  "anon-" + self.envars.get("request_ip", "unknown").encode(), hashes=['md5'])['md5'][0]
131
- if not stob(self.parameters.get("overwrite", "False")):
131
+ if not stob(self.parameters.get("overwrite", False)):
132
132
  now = datetime.datetime.now()
133
133
  object_qualifier = "/".join([object_qualifier, now.strftime("%Y-%m-%d_%H.%M.%S")])
134
134
 
135
135
  for k, v in self.outputs.items():
136
- object_name = "/".join([self.path, object_qualifier, k])
136
+ object_name = "/".join([self.path, object_qualifier, k]).lstrip("/")
137
137
  file_path = v[LOCAL_PATH_KEY]
138
138
  acl = self.parameters.get("acl", "private")
139
139
  signed_url = stob(self.parameters.get("signed_url", acl == "public-read"))
@@ -138,7 +138,8 @@ class BaseQueryProcessor(BaseProcessor):
138
138
  if not (urlparts.scheme and urlparts.netloc):
139
139
  urlparts = urlsplit(self.catalog.get_server_uri())
140
140
  server_uri = urlparts.scheme + "://" + urlparts.netloc
141
- url = ''.join([server_uri, url])
141
+ sep = "/" if not url.startswith("/") else ""
142
+ url = ''.join([server_uri, sep, url])
142
143
 
143
144
  return url
144
145
 
@@ -233,8 +233,11 @@ class DerivaUpload(object):
233
233
  self.credentials = credentials
234
234
  self.catalog.set_credentials(self.credentials, host)
235
235
  self.store.set_credentials(self.credentials, host)
236
- attributes = self.catalog.get_authn_session().json()
237
- self.identity = attributes.get("client", self.identity)
236
+ try:
237
+ attributes = self.catalog.get_authn_session().json()
238
+ self.identity = attributes.get("client", self.identity)
239
+ except Exception as e:
240
+ logger.warning("Unable to determine user identity: %s" % e)
238
241
 
239
242
  def setConfig(self, config_file):
240
243
  if not config_file:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: deriva
3
- Version: 1.7.1
3
+ Version: 1.7.4
4
4
  Summary: Python APIs and CLIs (Command-Line Interfaces) for the DERIVA platform.
5
5
  Home-page: https://github.com/informatics-isi-edu/deriva-py
6
6
  Author: USC Information Sciences Institute, Informatics Systems Research Division
@@ -1,24 +1,25 @@
1
1
  deriva/__init__.py,sha256=h-QyvMVzDNpT3jyVskcSbUVFXxGCRxieFPrvTveZG9k,64
2
2
  deriva/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  deriva/config/acl_config.py,sha256=yZ0g_Cwv1MZXajUP2sVbc928XakUDu5Q97w9aK3VCCE,23946
4
- deriva/config/annotation_config.py,sha256=DQHPn4bKVYUxWPKyHkPfwLbdtOuBWpIyW_Uln-p10K0,11732
4
+ deriva/config/annotation_config.py,sha256=sWcJnRfS5vcb85IdUOd420cmFHRyb4br5OxLCOssbec,11714
5
5
  deriva/config/annotation_validate.py,sha256=ZN0jq6As49hfsAmWONUxAStqFG9TeYzvCmRU9TQ-zD8,5228
6
6
  deriva/config/base_config.py,sha256=Y5sFotuAWWyo-LZvzbzVY2ZDaC-zhwbMXusgBF1OJYM,20724
7
7
  deriva/config/dump_catalog_annotations.py,sha256=QzaWDLfWIAQ0eWVV11zeceWgwDBOYIePJnDQgRydwTE,9362
8
- deriva/config/rollback_annotation.py,sha256=EMVpuaMh2VaXXoHhsr3ldc7g7e92ngszEswdGNEmGFQ,3020
8
+ deriva/config/rollback_annotation.py,sha256=vqrIcen-KZX8LDpu2OVNivzIHpQoQgWkZAChZJctvtk,3015
9
9
  deriva/config/examples/group_owner_policy.json,sha256=8v3GWM1F_BWnYD9x_f6Eo4kBDvyy8g7mRqujfoEKLNc,2408
10
10
  deriva/config/examples/self_serve_policy.json,sha256=pW-cqWz4rJNNXwY4eVZFkQ8gKCHclC9yDa22ylfcDqY,1676
11
- deriva/core/__init__.py,sha256=e2yjmArOhvRrFnmJxgjd_BPYIhiYsTVeYXe3iVQIKaU,4945
11
+ deriva/core/__init__.py,sha256=KyMruBM9qoCK0JQQvwsIDhC6leQqFueAwqGlA7oYsZA,4945
12
12
  deriva/core/annotation.py,sha256=PkAkPkxX1brQsb8_drR1Qj5QjQA5mjkpXhkq9NuZ1g8,13432
13
13
  deriva/core/base_cli.py,sha256=EkLXOTeaFWUbPaYV-eLuLGga1PbkFVWi3Jjo-e_Vb-U,2681
14
14
  deriva/core/catalog_cli.py,sha256=-6Bo6GLWFWap7y3VxkzPs73HAe_XzRXIJMW-Ri84m3M,23273
15
- deriva/core/datapath.py,sha256=4Q3snZ-rBqQV5x7ZAfU7fWdVcmQYu-8Ma6a7DcOL6zQ,81306
15
+ deriva/core/datapath.py,sha256=w8LvPAd_DuknKxHc_YS6NUHhTY6XpCSkfa0m_xQUdZE,89068
16
16
  deriva/core/deriva_binding.py,sha256=_sA9HGrcVRqT-OhrneMDMOquyVOFOxLq3WzBQhasLIM,12970
17
17
  deriva/core/deriva_server.py,sha256=nsW3gwg1sIaHl3BTf-nL41AkSj3dEpcEBlatvjvN8CQ,200
18
- deriva/core/ermrest_catalog.py,sha256=B8XdzDScxad4PVUxRxT3GLUkV5vSsNnvMA5a76cUdsc,50817
19
- deriva/core/ermrest_model.py,sha256=opQunJOl4Vm62U5LBbO8w77dz9l11B0DvGDU6Sfe2FQ,85916
18
+ deriva/core/ermrest_catalog.py,sha256=_eqQg16i1aA95R99B7tLZxHWQlYk-rLpN_0zghfNWRc,54991
19
+ deriva/core/ermrest_model.py,sha256=OlG-TQ6VOwFKFwXzn-aVTErcd50-ZsqxVa4TyXQHoys,124919
20
20
  deriva/core/hatrac_cli.py,sha256=l9QmneLRHSMiG_z9S83ea0QGVhTS3Wq1KGPEKEDpecM,14522
21
- deriva/core/hatrac_store.py,sha256=t7gEsZ3SJqt1RefSGc3728PQoVs9E5UWEBNGGbbG6Bw,22582
21
+ deriva/core/hatrac_store.py,sha256=pRupabYZzXvf1iQTYmv0AME8n7KCkTCMfrojhl_JOTs,22178
22
+ deriva/core/mmo.py,sha256=dcB8akgsqbYMi22ClbVpOKVL6so8FjSDjSb6gP4_jFo,17852
22
23
  deriva/core/polling_ermrest_catalog.py,sha256=KsjiFqPQaHWnJZCVF5i77sdzfubqZHgMBbQ1p8V8D3s,10351
23
24
  deriva/core/schemas/app_links.schema.json,sha256=AxrkC2scxomM6N7jyjtdYA73BbZzPrmuqU8PYWe7okI,954
24
25
  deriva/core/schemas/asset.schema.json,sha256=rVQobTnTxPtC-HOQhzSjc9CHo43cK97rImYqnxSp5ZA,1287
@@ -44,7 +45,7 @@ deriva/core/schemas/visible_foreign_keys.schema.json,sha256=K-oa2qzj5EbmJCEyN6mN
44
45
  deriva/core/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
46
  deriva/core/utils/__init__.py,sha256=XSbGaWe44hebxYvoh5huFzZkMY6TSKPOCRSjUOvaY70,124
46
47
  deriva/core/utils/core_utils.py,sha256=5xUjJ-1QrPFKOiwfSWFDdH8Hm5a-AEhzCvy2GJPjx4A,19500
47
- deriva/core/utils/globus_auth_utils.py,sha256=M7u6rN1IeQDb3RRN6bM3YIJMitPEP3Usugp-cLgsAr8,55601
48
+ deriva/core/utils/globus_auth_utils.py,sha256=huPzKSr0d2NirpLzyp6CSyR1gIAdlRuP-X0jRo5W_p8,55732
48
49
  deriva/core/utils/hash_utils.py,sha256=JqUYVB3jXusCQYX9fkKmweUKBC0WQi8ZI2N8m-uKygQ,2299
49
50
  deriva/core/utils/mime_utils.py,sha256=ZT7pMjY2kQWBsgsGC3jY6kjfygdsIyiYW3BKNw_pPyg,1128
50
51
  deriva/core/utils/version_utils.py,sha256=HWNUQAZrPXu0oGjhG6gMNm3kWtfa3nR50vfH2uQxBA0,2954
@@ -65,11 +66,11 @@ deriva/transfer/download/processors/__init__.py,sha256=evLp36tZn-Z_AMshdfV3JJO8w
65
66
  deriva/transfer/download/processors/base_processor.py,sha256=R6IIHSa_euv4X2Dyhd8fvQAiVYDGJTWMQtPoukHQn-Q,3837
66
67
  deriva/transfer/download/processors/postprocess/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
68
  deriva/transfer/download/processors/postprocess/identifier_post_processor.py,sha256=rQVnh7A9n9l5zE0MqDMYTOdpA6Ku9enFLbzWwT6hKTg,5370
68
- deriva/transfer/download/processors/postprocess/transfer_post_processor.py,sha256=JYEXRiGdgbGEtJKt5BvjPMZb68tU0hzqtUGeQCuWeTc,7828
69
+ deriva/transfer/download/processors/postprocess/transfer_post_processor.py,sha256=8pSYicB-Yn_fONJcfZNGdaV8w6Zb7CiqnUMKZ9PAj94,7838
69
70
  deriva/transfer/download/processors/postprocess/url_post_processor.py,sha256=s68iIYqQSZHtbv4y-fCG8pjhApAeMEG6hYcKx2Pvf5Y,2745
70
71
  deriva/transfer/download/processors/query/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
72
  deriva/transfer/download/processors/query/bag_fetch_query_processor.py,sha256=tiQtfuy01YgOFFD5b_sP7TGjMnt0Jqcg2gp1KNWqeLE,5645
72
- deriva/transfer/download/processors/query/base_query_processor.py,sha256=oM1pbsbpnPV12h3FLtxo8Sp0OCUQYiRhg22AVqf4N50,10327
73
+ deriva/transfer/download/processors/query/base_query_processor.py,sha256=DGvYM4Ykwo5OYq2D-HKB2bYPuqhJMKdMQ8GGw7OCMz0,10393
73
74
  deriva/transfer/download/processors/query/file_download_query_processor.py,sha256=Hg1NbKsaGJh9cB86yIyL7Fm7ywSNVop837Dv8aFXUes,7257
74
75
  deriva/transfer/download/processors/transform/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
76
  deriva/transfer/download/processors/transform/base_transform_processor.py,sha256=Ddw5gsNpDANeuLvUaF4utp8psaxOtAzlgXtOg8gb-Pc,4109
@@ -85,7 +86,7 @@ deriva/transfer/restore/deriva_restore.py,sha256=s0h7cXit2USSdjrIfrj0dr7BJ0rrHHM
85
86
  deriva/transfer/restore/deriva_restore_cli.py,sha256=2ViZ1Lyl5ndXPKeJFCHHGnwzkg3DfHhTuRa_bN7eJm8,5603
86
87
  deriva/transfer/upload/__init__.py,sha256=4mlc_iUX-v7SpXzlCZmhxQtSiW5JeDGb2FX7bb1E6tY,304
87
88
  deriva/transfer/upload/__main__.py,sha256=hqnXtGpRqPthwpO6uvrnf_TQm7McheeyOt960hStSMY,340
88
- deriva/transfer/upload/deriva_upload.py,sha256=9NJbsPx1FANgGrCr5AP78AjtM41LJsanCJKEW4UH9ws,60376
89
+ deriva/transfer/upload/deriva_upload.py,sha256=GuQb_-PBKR0JstEifXqSOZpF1zTyaPLfM0PCDlu2Qw8,60500
89
90
  deriva/transfer/upload/deriva_upload_cli.py,sha256=-Q6xgiYabQziTQcMQdGNDAv-eLxCCHO-BCSo4umbDE4,5082
90
91
  deriva/transfer/upload/processors/__init__.py,sha256=sMM5xdJ82UIRdB1lGMKk7ft0BgtjS2oJ0sI4SQSqiIU,2481
91
92
  deriva/transfer/upload/processors/archive_processor.py,sha256=ID0lDwDn4vPe5nbxy6m28Ssj_TsZpK4df2xRrM6nJRQ,2015
@@ -97,10 +98,18 @@ deriva/transfer/upload/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NM
97
98
  deriva/utils/__init__.py,sha256=jv2YF__bseklT3OWEzlqJ5qE24c4aWd5F4r0TTjOrWQ,65
98
99
  tests/deriva/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
99
100
  tests/deriva/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
100
- tests/deriva/core/test_datapath.py,sha256=hC5PqyL9zqNOV4ydY5L4pHdt8r7Or7OgZnX-F52P2nU,37308
101
- deriva-1.7.1.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
102
- deriva-1.7.1.dist-info/METADATA,sha256=WAYjUe8xgfn45OweE56aX8q67MuxaBcdxdkrSRfZfO4,1623
103
- deriva-1.7.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
104
- deriva-1.7.1.dist-info/entry_points.txt,sha256=72BEmEE4Bes5QhVxUHrl7EvUARrgISWxI2KGa8BbNZ8,786
105
- deriva-1.7.1.dist-info/top_level.txt,sha256=_LHDie5-O53wFlexfrxjewpVkf04oydf3CqX5h75DXE,13
106
- deriva-1.7.1.dist-info/RECORD,,
101
+ tests/deriva/core/test_datapath.py,sha256=0vUlQ48KYkDW5L7hzwyGAETa_40y0JmZDalk0W0fCq4,38722
102
+ tests/deriva/core/test_ermrest_model.py,sha256=tmWmAgXTcLBueY4iUS14uq-b1SjgKMaFGt2lw9mYvbg,34330
103
+ tests/deriva/core/mmo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
104
+ tests/deriva/core/mmo/base.py,sha256=3iLqUDNdiJaERB-8-G-5NEvkJr9fz0YUMvPxl5hMINE,9356
105
+ tests/deriva/core/mmo/test_mmo_drop.py,sha256=R_yl-PIHGx-3kchT5TH8O9TJktepWjgs6hHISOc6d2k,8930
106
+ tests/deriva/core/mmo/test_mmo_find.py,sha256=PcUN76sik68B3XKg0G3wHVpKcPEld_6RtbxeGzkrMQ8,4172
107
+ tests/deriva/core/mmo/test_mmo_prune.py,sha256=4pYtYL8g1BgadlewNPVpVA5lT_gV6SPTDYf04ZKzBTA,6851
108
+ tests/deriva/core/mmo/test_mmo_rename.py,sha256=4oSR1G3Od701Ss3AnolI1Z7CbMxKuQF2uSr2_IcoR6s,8512
109
+ tests/deriva/core/mmo/test_mmo_replace.py,sha256=w-66LWyiQ_ajC7Ipmhc4kAKwIloPdQELeUPsvelTdX8,8439
110
+ deriva-1.7.4.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
111
+ deriva-1.7.4.dist-info/METADATA,sha256=wzg-6mYMEeNT1hsWxSFcP_1vQOj9mL8CfW1q64rxdJc,1623
112
+ deriva-1.7.4.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
113
+ deriva-1.7.4.dist-info/entry_points.txt,sha256=72BEmEE4Bes5QhVxUHrl7EvUARrgISWxI2KGa8BbNZ8,786
114
+ deriva-1.7.4.dist-info/top_level.txt,sha256=_LHDie5-O53wFlexfrxjewpVkf04oydf3CqX5h75DXE,13
115
+ deriva-1.7.4.dist-info/RECORD,,
File without changes