dcicutils 8.14.0.1b9__py3-none-any.whl → 8.14.0.1b11__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/scripts/update_portal_object.py +219 -56
- {dcicutils-8.14.0.1b9.dist-info → dcicutils-8.14.0.1b11.dist-info}/METADATA +1 -1
- {dcicutils-8.14.0.1b9.dist-info → dcicutils-8.14.0.1b11.dist-info}/RECORD +6 -6
- {dcicutils-8.14.0.1b9.dist-info → dcicutils-8.14.0.1b11.dist-info}/LICENSE.txt +0 -0
- {dcicutils-8.14.0.1b9.dist-info → dcicutils-8.14.0.1b11.dist-info}/WHEEL +0 -0
- {dcicutils-8.14.0.1b9.dist-info → dcicutils-8.14.0.1b11.dist-info}/entry_points.txt +0 -0
| @@ -14,13 +14,15 @@ import io | |
| 14 14 | 
             
            import json
         | 
| 15 15 | 
             
            import os
         | 
| 16 16 | 
             
            import re
         | 
| 17 | 
            +
            import shutil
         | 
| 17 18 | 
             
            import sys
         | 
| 18 19 | 
             
            from typing import Callable, List, Optional, Tuple, Union
         | 
| 19 20 | 
             
            from dcicutils.command_utils import yes_or_no
         | 
| 20 21 | 
             
            from dcicutils.common import ORCHESTRATED_APPS, APP_SMAHT
         | 
| 21 22 | 
             
            from dcicutils.ff_utils import delete_metadata, purge_metadata
         | 
| 22 | 
            -
            from dcicutils.misc_utils import get_error_message, ignored, PRINT
         | 
| 23 | 
            +
            from dcicutils.misc_utils import get_error_message, ignored, PRINT, to_camel_case, to_snake_case
         | 
| 23 24 | 
             
            from dcicutils.portal_utils import Portal as PortalFromUtils
         | 
| 25 | 
            +
            from dcicutils.tmpfile_utils import temporary_directory
         | 
| 24 26 |  | 
| 25 27 |  | 
| 26 28 | 
             
            class Portal(PortalFromUtils):
         | 
| @@ -131,6 +133,8 @@ def main(): | |
| 131 133 | 
             
                parser.add_argument("--confirm", action="store_true", required=False, default=False, help="Confirm before action.")
         | 
| 132 134 | 
             
                parser.add_argument("--verbose", action="store_true", required=False, default=False, help="Verbose output.")
         | 
| 133 135 | 
             
                parser.add_argument("--quiet", action="store_true", required=False, default=False, help="Quiet output.")
         | 
| 136 | 
            +
                parser.add_argument("--noprogress", action="store_true", required=False, default=False,
         | 
| 137 | 
            +
                                    help="No progress bar output for --load.")
         | 
| 134 138 | 
             
                parser.add_argument("--debug", action="store_true", required=False, default=False, help="Debugging output.")
         | 
| 135 139 | 
             
                args = parser.parse_args()
         | 
| 136 140 |  | 
| @@ -158,27 +162,8 @@ def main(): | |
| 158 162 | 
             
                        _print("The --env is not used for the --load option (to load data via snovault.loadxl).")
         | 
| 159 163 | 
             
                    if args.schema:
         | 
| 160 164 | 
             
                        _print("The --schema is not used for the --load option (to load data via snovault.loadxl).")
         | 
| 161 | 
            -
                     | 
| 162 | 
            -
             | 
| 163 | 
            -
                    if args.ini:
         | 
| 164 | 
            -
                        ini_file = args.ini
         | 
| 165 | 
            -
                    else:
         | 
| 166 | 
            -
                        ini_file = _DEFAULT_INI_FILE_FOR_LOAD
         | 
| 167 | 
            -
                    if not os.path.exists(ini_file):
         | 
| 168 | 
            -
                        _print(f"The INI file required for --load is not found: {ini_file}")
         | 
