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 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 (value_dot_zero_suffix := re.search(r"\.0*$", value)):
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[:value_dot_zero_suffix.start()]
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
- _SCHEMAS_IGNORE_PROPERTIES = [
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, # unused here
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
- (individual_result := portal.get_metadata(result_uuid, raise_exception=False)) and
287
- isinstance(result_type:= individual_result.get("@type"), list) and result_type and result_type[0]): # noqa
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):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dcicutils
3
- Version: 8.13.3.1b30
3
+ Version: 8.14.0.1b2
4
4
  Summary: Utility package for interacting with the 4DN Data Portal and other 4DN resources
5
5
  Home-page: https://github.com/4dn-dcic/utils
6
6
  License: MIT
@@ -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=yoccfuCRlHOky31ljxtMDugrNE4QHqaweGWOWjWHI94,115922
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=Lrgj01JuxmQSoWikukYgwm5LKi9CgSzjAogoMIBsQC4,20373
64
- dcicutils/scripts/view_portal_object.py,sha256=h8COy0lcLNWF9b5spjrlQ28wfqyTTMqAeC_xpFXutus,32262
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.13.3.1b30.dist-info/LICENSE.txt,sha256=qnwSmfnEWMl5l78VPDEzAmEbLVrRqQvfUQiHT0ehrOo,1102
79
- dcicutils-8.13.3.1b30.dist-info/METADATA,sha256=W41FLeNYNat2V-1BvXOE60D4QN1N-Gj7PdjYXESWib4,3440
80
- dcicutils-8.13.3.1b30.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
81
- dcicutils-8.13.3.1b30.dist-info/entry_points.txt,sha256=W6kEWdUJk9tQ4myAgpehPdebcwvCAZ7UgB-wyPgDUMg,335
82
- dcicutils-8.13.3.1b30.dist-info/RECORD,,
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,,