dcicutils 8.14.0.1b16__py3-none-any.whl → 8.14.0.1b17__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.
@@ -21,7 +21,7 @@ from dcicutils.captured_output import captured_output
21
21
  from dcicutils.command_utils import yes_or_no
22
22
  from dcicutils.common import ORCHESTRATED_APPS, APP_CGAP, APP_FOURFRONT, APP_SMAHT
23
23
  from dcicutils.ff_utils import delete_metadata, purge_metadata
24
- from dcicutils.misc_utils import get_error_message, ignored, PRINT, to_camel_case, to_snake_case
24
+ from dcicutils.misc_utils import get_error_message, ignored, normalize_string, PRINT, to_camel_case, to_snake_case
25
25
  from dcicutils.portal_utils import Portal as PortalFromUtils
26
26
  from dcicutils.tmpfile_utils import temporary_directory
27
27
 
@@ -393,14 +393,20 @@ def _load_data(portal: Portal, load: str, ini_file: str, explicit_schema_name: O
393
393
  verbose: bool = False, debug: bool = False, noprogress: bool = False,
394
394
  _single_insert_file: Optional[str] = None) -> bool:
395
395
 
396
+ import snovault.loadxl
396
397
  from snovault.loadxl import load_all_gen, LoadGenWrapper
397
398
  from dcicutils.progress_bar import ProgressBar
398
399
 
399
400
  loadxl_summary = {}
401
+ loadxl_unresolved = {}
402
+ loadxl_output = []
403
+ loadxl_total_item_count = 0
404
+ loadxl_total_error_count = 0
400
405
 
401
406
  def loadxl(portal: Portal, inserts_directory: str, schema_names_to_load: dict):
402
407
 
403
408
  nonlocal LoadGenWrapper, load_all_gen, loadxl_summary, verbose, debug
409
+ nonlocal loadxl_total_item_count, loadxl_total_error_count
404
410
  progress_total = sum(schema_names_to_load.values()) * 2 # loadxl does two passes
405
411
  progress_bar = ProgressBar(progress_total, interrupt_exit=True) if not noprogress else None
406
412
 
