dcicutils 8.13.3.1b30__py3-none-any.whl → 8.14.0.1b2__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.
- dcicutils/misc_utils.py +3 -3
- dcicutils/scripts/update_portal_object.py +25 -8
- dcicutils/scripts/view_portal_object.py +21 -3
- {dcicutils-8.13.3.1b30.dist-info → dcicutils-8.14.0.1b2.dist-info}/METADATA +1 -1
- {dcicutils-8.13.3.1b30.dist-info → dcicutils-8.14.0.1b2.dist-info}/RECORD +8 -8
- {dcicutils-8.13.3.1b30.dist-info → dcicutils-8.14.0.1b2.dist-info}/LICENSE.txt +0 -0
- {dcicutils-8.13.3.1b30.dist-info → dcicutils-8.14.0.1b2.dist-info}/WHEEL +0 -0
- {dcicutils-8.13.3.1b30.dist-info → dcicutils-8.14.0.1b2.dist-info}/entry_points.txt +0 -0
dcicutils/misc_utils.py
CHANGED
@@ -1027,7 +1027,7 @@ _TO_NUMBER_MULTIPLIER_SUFFIXES = {
|
|
1027
1027
|
"GB": _TO_NUMBER_POWER_OF_TEN_FOR_G,
|
1028
1028
|
"T": _TO_NUMBER_POWER_OF_TEN_FOR_T,
|
1029
1029
|
"TB": _TO_NUMBER_POWER_OF_TEN_FOR_T,
|
1030
|
-
# B means bytes or bases and BP means base pairs; needs to be last.
|
1030
|
+
# B means bytes or bases and BP means base pairs; this needs to be last.
|
1031
1031
|
"B": _TO_NUMBER_POWER_OF_TEN_FOR_NOTHING,
|
1032
1032
|
"BP": _TO_NUMBER_POWER_OF_TEN_FOR_NOTHING
|
1033
1033
|
}
|
@@ -1093,9 +1093,9 @@ def to_number(value: str,
|
|
1093
1093
|
if not value_fraction:
|
1094
1094
|
return fallback
|
1095
1095
|
value = "0"
|
1096
|
-
elif (as_float is not True) and (
|
1096
|
+
elif (as_float is not True) and (value_dot_zeros_suffix := re.search(r"\.0*$", value)):
|
1097
1097
|
# Allow for example "123.00" to mean 123 (int).
|
1098
|
-
value = value[:
|
1098
|
+
value = value[:value_dot_zeros_suffix.start()]
|
1099
1099
|
|
1100
1100
|
if (allow_commas is True) and ("," in value):
|
1101
1101
|
# Make sure any commas are properly placed/spaced.
|
@@ -19,7 +19,7 @@ from typing import Callable, List, Optional, Tuple, Union
|
|
19
19
|
from dcicutils.command_utils import yes_or_no
|
20
20
|
from dcicutils.common import ORCHESTRATED_APPS, APP_SMAHT
|
21
21
|
from dcicutils.ff_utils import delete_metadata, purge_metadata
|
22
|
-
from dcicutils.misc_utils import get_error_message, PRINT
|
22
|
+
from dcicutils.misc_utils import get_error_message, ignored, PRINT
|
23
23
|
from dcicutils.portal_utils import Portal as PortalFromUtils
|
24
24
|
|
25
25
|
|
@@ -40,7 +40,7 @@ _DEFAULT_APP = "smaht"
|
|
40
40
|
_SMAHT_ENV_ENVIRON_NAME = "SMAHT_ENV"
|
41
41
|
|
42
42
|
# Schema properties to ignore (by default) for the view schema usage.
|
43
|
-
|
43
|
+
_IGNORE_PROPERTIES_ON_UPDATE = [
|
44
44
|
"date_created",
|
45
45
|
"last_modified",
|
46
46
|
"principals_allowed",
|
@@ -122,6 +122,8 @@ def main():
|
|
122
122
|
parser.add_argument("--upsert", type=str, required=False, default=None, help="Upsert data.")
|
123
123
|
parser.add_argument("--delete", type=str, required=False, default=None, help="Delete data.")
|
124
124
|
parser.add_argument("--purge", type=str, required=False, default=None, help="Purge data.")
|
125
|
+
parser.add_argument("--noignore", action="store_true", required=False, default=False,
|
126
|
+
help="Do not ignore standard fields on insert.")
|
125
127
|
parser.add_argument("--confirm", action="store_true", required=False, default=False, help="Confirm before action.")
|
126
128
|
parser.add_argument("--verbose", action="store_true", required=False, default=False, help="Verbose output.")
|
127
129
|
parser.add_argument("--quiet", action="store_true", required=False, default=False, help="Quiet output.")
|
@@ -156,6 +158,7 @@ def main():
|
|
156
158
|
explicit_schema_name=explicit_schema_name,
|
157
159
|
update_function=post_data,
|
158
160
|
update_action_name="POST",
|
161
|
+
noignore=args.noignore,
|
159
162
|
confirm=args.confirm, verbose=args.verbose, quiet=args.quiet, debug=args.debug)
|
160
163
|
if args.patch:
|
161
164
|
_post_or_patch_or_upsert(portal=portal,
|
@@ -164,6 +167,7 @@ def main():
|
|
164
167
|
update_function=patch_data,
|
165
168
|
update_action_name="PATCH",
|
166
169
|
patch_delete_fields=args.delete,
|
170
|
+
noignore=args.noignore,
|
167
171
|
confirm=args.confirm, verbose=args.verbose, quiet=args.quiet, debug=args.debug)
|
168
172
|
args.delete = None
|
169
173
|
if args.upsert:
|
@@ -173,6 +177,7 @@ def main():
|
|
173
177
|
update_function=upsert_data,
|
174
178
|
update_action_name="UPSERT",
|
175
179
|
patch_delete_fields=args.delete,
|
180
|
+
noignore=args.noignore,
|
176
181
|
confirm=args.confirm, verbose=args.verbose, quiet=args.quiet, debug=args.debug)
|
177
182
|
args.delete = None
|
178
183
|
|
@@ -196,6 +201,7 @@ def _post_or_patch_or_upsert(portal: Portal, file_or_directory: str,
|
|
196
201
|
explicit_schema_name: str,
|
197
202
|
update_function: Callable, update_action_name: str,
|
198
203
|
patch_delete_fields: Optional[str] = None,
|
204
|
+
noignore: bool = False,
|
199
205
|
confirm: bool = False, verbose: bool = False,
|
200
206
|
quiet: bool = False, debug: bool = False) -> None:
|
201
207
|
|
@@ -221,7 +227,7 @@ def _post_or_patch_or_upsert(portal: Portal, file_or_directory: str,
|
|
221
227
|
if debug:
|
222
228
|
_print(f"DEBUG: File ({file}) contains an object of type: {schema_name}")
|
223
229
|
update_function(portal, data, schema_name, file=file,
|
224
|
-
patch_delete_fields=patch_delete_fields,
|
230
|
+
patch_delete_fields=patch_delete_fields, noignore=noignore,
|
225
231
|
confirm=confirm, verbose=verbose, debug=debug)
|
226
232
|
elif is_schema_name_list(portal, list(data.keys())):
|
227
233
|
if debug:
|
@@ -232,7 +238,7 @@ def _post_or_patch_or_upsert(portal: Portal, file_or_directory: str,
|
|
232
238
|
_print(f"DEBUG: Processing {update_action_name}s for type: {schema_name}")
|
233
239
|
for index, item in enumerate(schema_data):
|
234
240
|
update_function(portal, item, schema_name, file=file, index=index,
|
235
|
-
patch_delete_fields=patch_delete_fields,
|
241
|
+
patch_delete_fields=patch_delete_fields, noignore=noignore,
|
236
242
|
confirm=confirm, verbose=verbose, debug=debug)
|
237
243
|
else:
|
238
244
|
_print(f"WARNING: File ({file}) contains schema item which is not a list: {schema_name}")
|
@@ -243,7 +249,7 @@ def _post_or_patch_or_upsert(portal: Portal, file_or_directory: str,
|
|
243
249
|
_print(f"DEBUG: File ({file}) contains a list of objects of type: {schema_name}")
|
244
250
|
for index, item in enumerate(data):
|
245
251
|
update_function(portal, item, schema_name, file=file, index=index,
|
246
|
-
patch_delete_fields=patch_delete_fields,
|
252
|
+
patch_delete_fields=patch_delete_fields, noignore=noignore,
|
247
253
|
confirm=confirm, verbose=verbose, debug=debug)
|
248
254
|
if debug:
|
249
255
|
_print(f"DEBUG: Processing {update_action_name} file done: {file}")
|
@@ -278,8 +284,9 @@ def _post_or_patch_or_upsert(portal: Portal, file_or_directory: str,
|
|
278
284
|
|
279
285
|
def post_data(portal: Portal, data: dict, schema_name: str,
|
280
286
|
file: Optional[str] = None, index: int = 0,
|
281
|
-
patch_delete_fields: Optional[str] = None,
|
287
|
+
patch_delete_fields: Optional[str] = None, noignore: bool = False,
|
282
288
|
confirm: bool = False, verbose: bool = False, debug: bool = False) -> None:
|
289
|
+
ignored(patch_delete_fields)
|
283
290
|
if not (identifying_path := portal.get_identifying_path(data, portal_type=schema_name)):
|
284
291
|
if isinstance(file, str) and isinstance(index, int):
|
285
292
|
_print(f"ERROR: Item for POST has no identifying property: {file} (#{index + 1})")
|
@@ -294,6 +301,7 @@ def post_data(portal: Portal, data: dict, schema_name: str,
|
|
294
301
|
if verbose:
|
295
302
|
_print(f"POST {schema_name} item: {identifying_path}")
|
296
303
|
try:
|
304
|
+
data = _prune_data_for_update(data, noignore=noignore)
|
297
305
|
portal.post_metadata(schema_name, data)
|
298
306
|
if debug:
|
299
307
|
_print(f"DEBUG: POST {schema_name} item done: {identifying_path}")
|
@@ -305,7 +313,7 @@ def post_data(portal: Portal, data: dict, schema_name: str,
|
|
305
313
|
|
306
314
|
def patch_data(portal: Portal, data: dict, schema_name: str,
|
307
315
|
file: Optional[str] = None, index: int = 0,
|
308
|
-
patch_delete_fields: Optional[str] = None,
|
316
|
+
patch_delete_fields: Optional[str] = None, noignore: bool = False,
|
309
317
|
confirm: bool = False, verbose: bool = False, debug: bool = False) -> None:
|
310
318
|
if not (identifying_path := portal.get_identifying_path(data, portal_type=schema_name)):
|
311
319
|
if isinstance(file, str) and isinstance(index, int):
|
@@ -323,6 +331,7 @@ def patch_data(portal: Portal, data: dict, schema_name: str,
|
|
323
331
|
try:
|
324
332
|
if delete_fields := _parse_delete_fields(patch_delete_fields):
|
325
333
|
identifying_path += f"?delete_fields={delete_fields}"
|
334
|
+
data = _prune_data_for_update(data, noignore=noignore)
|
326
335
|
portal.patch_metadata(identifying_path, data)
|
327
336
|
if debug:
|
328
337
|
_print(f"DEBUG: PATCH {schema_name} item OK: {identifying_path}")
|
@@ -334,7 +343,7 @@ def patch_data(portal: Portal, data: dict, schema_name: str,
|
|
334
343
|
|
335
344
|
def upsert_data(portal: Portal, data: dict, schema_name: str,
|
336
345
|
file: Optional[str] = None, index: int = 0,
|
337
|
-
patch_delete_fields: Optional[str] = None,
|
346
|
+
patch_delete_fields: Optional[str] = None, noignore: bool = False,
|
338
347
|
confirm: bool = False, verbose: bool = False, debug: bool = False) -> None:
|
339
348
|
if not (identifying_path := portal.get_identifying_path(data, portal_type=schema_name)):
|
340
349
|
if isinstance(file, str) and isinstance(index, int):
|
@@ -349,10 +358,12 @@ def upsert_data(portal: Portal, data: dict, schema_name: str,
|
|
349
358
|
_print(f"{'PATCH' if exists else 'POST'} {schema_name} item: {identifying_path}")
|
350
359
|
try:
|
351
360
|
if not exists:
|
361
|
+
data = _prune_data_for_update(data, noignore=noignore)
|
352
362
|
portal.post_metadata(schema_name, data)
|
353
363
|
else:
|
354
364
|
if delete_fields := _parse_delete_fields(patch_delete_fields):
|
355
365
|
identifying_path += f"?delete_fields={delete_fields}"
|
366
|
+
data = _prune_data_for_update(data, noignore=noignore)
|
356
367
|
portal.patch_metadata(identifying_path, data)
|
357
368
|
if debug:
|
358
369
|
_print(f"DEBUG: UPSERT {schema_name} item OK: {identifying_path}")
|
@@ -362,6 +373,12 @@ def upsert_data(portal: Portal, data: dict, schema_name: str,
|
|
362
373
|
return
|
363
374
|
|
364
375
|
|
376
|
+
def _prune_data_for_update(data: dict, noignore: bool = False) -> dict:
|
377
|
+
if noignore is True:
|
378
|
+
return data
|
379
|
+
return {key: value for key, value in data.items() if key not in _IGNORE_PROPERTIES_ON_UPDATE}
|
380
|
+
|
381
|
+
|
365
382
|
def _create_portal(env: Optional[str] = None, app: Optional[str] = None,
|
366
383
|
verbose: bool = False, debug: bool = False) -> Optional[Portal]:
|
367
384
|
|
@@ -279,13 +279,31 @@ def _get_portal_object(portal: Portal, uuid: str,
|
|
279
279
|
if not ((supertypes := portal.get_schemas_super_type_map()) and (subtypes := supertypes.get(results_type))):
|
280
280
|
subtypes = None
|
281
281
|
response = {}
|
282
|
+
results_index = 0
|
283
|
+
results_total = len(results)
|
284
|
+
def get_metadata_for_individual_result_type(uuid: str) -> Optional[dict]: # noqa
|
285
|
+
# There can be a lot of individual results for which we may need to get the actual type,
|
286
|
+
# so do this in a function we were can give verbose output feedback.
|
287
|
+
nonlocal portal, results_index, results_total, verbose
|
288
|
+
if verbose:
|
289
|
+
_print(f"Getting actual type for {results_type} result:"
|
290
|
+
f" {uuid} [{results_index} of {results_total}]", end="")
|
291
|
+
result = portal.get_metadata(uuid, raise_exception=False)
|
292
|
+
if (isinstance(result_types := result.get("@type"), list) and
|
293
|
+
result_types and (result_type := result_types[0])): # noqa
|
294
|
+
if verbose:
|
295
|
+
_print(f" -> {result_type}")
|
296
|
+
return result_type
|
297
|
+
if verbose:
|
298
|
+
_print()
|
299
|
+
return None
|
282
300
|
for result in results:
|
301
|
+
results_index += 1
|
283
302
|
result.pop("schema_version", None)
|
284
303
|
if (subtypes and
|
285
304
|
(result_uuid := result.get("uuid")) and
|
286
|
-
(
|
287
|
-
|
288
|
-
result_type = result_type[0]
|
305
|
+
(individual_result_type := get_metadata_for_individual_result_type(result_uuid))): # noqa
|
306
|
+
result_type = individual_result_type
|
289
307
|
else:
|
290
308
|
result_type = results_type
|
291
309
|
if response.get(result_type):
|
@@ -45,7 +45,7 @@ dcicutils/license_policies/park-lab-gpl-pipeline.jsonc,sha256=vLZkwm3Js-kjV44nug
|
|
45
45
|
dcicutils/license_policies/park-lab-pipeline.jsonc,sha256=9qlY0ASy3iUMQlr3gorVcXrSfRHnVGbLhkS427UaRy4,283
|
46
46
|
dcicutils/license_utils.py,sha256=2Yxnh1T1iuMe6wluwbvpFO_zYSGPxB4-STAMc-vz-YM,47202
|
47
47
|
dcicutils/log_utils.py,sha256=7pWMc6vyrorUZQf-V-M3YC6zrPgNhuV_fzm9xqTPph0,10883
|
48
|
-
dcicutils/misc_utils.py,sha256=
|
48
|
+
dcicutils/misc_utils.py,sha256=mO-5i0IUZ2U-P7rnQcC9VURzQ35pz7jFsMZdq6BB_QM,115929
|
49
49
|
dcicutils/obfuscation_utils.py,sha256=fo2jOmDRC6xWpYX49u80bVNisqRRoPskFNX3ymFAmjw,5963
|
50
50
|
dcicutils/opensearch_utils.py,sha256=V2exmFYW8Xl2_pGFixF4I2Cc549Opwe4PhFi5twC0M8,1017
|
51
51
|
dcicutils/portal_object_utils.py,sha256=Az3n1aL-PQkN5gOFE6ZqC2XkYsqiwKlq7-tZggs1QN4,11062
|
@@ -60,8 +60,8 @@ dcicutils/s3_utils.py,sha256=h2B9ftOo-kxqfiKth5ZDC_cAUFy1Pbu7BrVanFnE5Iw,28839
|
|
60
60
|
dcicutils/schema_utils.py,sha256=GmRm-XqZKJ6qine16SQF1txcby9WougDav_sYmKNs9E,12400
|
61
61
|
dcicutils/scripts/publish_to_pypi.py,sha256=sMd4WASQGlxlh7uLrt2eGkFRXYgONVmvIg8mClMS5RQ,13903
|
62
62
|
dcicutils/scripts/run_license_checker.py,sha256=z2keYnRDZsHQbTeo1XORAXSXNJK5axVzL5LjiNqZ7jE,4184
|
63
|
-
dcicutils/scripts/update_portal_object.py,sha256=
|
64
|
-
dcicutils/scripts/view_portal_object.py,sha256=
|
63
|
+
dcicutils/scripts/update_portal_object.py,sha256=gIO0fz6_SrfttYrdhfX7BVAYdtC4VZDXomycPrNWdbI,21395
|
64
|
+
dcicutils/scripts/view_portal_object.py,sha256=yQAGxFWBZ7UU8vrD8xbeI_oS4oU2mXZBaQPCraLbdCU,33241
|
65
65
|
dcicutils/secrets_utils.py,sha256=8dppXAsiHhJzI6NmOcvJV5ldvKkQZzh3Fl-cb8Wm7MI,19745
|
66
66
|
dcicutils/sheet_utils.py,sha256=VlmzteONW5VF_Q4vo0yA5vesz1ViUah1MZ_yA1rwZ0M,33629
|
67
67
|
dcicutils/snapshot_utils.py,sha256=YDeI3vD-MhAtHwKDzfEm2q-n3l-da2yRpRR3xp0Ah1M,23021
|
@@ -75,8 +75,8 @@ dcicutils/trace_utils.py,sha256=g8kwV4ebEy5kXW6oOrEAUsurBcCROvwtZqz9fczsGRE,1769
|
|
75
75
|
dcicutils/validation_utils.py,sha256=cMZIU2cY98FYtzK52z5WUYck7urH6JcqOuz9jkXpqzg,14797
|
76
76
|
dcicutils/variant_utils.py,sha256=2H9azNx3xAj-MySg-uZ2SFqbWs4kZvf61JnK6b-h4Qw,4343
|
77
77
|
dcicutils/zip_utils.py,sha256=_Y9EmL3D2dUZhxucxHvrtmmlbZmK4FpSsHEb7rGSJLU,3265
|
78
|
-
dcicutils-8.
|
79
|
-
dcicutils-8.
|
80
|
-
dcicutils-8.
|
81
|
-
dcicutils-8.
|
82
|
-
dcicutils-8.
|
78
|
+
dcicutils-8.14.0.1b2.dist-info/LICENSE.txt,sha256=qnwSmfnEWMl5l78VPDEzAmEbLVrRqQvfUQiHT0ehrOo,1102
|
79
|
+
dcicutils-8.14.0.1b2.dist-info/METADATA,sha256=uiJoLtk6VKcjRjvIlCDmF_8ADNo31t_Kuf1fxtv5OBM,3439
|
80
|
+
dcicutils-8.14.0.1b2.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
|
81
|
+
dcicutils-8.14.0.1b2.dist-info/entry_points.txt,sha256=W6kEWdUJk9tQ4myAgpehPdebcwvCAZ7UgB-wyPgDUMg,335
|
82
|
+
dcicutils-8.14.0.1b2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|