dcicutils 8.9.0.1b2__py3-none-any.whl → 8.9.0.1b5__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 +41 -10
- dcicutils/structured_data.py +5 -6
- {dcicutils-8.9.0.1b2.dist-info → dcicutils-8.9.0.1b5.dist-info}/METADATA +1 -1
- {dcicutils-8.9.0.1b2.dist-info → dcicutils-8.9.0.1b5.dist-info}/RECORD +7 -7
- {dcicutils-8.9.0.1b2.dist-info → dcicutils-8.9.0.1b5.dist-info}/LICENSE.txt +0 -0
- {dcicutils-8.9.0.1b2.dist-info → dcicutils-8.9.0.1b5.dist-info}/WHEEL +0 -0
- {dcicutils-8.9.0.1b2.dist-info → dcicutils-8.9.0.1b5.dist-info}/entry_points.txt +0 -0
dcicutils/misc_utils.py
CHANGED
@@ -4,6 +4,7 @@ This file contains functions that might be generally useful.
|
|
4
4
|
|
5
5
|
from collections import namedtuple
|
6
6
|
import appdirs
|
7
|
+
from copy import deepcopy
|
7
8
|
import contextlib
|
8
9
|
import datetime
|
9
10
|
import functools
|
@@ -2199,28 +2200,58 @@ def merge_key_value_dict_lists(x, y):
|
|
2199
2200
|
return [key_value_dict(k, v) for k, v in merged.items()]
|
2200
2201
|
|
2201
2202
|
|
2202
|
-
def merge_objects(target: Union[dict, List[Any]], source: Union[dict, List[Any]],
|
2203
|
+
def merge_objects(target: Union[dict, List[Any]], source: Union[dict, List[Any]],
|
2204
|
+
full: bool = False, # deprecated
|
2205
|
+
expand_lists: Optional[bool] = None,
|
2206
|
+
primitive_lists: bool = False,
|
2207
|
+
copy: bool = False, _recursing: bool = False) -> Union[dict, List[Any]]:
|
2203
2208
|
"""
|
2204
|
-
Merges the given source dictionary or list into the target dictionary or list
|
2205
|
-
This MAY well change the given target (dictionary or list) IN PLACE
|
2206
|
-
|
2207
|
-
|
2209
|
+
Merges the given source dictionary or list into the target dictionary or list and returns the
|
2210
|
+
result. This MAY well change the given target (dictionary or list) IN PLACE ... UNLESS the copy
|
2211
|
+
argument is True, then the given target will not change as a local copy is made (and returned).
|
2212
|
+
|
2213
|
+
If the expand_lists argument is True then any target lists longer than the
|
2214
|
+
source be will be filled out with the last element(s) of the source; the full
|
2215
|
+
argument (is deprecated and) is a synomym for this. The default is False.
|
2216
|
+
|
2217
|
+
If the primitive_lists argument is True then lists of primitives (i.e. lists in which
|
2218
|
+
NONE of its elements are dictionaries, lists, or tuples) will themselves be treated
|
2219
|
+
like primitives, meaning the whole of a source list will replace the corresponding
|
2220
|
+
target; otherwise they will be merged normally, meaning each element of a source list
|
2221
|
+
will be merged, recursively, into the corresponding target list. The default is False.
|
2208
2222
|
"""
|
2223
|
+
def is_primitive_list(value: Any) -> bool: # noqa
|
2224
|
+
if not isinstance(value, list):
|
2225
|
+
return False
|
2226
|
+
for item in value:
|
2227
|
+
if isinstance(item, (dict, list, tuple)):
|
2228
|
+
return False
|
2229
|
+
return True
|
2230
|
+
|
2209
2231
|
if target is None:
|
2210
2232
|
return source
|
2233
|
+
if expand_lists not in (True, False):
|
2234
|
+
expand_lists = full is True
|
2235
|
+
if (copy is True) and (_recursing is not True):
|
2236
|
+
target = deepcopy(target)
|
2211
2237
|
if isinstance(target, dict) and isinstance(source, dict) and source:
|
2212
2238
|
for key, value in source.items():
|
2213
|
-
|
2239
|
+
if ((primitive_lists is True) and
|
2240
|
+
(key in target) and is_primitive_list(target[key]) and is_primitive_list(value)): # noqa
|
2241
|
+
target[key] = value
|
2242
|
+
else:
|
2243
|
+
target[key] = merge_objects(target[key], value,
|
2244
|
+
expand_lists=expand_lists, _recursing=True) if key in target else value
|
2214
2245
|
elif isinstance(target, list) and isinstance(source, list) and source:
|
2215
2246
|
for i in range(max(len(source), len(target))):
|
2216
2247
|
if i < len(target):
|
2217
2248
|
if i < len(source):
|
2218
|
-
target[i] = merge_objects(target[i], source[i],
|
2219
|
-
elif
|
2220
|
-
target[i] = merge_objects(target[i], source[len(source) - 1],
|
2249
|
+
target[i] = merge_objects(target[i], source[i], expand_lists=expand_lists, _recursing=True)
|
2250
|
+
elif expand_lists is True:
|
2251
|
+
target[i] = merge_objects(target[i], source[len(source) - 1], expand_lists=expand_lists)
|
2221
2252
|
else:
|
2222
2253
|
target.append(source[i])
|
2223
|
-
elif source:
|
2254
|
+
elif source not in (None, {}, []):
|
2224
2255
|
target = source
|
2225
2256
|
return target
|
2226
2257
|
|
dcicutils/structured_data.py
CHANGED
@@ -74,7 +74,7 @@ class StructuredDataSet:
|
|
74
74
|
self._nrows = 0
|
75
75
|
self._autoadd_properties = autoadd if isinstance(autoadd, dict) and autoadd else None
|
76
76
|
self._norefs = True if norefs is True else False
|
77
|
-
self._merge = True if merge is True else False
|
77
|
+
self._merge = True if merge is True else False # New merge functionality (2024-05-25)
|
78
78
|
self._debug_sleep = None
|
79
79
|
if debug_sleep:
|
80
80
|
try:
|
@@ -347,7 +347,7 @@ class StructuredDataSet:
|
|
347
347
|
(self._portal.get_schema(schema_name_inferred_from_file_name) is not None)): # noqa
|
348
348
|
# If the JSON file name looks like a schema name then assume it
|
349
349
|
# contains an object or an array of object of that schema type.
|
350
|
-
if self._merge:
|
350
|
+
if self._merge: # New merge functionality (2024-05-25)
|
351
351
|
data = self._merge_with_existing_portal_object(data, schema_name_inferred_from_file_name)
|
352
352
|
self._add(Schema.type_name(file), data)
|
353
353
|
elif isinstance(data, dict):
|
@@ -356,7 +356,7 @@ class StructuredDataSet:
|
|
356
356
|
# which (each property) contains a list of object of that schema type.
|
357
357
|
for schema_name in data:
|
358
358
|
item = data[schema_name]
|
359
|
-
if self._merge:
|
359
|
+
if self._merge: # New merge functionality (2024-05-25)
|
360
360
|
item = self._merge_with_existing_portal_object(item, schema_name)
|
361
361
|
self._add(schema_name, item)
|
362
362
|
|
@@ -380,8 +380,7 @@ class StructuredDataSet:
|
|
380
380
|
structured_row_template.set_value(structured_row, column_name, value, reader.file, reader.row_number)
|
381
381
|
if self._autoadd_properties:
|
382
382
|
self._add_properties(structured_row, self._autoadd_properties, schema)
|
383
|
-
# New merge functionality (2024-05-25)
|
384
|
-
if self._merge:
|
383
|
+
if self._merge: # New merge functionality (2024-05-25)
|
385
384
|
structured_row = self._merge_with_existing_portal_object(structured_row, schema_name)
|
386
385
|
if (prune_error := self._prune_structured_row(structured_row)) is not None:
|
387
386
|
self._note_error({"src": create_dict(type=schema_name, row=reader.row_number),
|
@@ -437,7 +436,7 @@ class StructuredDataSet:
|
|
437
436
|
"""
|
438
437
|
for identifying_path in self._portal.get_identifying_paths(portal_object, portal_type):
|
439
438
|
if existing_portal_object := self._portal.get_metadata(identifying_path, raw=True, raise_exception=False):
|
440
|
-
return merge_objects(existing_portal_object, portal_object)
|
439
|
+
return merge_objects(existing_portal_object, portal_object, primitive_lists=True)
|
441
440
|
return portal_object
|
442
441
|
|
443
442
|
def _is_ref_lookup_specified_type(ref_lookup_flags: int) -> bool:
|
@@ -44,7 +44,7 @@ dcicutils/license_policies/park-lab-gpl-pipeline.jsonc,sha256=vLZkwm3Js-kjV44nug
|
|
44
44
|
dcicutils/license_policies/park-lab-pipeline.jsonc,sha256=9qlY0ASy3iUMQlr3gorVcXrSfRHnVGbLhkS427UaRy4,283
|
45
45
|
dcicutils/license_utils.py,sha256=d1cq6iwv5Ju-VjdoINi6q7CPNNL7Oz6rcJdLMY38RX0,46978
|
46
46
|
dcicutils/log_utils.py,sha256=7pWMc6vyrorUZQf-V-M3YC6zrPgNhuV_fzm9xqTPph0,10883
|
47
|
-
dcicutils/misc_utils.py,sha256
|
47
|
+
dcicutils/misc_utils.py,sha256=-syqTAj8DESiiP_KHoyBv9VvfboFYB03QbBlmXnBZXw,109423
|
48
48
|
dcicutils/obfuscation_utils.py,sha256=fo2jOmDRC6xWpYX49u80bVNisqRRoPskFNX3ymFAmjw,5963
|
49
49
|
dcicutils/opensearch_utils.py,sha256=V2exmFYW8Xl2_pGFixF4I2Cc549Opwe4PhFi5twC0M8,1017
|
50
50
|
dcicutils/portal_object_utils.py,sha256=Az3n1aL-PQkN5gOFE6ZqC2XkYsqiwKlq7-tZggs1QN4,11062
|
@@ -64,7 +64,7 @@ dcicutils/secrets_utils.py,sha256=8dppXAsiHhJzI6NmOcvJV5ldvKkQZzh3Fl-cb8Wm7MI,19
|
|
64
64
|
dcicutils/sheet_utils.py,sha256=VlmzteONW5VF_Q4vo0yA5vesz1ViUah1MZ_yA1rwZ0M,33629
|
65
65
|
dcicutils/snapshot_utils.py,sha256=ymP7PXH6-yEiXAt75w0ldQFciGNqWBClNxC5gfX2FnY,22961
|
66
66
|
dcicutils/ssl_certificate_utils.py,sha256=F0ifz_wnRRN9dfrfsz7aCp4UDLgHEY8LaK7PjnNvrAQ,9707
|
67
|
-
dcicutils/structured_data.py,sha256=
|
67
|
+
dcicutils/structured_data.py,sha256=HVe1ruXz0vH4nRBOwq0cNrfR4KtqocC4U940KRXM5zY,64160
|
68
68
|
dcicutils/submitr/progress_constants.py,sha256=5bxyX77ql8qEJearfHEvsvXl7D0GuUODW0T65mbRmnE,2895
|
69
69
|
dcicutils/submitr/ref_lookup_strategy.py,sha256=VJN-Oo0LLna6Vo2cu47eC-eU-yUC9NFlQP29xajejVU,4741
|
70
70
|
dcicutils/task_utils.py,sha256=MF8ujmTD6-O2AC2gRGPHyGdUrVKgtr8epT5XU8WtNjk,8082
|
@@ -73,8 +73,8 @@ dcicutils/trace_utils.py,sha256=g8kwV4ebEy5kXW6oOrEAUsurBcCROvwtZqz9fczsGRE,1769
|
|
73
73
|
dcicutils/validation_utils.py,sha256=cMZIU2cY98FYtzK52z5WUYck7urH6JcqOuz9jkXpqzg,14797
|
74
74
|
dcicutils/variant_utils.py,sha256=2H9azNx3xAj-MySg-uZ2SFqbWs4kZvf61JnK6b-h4Qw,4343
|
75
75
|
dcicutils/zip_utils.py,sha256=_Y9EmL3D2dUZhxucxHvrtmmlbZmK4FpSsHEb7rGSJLU,3265
|
76
|
-
dcicutils-8.9.0.
|
77
|
-
dcicutils-8.9.0.
|
78
|
-
dcicutils-8.9.0.
|
79
|
-
dcicutils-8.9.0.
|
80
|
-
dcicutils-8.9.0.
|
76
|
+
dcicutils-8.9.0.1b5.dist-info/LICENSE.txt,sha256=qnwSmfnEWMl5l78VPDEzAmEbLVrRqQvfUQiHT0ehrOo,1102
|
77
|
+
dcicutils-8.9.0.1b5.dist-info/METADATA,sha256=YTZR9PRzIbTMoeiRjoZD6mKgIDpZFgQmig1EJXLYoN8,3439
|
78
|
+
dcicutils-8.9.0.1b5.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
|
79
|
+
dcicutils-8.9.0.1b5.dist-info/entry_points.txt,sha256=51Q4F_2V10L0282W7HFjP4jdzW4K8lnWDARJQVFy_hw,270
|
80
|
+
dcicutils-8.9.0.1b5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|