@@ -413,27 +419,54 @@ def _load_data(portal: Portal, load: str, ini_file: str, explicit_schema_name: O
413
419
  return str_or_bytes.strip()
414
420
  return ""
415
421
 
422
+ def loadxl_print(arg):
423
+ if arg:
424
+ loadxl_output.append(normalize_string(str(arg)))
425
+
426
+ snovault.loadxl.print = loadxl_print
427
+
416
428
  LOADXL_RESPONSE_PATTERN = re.compile(r"^([A-Z]+):\s*([a-zA-Z\/\d_-]+)\s*(\S+)\s*(\S+)?\s*(.*)$")
417
429
  LOADXL_ACTION_NAME = {"POST": "Create", "PATCH": "Update", "SKIP": "Check",
418
430
  "CHECK": "Validate", "ERROR": "Error"}
419
431
  current_item_type = None
420
432
  current_item_count = 0
421
433
  current_item_total = 0
422
- total_item_count = 0
434
+
423
435
  for item in LoadGenWrapper(load_all_gen(testapp=portal.vapp, inserts=inserts_directory,
424
436
  docsdir=None, overwrite=True, verbose=True)):
425
- total_item_count += 1
437
+ loadxl_total_item_count += 1
426
438
  item = decode_bytes(item)
427
439
  match = LOADXL_RESPONSE_PATTERN.match(item)
428
440
  if not match or match.re.groups < 3:
429
441
  continue
430
- action = LOADXL_ACTION_NAME[match.group(1).upper()]
431
- # response_value = match.group(0)
432
- # identifying_value = match.group(2)
442
+ if (action := LOADXL_ACTION_NAME[match.group(1).upper()]) == "Error":
443
+ identifying_value = match.group(2)
444
+ # Example message for unresolved link:
445
+ # ERROR: /22813a02-906b-4b60-b2b2-4afaea24aa28 Bad response: 422 Unprocessable Entity
446
+ # (not 200 OK or 3xx redirect for http://localhost/file_set?skip_indexing=true)b\'{"@type":
447
+ # ["ValidationFailure", "Error"], "status": "error", "code": # 422, "title": "Unprocessable Entity",
448
+ # "description": "Failed validation", "errors": [{"location": "body", "name": # "Schema: ",
449
+ # "description": "Unable to resolve link: /Library/a4e8f79f-4d47-4e85-9707-c343c940a315"},
450
+ # {"location": "body", "name": "Schema: libraries.0",
451
+ # "description": "\\\'a4e8f79f-4d47-4e85-9707-c343c940a315\\\' not found"}]}\'
452
+ unresolved_link_error_message_prefix = "Unable to resolve link:"
453
+ if (i := item.find(unresolved_link_error_message_prefix)) > 0:
454
+ unresolved_link = item[i + len(unresolved_link_error_message_prefix):].strip()
455
+ if (i := unresolved_link.find("\"")) > 0:
456
+ if (unresolved_link := unresolved_link[0:i]):
457
+ if ((error_type := re.search(r"https?://.*/(.*)\?skip_indexing=.*", item)) and
458
+ (len(error_type.groups()) == 1)): # noqa
459
+ error_type = to_camel_case(error_type.group(1))
460
+ identifying_value = f"/{error_type}{identifying_value}"
461
+ if not loadxl_unresolved.get(identifying_value):
462
+ loadxl_unresolved[identifying_value] = []
463
+ loadxl_unresolved[identifying_value].append(unresolved_link)
464
+ loadxl_total_error_count += 1
465
+ continue
433
466
  item_type = match.group(3)
434
467
  if current_item_type != item_type:
435
468
  if noprogress and debug and current_item_type is not None:
436
- print()
469
+ _print()
437
470
  current_item_type = item_type
438
471
  current_item_count = 0
439
472
  current_item_total = schema_names_to_load[item_type]
@@ -444,12 +477,13 @@ def _load_data(portal: Portal, load: str, ini_file: str, explicit_schema_name: O
444
477
  loadxl_summary[current_item_type] = 0
445
478
  loadxl_summary[current_item_type] += 1
446
479
  if progress_bar:
447
- progress_bar.set_progress(total_item_count)
480
+ progress_bar.set_progress(loadxl_total_item_count)
448
481
  elif debug:
449
- print(f"{current_item_type}: {current_item_count} or {current_item_total} ({action})")
482
+ _print(f"{current_item_type}: {current_item_count} or {current_item_total} ({action})")
450
483
  if progress_bar:
451
484
  progress_bar.set_description("▶ Load Complete")
452
- print()
485
+ if loadxl_total_item_count > loadxl_total_error_count:
486
+ _print()
453
487
 
454
488
  if not portal.vapp:
455
489
  _print("Must using INI based Portal object with --load (use --ini option to specify an INI file).")
@@ -573,8 +607,20 @@ def _load_data(portal: Portal, load: str, ini_file: str, explicit_schema_name: O
573
607
  _print(f"Done loading data into Portal (via snovault.loadxl) from file: {_single_insert_file}")
574
608
  else:
575
609
  _print(f"Done loading data into Portal (via snovault.loadxl) from directory: {inserts_directory}")
610
+ _print(f"Total items loaded: {loadxl_total_item_count}"
611
+ f"{f' (errors: {loadxl_total_error_count})' if loadxl_total_error_count else ''}")
576
612
  for item in sorted(loadxl_summary.keys()):
577
613
  _print(f"▷ {to_camel_case(item)}: {loadxl_summary[item]}")
614
+ if loadxl_unresolved:
615
+ _print("✗ Unresolved references:")
616
+ for item in loadxl_unresolved:
617
+ _print(f" ▶ {item}: {len(loadxl_unresolved[item])}")
618
+ for subitem in loadxl_unresolved[item]:
619
+ _print(f" ▷ {subitem}")
620
+ if debug and loadxl_output:
621
+ _print("✗ Output from loadxl:")
622
+ for item in loadxl_output:
623
+ _print(f" ▶ {item}")
578
624
 
579
625
  return True
580
626
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dcicutils
3
- Version: 8.14.0.1b16
3
+ Version: 8.14.0.1b17
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
@@ -60,7 +60,7 @@ 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=lRF40toLSGjqlbeHDxKIyx2XaasLKEmvSn_ZnCpKm_A,35566
63
+ dcicutils/scripts/update_portal_object.py,sha256=MsNpF6eHGVxr7dUg8QrwZo9XfIjPjAavOWqyI_RrfpA,38397
64
64
  dcicutils/scripts/view_portal_object.py,sha256=lcgXWH9ooVf7tJDIRnoFGOgT0wYLGhiJlJW3a9w6A_c,36983
65
65
  dcicutils/secrets_utils.py,sha256=8dppXAsiHhJzI6NmOcvJV5ldvKkQZzh3Fl-cb8Wm7MI,19745
66
66
  dcicutils/sheet_utils.py,sha256=VlmzteONW5VF_Q4vo0yA5vesz1ViUah1MZ_yA1rwZ0M,33629
@@ -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.14.0.1b16.dist-info/LICENSE.txt,sha256=qnwSmfnEWMl5l78VPDEzAmEbLVrRqQvfUQiHT0ehrOo,1102
79
- dcicutils-8.14.0.1b16.dist-info/METADATA,sha256=9KI830ZNINFtzrJ1PCSrGZG6UB_zOjnvTeRU0cmlJhk,3440
80
- dcicutils-8.14.0.1b16.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
81
- dcicutils-8.14.0.1b16.dist-info/entry_points.txt,sha256=W6kEWdUJk9tQ4myAgpehPdebcwvCAZ7UgB-wyPgDUMg,335
82
- dcicutils-8.14.0.1b16.dist-info/RECORD,,
78
+ dcicutils-8.14.0.1b17.dist-info/LICENSE.txt,sha256=qnwSmfnEWMl5l78VPDEzAmEbLVrRqQvfUQiHT0ehrOo,1102
79
+ dcicutils-8.14.0.1b17.dist-info/METADATA,sha256=WxgzreGqLqRZT1QRIzME9quTpxihdyduDQKkxX9kdS0,3440
80
+ dcicutils-8.14.0.1b17.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
81
+ dcicutils-8.14.0.1b17.dist-info/entry_points.txt,sha256=W6kEWdUJk9tQ4myAgpehPdebcwvCAZ7UgB-wyPgDUMg,335
82
+ dcicutils-8.14.0.1b17.dist-info/RECORD,,