dcicutils 8.14.0.1b16__py3-none-any.whl → 8.14.0.1b18__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,55 @@ 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
- docsdir=None, overwrite=True, verbose=True)):
425
- total_item_count += 1
436
+ docsdir=None, overwrite=True, verbose=True,
437
+ continue_on_exception=True)):
438
+ loadxl_total_item_count += 1
426
439
  item = decode_bytes(item)
427
440
  match = LOADXL_RESPONSE_PATTERN.match(item)
428
441
  if not match or match.re.groups < 3:
429
442
  continue
430
- action = LOADXL_ACTION_NAME[match.group(1).upper()]
431
- # response_value = match.group(0)
432
- # identifying_value = match.group(2)
443
+ if (action := LOADXL_ACTION_NAME[match.group(1).upper()]) == "Error":
444
+ identifying_value = match.group(2)
445
+ # Example message for unresolved link:
446
+ # ERROR: /22813a02-906b-4b60-b2b2-4afaea24aa28 Bad response: 422 Unprocessable Entity
447
+ # (not 200 OK or 3xx redirect for http://localhost/file_set?skip_indexing=true)b\'{"@type":
448
+ # ["ValidationFailure", "Error"], "status": "error", "code": # 422, "title": "Unprocessable Entity",
449
+ # "description": "Failed validation", "errors": [{"location": "body", "name": # "Schema: ",
450
+ # "description": "Unable to resolve link: /Library/a4e8f79f-4d47-4e85-9707-c343c940a315"},
451
+ # {"location": "body", "name": "Schema: libraries.0",
452
+ # "description": "\\\'a4e8f79f-4d47-4e85-9707-c343c940a315\\\' not found"}]}\'
453
+ unresolved_link_error_message_prefix = "Unable to resolve link:"
454
+ if (i := item.find(unresolved_link_error_message_prefix)) > 0:
455
+ unresolved_link = item[i + len(unresolved_link_error_message_prefix):].strip()
456
+ if (i := unresolved_link.find("\"")) > 0:
457
+ if (unresolved_link := unresolved_link[0:i]):
458
+ if ((error_type := re.search(r"https?://.*/(.*)\?skip_indexing=.*", item)) and
459
+ (len(error_type.groups()) == 1)): # noqa
460
+ error_type = to_camel_case(error_type.group(1))
461
+ identifying_value = f"/{error_type}{identifying_value}"
462
+ if not loadxl_unresolved.get(identifying_value):
463
+ loadxl_unresolved[identifying_value] = []
464
+ loadxl_unresolved[identifying_value].append(unresolved_link)
465
+ loadxl_total_error_count += 1
466
+ continue
433
467
  item_type = match.group(3)
434
468
  if current_item_type != item_type:
435
469
  if noprogress and debug and current_item_type is not None:
436
- print()
470
+ _print()
437
471
  current_item_type = item_type
438
472
  current_item_count = 0
439
473
  current_item_total = schema_names_to_load[item_type]
@@ -444,12 +478,13 @@ def _load_data(portal: Portal, load: str, ini_file: str, explicit_schema_name: O
444
478
  loadxl_summary[current_item_type] = 0
445
479
  loadxl_summary[current_item_type] += 1
446
480
  if progress_bar:
447
- progress_bar.set_progress(total_item_count)
481
+ progress_bar.set_progress(loadxl_total_item_count)
448
482
  elif debug:
449
- print(f"{current_item_type}: {current_item_count} or {current_item_total} ({action})")
483
+ _print(f"{current_item_type}: {current_item_count} or {current_item_total} ({action})")
450
484
  if progress_bar:
451
485
  progress_bar.set_description("▶ Load Complete")
452
- print()
486
+ if loadxl_total_item_count > loadxl_total_error_count:
487
+ _print()
453
488
 
454
489
  if not portal.vapp:
455
490
  _print("Must using INI based Portal object with --load (use --ini option to specify an INI file).")
@@ -573,8 +608,20 @@ def _load_data(portal: Portal, load: str, ini_file: str, explicit_schema_name: O
573
608
  _print(f"Done loading data into Portal (via snovault.loadxl) from file: {_single_insert_file}")
574
609
  else:
575
610
  _print(f"Done loading data into Portal (via snovault.loadxl) from directory: {inserts_directory}")
611
+ _print(f"Total items loaded: {loadxl_total_item_count}"
612
+ f"{f' (errors: {loadxl_total_error_count})' if loadxl_total_error_count else ''}")
576
613
  for item in sorted(loadxl_summary.keys()):
577
614
  _print(f"▷ {to_camel_case(item)}: {loadxl_summary[item]}")
615
+ if loadxl_unresolved:
616
+ _print("✗ Unresolved references:")
617
+ for item in loadxl_unresolved:
618
+ _print(f" ▶ {item}: {len(loadxl_unresolved[item])}")
619
+ for subitem in loadxl_unresolved[item]:
620
+ _print(f" ▷ {subitem}")
621
+ if debug and loadxl_output:
622
+ _print("✗ Output from loadxl:")
623
+ for item in loadxl_output:
624
+ _print(f" ▶ {item}")
578
625
 
579
626
  return True
580
627
 
@@ -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.1b18
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=r-uT7y-S0bmiDTSH0UFnae5HDntiAkP-DadPZ8Fr-xk,38473
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.1b18.dist-info/LICENSE.txt,sha256=qnwSmfnEWMl5l78VPDEzAmEbLVrRqQvfUQiHT0ehrOo,1102
79
+ dcicutils-8.14.0.1b18.dist-info/METADATA,sha256=41mUWL-MZgiKTwZDpbO9aURr1P8yMa4xnjbaUsSGHJM,3440
80
+ dcicutils-8.14.0.1b18.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
81
+ dcicutils-8.14.0.1b18.dist-info/entry_points.txt,sha256=W6kEWdUJk9tQ4myAgpehPdebcwvCAZ7UgB-wyPgDUMg,335
82
+ dcicutils-8.14.0.1b18.dist-info/RECORD,,