| 169 | 
            -
                        exit(1)
         | 
| 170 | 
            -
                    if not os.path.isdir(args.load):
         | 
| 171 | 
            -
                        _print(f"Load directory does not exist: {args.load}")
         | 
| 172 | 
            -
                        exit(1)
         | 
| 173 | 
            -
                    portal = None
         | 
| 174 | 
            -
                    with captured_output(not args.debug):
         | 
| 175 | 
            -
                        portal = Portal(ini_file)
         | 
| 176 | 
            -
                    if args.verbose:
         | 
| 177 | 
            -
                        _print(f"Loading data files into Portal (via snovault.loadxl) from: {args.load}")
         | 
| 178 | 
            -
                        _print(f"Portal INI file for load is: {ini_file}")
         | 
| 179 | 
            -
                    load_data(portal.vapp, indir=args.load, overwrite=True, use_master_inserts=False)
         | 
| 180 | 
            -
                    if args.verbose:
         | 
| 181 | 
            -
                        _print(f"Done loading data into Portal (via snovault.loadxl) files from: {args.load}")
         | 
| 165 | 
            +
                    _load_data(load=args.load, ini_file=args.ini,
         | 
| 166 | 
            +
                               verbose=args.verbose, debug=args.debug, noprogress=args.noprogress)
         | 
| 182 167 | 
             
                    exit(0)
         | 
| 183 168 |  | 
| 184 169 | 
             
                portal = _create_portal(env=args.env, app=app, verbose=args.verbose, debug=args.debug)
         | 
| @@ -192,7 +177,7 @@ def main(): | |
| 192 177 | 
             
                    _post_or_patch_or_upsert(portal=portal,
         | 
| 193 178 | 
             
                                             file_or_directory=args.post,
         | 
| 194 179 | 
             
                                             explicit_schema_name=explicit_schema_name,
         | 
| 195 | 
            -
                                             update_function= | 
| 180 | 
            +
                                             update_function=_post_data,
         | 
| 196 181 | 
             
                                             update_action_name="POST",
         | 
| 197 182 | 
             
                                             noignore=args.noignore, ignore=args.ignore,
         | 
| 198 183 | 
             
                                             confirm=args.confirm, verbose=args.verbose, quiet=args.quiet, debug=args.debug)
         | 
| @@ -200,7 +185,7 @@ def main(): | |
| 200 185 | 
             
                    _post_or_patch_or_upsert(portal=portal,
         | 
| 201 186 | 
             
                                             file_or_directory=args.patch,
         | 
| 202 187 | 
             
                                             explicit_schema_name=explicit_schema_name,
         | 
| 203 | 
            -
                                             update_function= | 
| 188 | 
            +
                                             update_function=_patch_data,
         | 
| 204 189 | 
             
                                             update_action_name="PATCH",
         | 
| 205 190 | 
             
                                             patch_delete_fields=args.delete,
         | 
| 206 191 | 
             
                                             noignore=args.noignore, ignore=args.ignore,
         | 
| @@ -210,7 +195,7 @@ def main(): | |
| 210 195 | 
             
                    _post_or_patch_or_upsert(portal=portal,
         | 
| 211 196 | 
             
                                             file_or_directory=args.upsert,
         | 
| 212 197 | 
             
                                             explicit_schema_name=explicit_schema_name,
         | 
| 213 | 
            -
                                             update_function= | 
| 198 | 
            +
                                             update_function=_upsert_data,
         | 
| 214 199 | 
             
                                             update_action_name="UPSERT",
         | 
| 215 200 | 
             
                                             patch_delete_fields=args.delete,
         | 
| 216 201 | 
             
                                             noignore=args.noignore, ignore=args.ignore,
         | 
| @@ -241,14 +226,6 @@ def _post_or_patch_or_upsert(portal: Portal, file_or_directory: str, | |
| 241 226 | 
             
                                         confirm: bool = False, verbose: bool = False,
         | 
| 242 227 | 
             
                                         quiet: bool = False, debug: bool = False) -> None:
         | 
| 243 228 |  | 
| 244 | 
            -
                def is_schema_name_list(portal: Portal, keys: list) -> bool:
         | 
| 245 | 
            -
                    if isinstance(keys, list):
         | 
| 246 | 
            -
                        for key in keys:
         | 
| 247 | 
            -
                            if portal.get_schema(key) is None:
         | 
| 248 | 
            -
                                return False
         | 
| 249 | 
            -
                            return True
         | 
| 250 | 
            -
                    return False
         | 
| 251 | 
            -
             | 
| 252 229 | 
             
                def post_or_patch_or_upsert(portal: Portal, file: str, schema_name: Optional[str],
         | 
| 253 230 | 
             
                                            patch_delete_fields: Optional[str] = None,
         | 
| 254 231 | 
             
                                            confirm: bool = False, verbose: bool = False,
         | 
| @@ -266,7 +243,7 @@ def _post_or_patch_or_upsert(portal: Portal, file_or_directory: str, | |
| 266 243 | 
             
                                                patch_delete_fields=patch_delete_fields,
         | 
| 267 244 | 
             
                                                noignore=noignore, ignore=ignore,
         | 
| 268 245 | 
             
                                                confirm=confirm, verbose=verbose, debug=debug)
         | 
| 269 | 
            -
                            elif  | 
| 246 | 
            +
                            elif _is_schema_name_list(portal, list(data.keys())):
         | 
| 270 247 | 
             
                                if debug:
         | 
| 271 248 | 
             
                                    _print(f"DEBUG: File ({file}) contains a dictionary of schema names.")
         | 
| 272 249 | 
             
                                for schema_name in data:
         | 
| @@ -329,11 +306,11 @@ def _impose_special_ordering(data: List[dict], schema_name: str) -> List[dict]: | |
| 329 306 | 
             
                return data
         | 
| 330 307 |  | 
| 331 308 |  | 
| 332 | 
            -
            def  | 
| 333 | 
            -
             | 
| 334 | 
            -
             | 
| 335 | 
            -
             | 
| 336 | 
            -
             | 
| 309 | 
            +
            def _post_data(portal: Portal, data: dict, schema_name: str,
         | 
| 310 | 
            +
                           file: Optional[str] = None, index: int = 0,
         | 
| 311 | 
            +
                           patch_delete_fields: Optional[str] = None,
         | 
| 312 | 
            +
                           noignore: bool = False, ignore: Optional[List[str]] = None,
         | 
| 313 | 
            +
                           confirm: bool = False, verbose: bool = False, debug: bool = False) -> None:
         | 
| 337 314 | 
             
                ignored(patch_delete_fields)
         | 
| 338 315 | 
             
                if not (identifying_path := portal.get_identifying_path(data, portal_type=schema_name)):
         | 
| 339 316 | 
             
                    if isinstance(file, str) and isinstance(index, int):
         | 
| @@ -359,11 +336,11 @@ def post_data(portal: Portal, data: dict, schema_name: str, | |
| 359 336 | 
             
                    return
         | 
| 360 337 |  | 
| 361 338 |  | 
| 362 | 
            -
            def  | 
| 363 | 
            -
             | 
| 364 | 
            -
             | 
| 365 | 
            -
             | 
| 366 | 
            -
             | 
| 339 | 
            +
            def _patch_data(portal: Portal, data: dict, schema_name: str,
         | 
| 340 | 
            +
                            file: Optional[str] = None, index: int = 0,
         | 
| 341 | 
            +
                            patch_delete_fields: Optional[str] = None,
         | 
| 342 | 
            +
                            noignore: bool = False, ignore: Optional[List[str]] = None,
         | 
| 343 | 
            +
                            confirm: bool = False, verbose: bool = False, debug: bool = False) -> None:
         | 
| 367 344 | 
             
                if not (identifying_path := portal.get_identifying_path(data, portal_type=schema_name)):
         | 
| 368 345 | 
             
                    if isinstance(file, str) and isinstance(index, int):
         | 
| 369 346 | 
             
                        _print(f"ERROR: Item for PATCH has no identifying property: {file} (#{index + 1})")
         | 
| @@ -390,11 +367,11 @@ def patch_data(portal: Portal, data: dict, schema_name: str, | |
| 390 367 | 
             
                    return
         | 
| 391 368 |  | 
| 392 369 |  | 
| 393 | 
            -
            def  | 
| 394 | 
            -
             | 
| 395 | 
            -
             | 
| 396 | 
            -
             | 
| 397 | 
            -
             | 
| 370 | 
            +
            def _upsert_data(portal: Portal, data: dict, schema_name: str,
         | 
| 371 | 
            +
                             file: Optional[str] = None, index: int = 0,
         | 
| 372 | 
            +
                             patch_delete_fields: Optional[str] = None,
         | 
| 373 | 
            +
                             noignore: bool = False, ignore: Optional[List[str]] = None,
         | 
| 374 | 
            +
                             confirm: bool = False, verbose: bool = False, debug: bool = False) -> None:
         | 
| 398 375 | 
             
                if not (identifying_path := portal.get_identifying_path(data, portal_type=schema_name)):
         | 
| 399 376 | 
             
                    if isinstance(file, str) and isinstance(index, int):
         | 
| 400 377 | 
             
                        _print(f"ERROR: Item for UPSERT has no identifying property: {file} (#{index + 1})")
         | 
| @@ -423,6 +400,188 @@ def upsert_data(portal: Portal, data: dict, schema_name: str, | |
| 423 400 | 
             
                    return
         | 
| 424 401 |  | 
| 425 402 |  | 
| 403 | 
            +
            def _load_data(load: str, ini_file: str, explicit_schema_name: Optional[str] = None,
         | 
| 404 | 
            +
                           verbose: bool = False, debug: bool = False, noprogress: bool = False) -> bool:
         | 
| 405 | 
            +
             | 
| 406 | 
            +
                from snovault.loadxl import load_all_gen, LoadGenWrapper
         | 
| 407 | 
            +
                from dcicutils.captured_output import captured_output
         | 
| 408 | 
            +
                from dcicutils.progress_bar import ProgressBar
         | 
| 409 | 
            +
             | 
| 410 | 
            +
                def loadxl(portal: Portal, inserts_directory: str, schema_names_to_load: dict):
         | 
| 411 | 
            +
             | 
| 412 | 
            +
                    nonlocal LoadGenWrapper, load_all_gen, verbose, debug
         | 
| 413 | 
            +
                    progress_total = sum(schema_names_to_load.values()) * 2  # loadxl does two passes
         | 
| 414 | 
            +
                    progress_bar = ProgressBar(progress_total) if not noprogress else None
         | 
| 415 | 
            +
             | 
| 416 | 
            +
                    def decode_bytes(str_or_bytes: Union[str, bytes], *, encoding: str = "utf-8") -> str:
         | 
| 417 | 
            +
                        if not isinstance(encoding, str):
         | 
| 418 | 
            +
                            encoding = "utf-8"
         | 
| 419 | 
            +
                        if isinstance(str_or_bytes, bytes):
         | 
| 420 | 
            +
                            return str_or_bytes.decode(encoding).strip()
         | 
| 421 | 
            +
                        elif isinstance(str_or_bytes, str):
         | 
| 422 | 
            +
                            return str_or_bytes.strip()
         | 
| 423 | 
            +
                        return ""
         | 
| 424 | 
            +
             | 
| 425 | 
            +
                    LOADXL_RESPONSE_PATTERN = re.compile(r"^([A-Z]+):\s*([a-zA-Z\/\d_-]+)\s*(\S+)\s*(\S+)?\s*(.*)$")
         | 
| 426 | 
            +
                    LOADXL_ACTION_NAME = {"POST": "Create", "PATCH": "Update", "SKIP": "Check",
         | 
| 427 | 
            +
                                          "CHECK": "Validate", "ERROR": "Error"}
         | 
| 428 | 
            +
                    current_item_type = None
         | 
| 429 | 
            +
                    current_item_count = 0
         | 
| 430 | 
            +
                    current_item_total = 0
         | 
| 431 | 
            +
                    total_item_count = 0
         | 
| 432 | 
            +
                    for item in LoadGenWrapper(load_all_gen(testapp=portal.vapp, inserts=inserts_directory,
         | 
| 433 | 
            +
                                                            docsdir=None, overwrite=True, verbose=True)):
         | 
| 434 | 
            +
                        total_item_count += 1
         | 
| 435 | 
            +
                        item = decode_bytes(item)
         | 
| 436 | 
            +
                        match = LOADXL_RESPONSE_PATTERN.match(item)
         | 
| 437 | 
            +
                        if not match or match.re.groups < 3:
         | 
| 438 | 
            +
                            continue
         | 
| 439 | 
            +
                        action = LOADXL_ACTION_NAME[match.group(1).upper()]
         | 
| 440 | 
            +
                        # response_value = match.group(0)
         | 
| 441 | 
            +
                        # identifying_value = match.group(2)
         | 
| 442 | 
            +
                        item_type = match.group(3)
         | 
| 443 | 
            +
                        if current_item_type != item_type:
         | 
| 444 | 
            +
                            if noprogress and debug and current_item_type is not None:
         | 
| 445 | 
            +
                                print()
         | 
| 446 | 
            +
                            current_item_type = item_type
         | 
| 447 | 
            +
                            current_item_count = 0
         | 
| 448 | 
            +
                            current_item_total = schema_names_to_load[item_type]
         | 
| 449 | 
            +
                            if progress_bar:
         | 
| 450 | 
            +
                                progress_bar.set_description(f"▶ {to_camel_case(current_item_type)}: {action}")
         | 
| 451 | 
            +
                        current_item_count += 1
         | 
| 452 | 
            +
                        if progress_bar:
         | 
| 453 | 
            +
                            progress_bar.set_progress(total_item_count)
         | 
| 454 | 
            +
                        elif debug:
         | 
| 455 | 
            +
                            print(f"{current_item_type}: {current_item_count} or {current_item_total} ({action})")
         | 
| 456 | 
            +
                    if progress_bar:
         | 
| 457 | 
            +
                        progress_bar.set_description("▶ Load Complete")
         | 
| 458 | 
            +
                        print()
         | 
| 459 | 
            +
             | 
| 460 | 
            +
                if not ini_file:
         | 
| 461 | 
            +
                    ini_file = _DEFAULT_INI_FILE_FOR_LOAD
         | 
| 462 | 
            +
                if not os.path.isabs(ini_file := os.path.expanduser(ini_file)):
         | 
| 463 | 
            +
                    ini_file = os.path.join(os.getcwd(), ini_file)
         | 
| 464 | 
            +
                if not os.path.exists(ini_file):
         | 
| 465 | 
            +
                    _print(f"The INI file required for --load is not found: {ini_file}")
         | 
| 466 | 
            +
                    exit(1)
         | 
| 467 | 
            +
             | 
| 468 | 
            +
                if not os.path.isabs(load := os.path.expanduser(load)):
         | 
| 469 | 
            +
                    load = os.path.join(os.getcwd(), load)
         | 
| 470 | 
            +
                if not os.path.exists(load):
         | 
| 471 | 
            +
                    return False
         | 
| 472 | 
            +
             | 
| 473 | 
            +
                if os.path.isdir(load):
         | 
| 474 | 
            +
                    inserts_directory = load
         | 
| 475 | 
            +
                    inserts_file = None
         | 
| 476 | 
            +
                else:
         | 
| 477 | 
            +
                    inserts_directory = None
         | 
| 478 | 
            +
                    inserts_file = load
         | 
| 479 | 
            +
             | 
| 480 | 
            +
                portal = None
         | 
| 481 | 
            +
                with captured_output(not debug):
         | 
| 482 | 
            +
                    portal = Portal(ini_file)
         | 
| 483 | 
            +
             | 
| 484 | 
            +
                if inserts_file:
         | 
| 485 | 
            +
                    with io.open(inserts_file, "r") as f:
         | 
| 486 | 
            +
                        try:
         | 
| 487 | 
            +
                            data = json.load(f)
         | 
| 488 | 
            +
                        except Exception:
         | 
| 489 | 
            +
                            _print(f"Cannot load JSON data from file: {inserts_file}")
         | 
| 490 | 
            +
                            return False
         | 
| 491 | 
            +
                        if isinstance(data, list):
         | 
| 492 | 
            +
                            if not (schema_name := explicit_schema_name):
         | 
| 493 | 
            +
                                if not (schema_name := _get_schema_name_from_schema_named_json_file_name(portal, inserts_file)):
         | 
| 494 | 
            +
                                    _print("Unable to determine schema name for JSON data file: {inserts_file}")
         | 
| 495 | 
            +
                                    return False
         | 
| 496 | 
            +
                            with temporary_directory() as tmpdir:
         | 
| 497 | 
            +
                                file_name = os.path.join(tmpdir, f"{to_snake_case(schema_name)}.json")
         | 
| 498 | 
            +
                                with io.open(file_name, "w") as f:
         | 
| 499 | 
            +
                                    json.dump(data, f)
         | 
| 500 | 
            +
                                return _load_data(load=tmpdir, ini_file=ini_file, explicit_schema_name=explicit_schema_name,
         | 
| 501 | 
            +
                                                  verbose=verbose, debug=debug, noprogress=noprogress)
         | 
| 502 | 
            +
                        elif isinstance(data, dict):
         | 
| 503 | 
            +
                            _print("DICT IN FILE FOR LOAD NOT YET SUPPPORTED")
         | 
| 504 | 
            +
                            if not _is_schema_name_list(portal, schema_names := list(data.keys())):
         | 
| 505 | 
            +
                                _print(f"Unrecognized types in JSON data file: {inserts_file}")
         | 
| 506 | 
            +
                                return False
         | 
| 507 | 
            +
                            with temporary_directory() as tmpdir:
         | 
| 508 | 
            +
                                nfiles = 0
         | 
| 509 | 
            +
                                for schema_name in schema_names:
         | 
| 510 | 
            +
                                    if not isinstance(schema_data := data[schema_name], list):
         | 
| 511 | 
            +
                                        _print(f"Unexpected value for data type ({schema_name})"
         | 
| 512 | 
            +
                                               f" in JSON data file: {inserts_file} ▶ ignoring")
         | 
| 513 | 
            +
                                        continue
         | 
| 514 | 
            +
                                    file_name = os.path.join(tmpdir, f"{to_snake_case(schema_name)}.json")
         | 
| 515 | 
            +
                                    with io.open(file_name, "w") as f:
         | 
| 516 | 
            +
                                        json.dump(schema_data, f)
         | 
| 517 | 
            +
                                    nfiles += 1
         | 
| 518 | 
            +
                                if nfiles > 0:
         | 
| 519 | 
            +
                                    return _load_data(load=tmpdir, ini_file=ini_file,
         | 
| 520 | 
            +
                                                      verbose=verbose, debug=debug, noprogress=noprogress)
         | 
| 521 | 
            +
                            # TODO
         | 
| 522 | 
            +
                            return True
         | 
| 523 | 
            +
                        else:
         | 
| 524 | 
            +
                            _print(f"Unrecognized JSON data in file: {inserts_file}")
         | 
| 525 | 
            +
                            return False
         | 
| 526 | 
            +
                    return True
         | 
| 527 | 
            +
                if verbose:
         | 
| 528 | 
            +
                    _print(f"Loading data files into Portal (via snovault.loadxl) from: {inserts_directory}")
         | 
| 529 | 
            +
                    _print(f"Portal INI file for load is: {ini_file}")
         | 
| 530 | 
            +
             | 
| 531 | 
            +
                schema_names = list(_get_schemas(portal).keys())
         | 
| 532 | 
            +
                schema_snake_case_names = [to_snake_case(item) for item in schema_names]
         | 
| 533 | 
            +
                schema_names_to_load = {}
         | 
| 534 | 
            +
             | 
| 535 | 
            +
                copy_to_temporary_directory = False
         | 
| 536 | 
            +
                for json_file_path in glob.glob(os.path.join(inserts_directory, "*.json")):
         | 
| 537 | 
            +
                    json_file_name = os.path.basename(json_file_path)
         | 
| 538 | 
            +
                    schema_name = os.path.basename(json_file_name)[:-len(".json")]
         | 
| 539 | 
            +
                    if (schema_name not in schema_snake_case_names) and (schema_name not in schema_names):
         | 
| 540 | 
            +
                        _print(f"File is not named for a known schema: {json_file_name} ▶ ignoring")
         | 
| 541 | 
            +
                        copy_to_temporary_directory = True
         | 
| 542 | 
            +
                    else:
         | 
| 543 | 
            +
                        try:
         | 
| 544 | 
            +
                            with io.open(json_file_path, "r") as f:
         | 
| 545 | 
            +
                                if not isinstance(data := json.load(f), list):
         | 
| 546 | 
            +
                                    _print("Data JSON file does not contain an array: {json_file_path} ▶ ignoring")
         | 
| 547 | 
            +
                                    copy_to_temporary_directory = True
         | 
| 548 | 
            +
                                elif (nobjects := len(data)) < 1:
         | 
| 549 | 
            +
                                    _print("Data JSON file contains no items: {json_file_path} ▶ ignoring")
         | 
| 550 | 
            +
                                    copy_to_temporary_directory = True
         | 
| 551 | 
            +
                                else:
         | 
| 552 | 
            +
                                    schema_names_to_load[schema_name] = nobjects
         | 
| 553 | 
            +
                        except Exception:
         | 
| 554 | 
            +
                            _print("Cannot load JSON data from file: {json_file_path} ▶ ignoring")
         | 
| 555 | 
            +
                            copy_to_temporary_directory = True
         | 
| 556 | 
            +
                if not schema_names_to_load:
         | 
| 557 | 
            +
                    _print("Directory contains no valid data: {inserts_directory}")
         | 
| 558 | 
            +
                    return False
         | 
| 559 | 
            +
                if copy_to_temporary_directory:
         | 
| 560 | 
            +
                    with temporary_directory() as tmpdir:
         | 
| 561 | 
            +
                        if debug:
         | 
| 562 | 
            +
                            _print(f"Using temporary directory: {tmpdir}")
         | 
| 563 | 
            +
                        for json_file_path in glob.glob(os.path.join(inserts_directory, "*.json")):
         | 
| 564 | 
            +
                            json_file_name = os.path.basename(json_file_path)
         | 
| 565 | 
            +
                            schema_name = os.path.basename(json_file_name)[:-len(".json")]
         | 
| 566 | 
            +
                            if (schema_name in schema_snake_case_names) or (schema_name in schema_names):
         | 
| 567 | 
            +
                                shutil.copy(json_file_path, tmpdir)
         | 
| 568 | 
            +
                        loadxl(portal=portal, inserts_directory=tmpdir, schema_names_to_load=schema_names_to_load)
         | 
| 569 | 
            +
                else:
         | 
| 570 | 
            +
                    loadxl(portal=portal, inserts_directory=inserts_directory, schema_names_to_load=schema_names_to_load)
         | 
| 571 | 
            +
                if verbose:
         | 
| 572 | 
            +
                    _print(f"Done loading data into Portal (via snovault.loadxl) files from: {inserts_directory}")
         | 
| 573 | 
            +
                return True
         | 
| 574 | 
            +
             | 
| 575 | 
            +
             | 
| 576 | 
            +
            def _is_schema_name_list(portal: Portal, keys: list) -> bool:
         | 
| 577 | 
            +
                if isinstance(keys, list):
         | 
| 578 | 
            +
                    for key in keys:
         | 
| 579 | 
            +
                        if portal.get_schema(key) is None:
         | 
| 580 | 
            +
                            return False
         | 
| 581 | 
            +
                        return True
         | 
| 582 | 
            +
                return False
         | 
| 583 | 
            +
             | 
| 584 | 
            +
             | 
| 426 585 | 
             
            def _prune_data_for_update(data: dict, noignore: bool = False, ignore: Optional[List[str]] = None) -> dict:
         | 
| 427 586 | 
             
                ignore_these_properties = [] if noignore is True else _IGNORE_PROPERTIES_ON_UPDATE
         | 
| 428 587 | 
             
                if isinstance(ignore, list):
         | 
| @@ -498,17 +657,21 @@ def _parse_delete_fields(value: str) -> str: | |
| 498 657 |  | 
| 499 658 |  | 
| 500 659 | 
             
            def _get_schema_name_from_schema_named_json_file_name(portal: Portal, value: str) -> Optional[str]:
         | 
| 501 | 
            -
                 | 
| 502 | 
            -
                     | 
| 503 | 
            -
                         | 
| 504 | 
            -
             | 
| 505 | 
            -
             | 
| 506 | 
            -
             | 
| 507 | 
            -
                     | 
| 660 | 
            +
                if isinstance(value, str) and value:
         | 
| 661 | 
            +
                    try:
         | 
| 662 | 
            +
                        if value.endswith(".json"):
         | 
| 663 | 
            +
                            value = value[:-5]
         | 
| 664 | 
            +
                        _, schema_name = _get_schema(portal, os.path.basename(value))
         | 
| 665 | 
            +
                        return schema_name
         | 
| 666 | 
            +
                    except Exception:
         | 
| 667 | 
            +
                        pass
         | 
| 668 | 
            +
                return False
         | 
| 508 669 |  | 
| 509 670 |  | 
| 510 671 | 
             
            @lru_cache(maxsize=1)
         | 
| 511 672 | 
             
            def _get_schemas(portal: Portal) -> Optional[dict]:
         | 
| 673 | 
            +
                if portal.vapp:
         | 
| 674 | 
            +
                    return portal.vapp.get("/profiles/?frame=raw").json
         | 
| 512 675 | 
             
                return portal.get_schemas()
         | 
| 513 676 |  | 
| 514 677 |  | 
| @@ -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= | 
| 63 | 
            +
            dcicutils/scripts/update_portal_object.py,sha256=fLgsPgnugKLS18A8JwP8O_UdmeFqNIjUIhrEFlIhfgE,32589
         | 
| 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. | 
| 79 | 
            -
            dcicutils-8.14.0. | 
| 80 | 
            -
            dcicutils-8.14.0. | 
| 81 | 
            -
            dcicutils-8.14.0. | 
| 82 | 
            -
            dcicutils-8.14.0. | 
| 78 | 
            +
            dcicutils-8.14.0.1b11.dist-info/LICENSE.txt,sha256=qnwSmfnEWMl5l78VPDEzAmEbLVrRqQvfUQiHT0ehrOo,1102
         | 
| 79 | 
            +
            dcicutils-8.14.0.1b11.dist-info/METADATA,sha256=HFNj87yKbAwTA98cVDJm_0r9aVJssg7zo5dIsqngVrg,3440
         | 
| 80 | 
            +
            dcicutils-8.14.0.1b11.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
         | 
| 81 | 
            +
            dcicutils-8.14.0.1b11.dist-info/entry_points.txt,sha256=W6kEWdUJk9tQ4myAgpehPdebcwvCAZ7UgB-wyPgDUMg,335
         | 
| 82 | 
            +
            dcicutils-8.14.0.1b11.dist-info/RECORD,,
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         |