dcicutils 8.7.0.1b36__py3-none-any.whl → 8.7.0.1b37__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.
@@ -1,8 +1,6 @@
1
1
  from functools import lru_cache
2
- import re
3
- from typing import Any, Callable, List, Optional, Tuple, Type, Union
2
+ from typing import List, Optional, Tuple, Type, Union
4
3
  from dcicutils.portal_utils import Portal
5
- from dcicutils.schema_utils import Schema
6
4
 
7
5
  PortalObject = Type["PortalObject"] # Forward type reference for type hints.
8
6
 
@@ -112,64 +110,3 @@ class PortalObject:
112
110
  except Exception:
113
111
  pass
114
112
  return None, self.identifying_path
115
-
116
- def compare(self, value: Union[dict, PortalObject], consider_link_to: bool = False) -> dict:
117
- """
118
- Compares this Portal object against the given Portal object value; noting differences values of properites
119
- which they have in common; and properties which are in this Portal object and not in the given Portal object;
120
- we do NOT check the converse, i.e. properties in the given Portal object which are not in this Portal object.
121
- Returns a dictionary with a description of the differences. If the given consider_link_to flag is True then
122
- TODO.
123
- """
124
- def are_properties_equal(property_path: str, property_value_a: Any, property_value_b: Any) -> bool:
125
- if property_value_a == property_value_b:
126
- return True
127
- nonlocal self
128
- if (schema := self.schema) and (property_type := Schema.get_property_by_path(schema, property_path)):
129
- if link_to := property_type.get("linkTo"):
130
- """
131
- This works basically except not WRT sub/super-types (e.g. CellCultureSample vs Sample);
132
- this is only preferable as it only requires one Portal GET rather than two, as below.
133
- if (a := self._portal.get(f"/{link_to}/{property_value_a}")) and (a.status_code == 200):
134
- if a_identifying_paths := PortalObject(self._portal, a.json()).identifying_paths:
135
- if f"/{link_to}/{property_value_b}" in a_identifying_paths:
136
- return True
137
- """
138
- if a := self._portal.get(f"/{link_to}/{property_value_a}", raw=True):
139
- if (a.status_code == 200) and (a := a.json()):
140
- if b := self._portal.get(f"/{link_to}/{property_value_b}", raw=True):
141
- if (b.status_code == 200) and (b := b.json()):
142
- return a == b
143
- return False
144
- return PortalObject._compare(self._data, value.data if isinstance(value, PortalObject) else value,
145
- compare=are_properties_equal if consider_link_to else None)
146
-
147
- _ARRAY_KEY_REGULAR_EXPRESSION = re.compile(rf"^({Schema._ARRAY_NAME_SUFFIX_CHAR}\d+)$")
148
-
149
- @staticmethod
150
- def _compare(a: dict, b: dict, compare: Optional[Callable] = None, _path: Optional[str] = None) -> dict:
151
- def key_to_path(key: str) -> Optional[str]: # noqa
152
- nonlocal _path
153
- if match := PortalObject._ARRAY_KEY_REGULAR_EXPRESSION.search(key):
154
- return f"{_path}{match.group(1)}" if _path else match.group(1)
155
- return f"{_path}.{key}" if _path else key
156
- def list_to_dictionary(value: list) -> dict: # noqa
157
- result = {}
158
- for index, item in enumerate(sorted(value)): # ignore array order
159
- result[f"#{index}"] = item
160
- return result
161
- diffs = {}
162
- for key in a:
163
- path = key_to_path(key)
164
- if key not in b:
165
- diffs[path] = {"value": a[key], "missing_value": True}
166
- else:
167
- if isinstance(a[key], dict) and isinstance(b[key], dict):
168
- diffs.update(PortalObject._compare(a[key], b[key], compare=compare, _path=path))
169
- elif isinstance(a[key], list) and isinstance(b[key], list):
170
- diffs.update(PortalObject._compare(list_to_dictionary(a[key]),
171
- list_to_dictionary(b[key]), compare=compare, _path=path))
172
- elif a[key] != b[key]:
173
- if not callable(compare) or not compare(path, a[key], b[key]):
174
- diffs[path] = {"value": a[key], "differing_value": b[key]}
175
- return diffs
dcicutils/schema_utils.py CHANGED
@@ -1,6 +1,4 @@
1
- import os
2
- from typing import Any, Dict, List, Optional, Tuple
3
- from dcicutils.misc_utils import to_camel_case
1
+ from typing import Any, Dict, List
4
2
 
5
3
 
6
4
  class JsonSchemaConstants:
@@ -185,85 +183,3 @@ def get_one_of_formats(schema: Dict[str, Any]) -> List[str]:
185
183
  for one_of_schema in get_one_of(schema)
186
184
  if get_format(one_of_schema)
187
185
  ]
188
-
189
-
190
- class Schema:
191
-
192
- def __init__(self, schema: dict, schema_type: Optional[str] = None) -> None:
193
- self._data = schema if isinstance(schema, dict) else (schema.data if isinstance(schema, Schema) else {})
194
- self._type = (isinstance(schema_type, str) and schema_type) or Schema.type_name(self._data.get("title", ""))
195
-
196
- @property
197
- def data(self) -> dict:
198
- return self._data
199
-
200
- @property
201
- def type(self) -> str:
202
- return self._type
203
-
204
- @staticmethod
205
- def type_name(value: str) -> Optional[str]: # File or other name.
206
- if isinstance(value, str) and (value := os.path.basename(value.replace(" ", ""))):
207
- return to_camel_case(value[0:dot] if (dot := value.rfind(".")) >= 0 else value)
208
-
209
- def property_by_path(self, property_path: str) -> Optional[dict]:
210
- """
211
- Looks for the given property path within this Portal schema and returns its dictionary value.
212
- This given property path can be either a simple property name, or a series of dot-separated
213
- property names representing nested (object) properties; and/or the property names may be
214
- suffixed with a pound (#) characteter, optionally followed by an integer, representing an
215
- array type property and its optional array index (this integer, if specified, is ignored
216
- for the purposes of this function, but it may have been created by another process/function,
217
- for example by PortalObject.compare). If the property is not found then None is returned.
218
- """
219
- return Schema.get_property_by_path(self._data, property_path)
220
-
221
- _ARRAY_NAME_SUFFIX_CHAR = "#"
222
- _DOTTED_NAME_DELIMITER_CHAR = "."
223
-
224
- @staticmethod
225
- def get_property_by_path(schema: dict, property_path: str) -> Optional[dict]:
226
- if not isinstance(schema, dict) or not isinstance(property_path, str):
227
- return None
228
- elif not (schema_properties := schema.get("properties")):
229
- return None
230
- property_paths = property_path.split(Schema._DOTTED_NAME_DELIMITER_CHAR)
231
- for property_index, property_name in enumerate(property_paths):
232
- property_name, array_specifiers = Schema._unarrayize_property_name(property_name)
233
- if not (property_value := schema_properties.get(property_name)):
234
- return None
235
- elif (property_type := property_value.get("type")) == "object":
236
- property_paths_tail = Schema._DOTTED_NAME_DELIMITER_CHAR.join(property_paths[property_index + 1:])
237
- return Schema.get_property_by_path(property_value, property_paths_tail)
238
- elif (property_type := property_value.get("type")) == "array":
239
- if not array_specifiers:
240
- if property_index == len(property_paths) - 1:
241
- return property_value
242
- return None
243
- for array_index in range(len(array_specifiers)):
244
- if property_type != "array":
245
- return None
246
- elif not (array_items := property_value.get("items")):
247
- return None
248
- property_type = (property_value := array_items).get("type")
249
- if property_type == "object":
250
- if property_index == len(property_paths) - 1:
251
- return property_value
252
- property_paths_tail = Schema._DOTTED_NAME_DELIMITER_CHAR.join(property_paths[property_index + 1:])
253
- return Schema.get_property_by_path(property_value, property_paths_tail)
254
- return property_value
255
-
256
- @staticmethod
257
- def _unarrayize_property_name(property_name: str) -> Tuple[str, Optional[List[int]]]:
258
- if len(components := (property_name := property_name.strip()).split(Schema._ARRAY_NAME_SUFFIX_CHAR)) < 2:
259
- return property_name, None
260
- unarrayized_property_name = components[0].strip()
261
- array_specifiers = []
262
- for component in components[1:]:
263
- if component.isdigit():
264
- array_specifiers.append(int(component))
265
- elif component == "":
266
- array_specifiers.append(0)
267
- else:
268
- return property_name, None
269
- return unarrayized_property_name, array_specifiers
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dcicutils
3
- Version: 8.7.0.1b36
3
+ Version: 8.7.0.1b37
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
@@ -44,7 +44,7 @@ dcicutils/log_utils.py,sha256=7pWMc6vyrorUZQf-V-M3YC6zrPgNhuV_fzm9xqTPph0,10883
44
44
  dcicutils/misc_utils.py,sha256=bMRWWxdbhuF3PKdCZEH-H4U1ecgT3Nag3EL92D9XGoY,100973
45
45
  dcicutils/obfuscation_utils.py,sha256=fo2jOmDRC6xWpYX49u80bVNisqRRoPskFNX3ymFAmjw,5963
46
46
  dcicutils/opensearch_utils.py,sha256=V2exmFYW8Xl2_pGFixF4I2Cc549Opwe4PhFi5twC0M8,1017
47
- dcicutils/portal_object_utils.py,sha256=I2uw-aqgEkkPQhn_OcjlBRxxP5yuZXm1WMaxOjOjmW8,9105
47
+ dcicutils/portal_object_utils.py,sha256=P8KW0ASWhac8u0Ddzt-uuQ2LFKAEwCrb7ORMsQNJ8HI,5199
48
48
  dcicutils/portal_utils.py,sha256=jKYgZUYVdkg6VOs1hsiX4bSULLguOIBJFFRpvvZEklU,26704
49
49
  dcicutils/project_utils.py,sha256=qPdCaFmWUVBJw4rw342iUytwdQC0P-XKpK4mhyIulMM,31250
50
50
  dcicutils/qa_checkers.py,sha256=cdXjeL0jCDFDLT8VR8Px78aS10hwNISOO5G_Zv2TZ6M,20534
@@ -52,7 +52,7 @@ dcicutils/qa_utils.py,sha256=TT0SiJWiuxYvbsIyhK9VO4uV_suxhB6CpuC4qPacCzQ,160208
52
52
  dcicutils/redis_tools.py,sha256=qkcSNMtvqkpvts-Cm9gWhneK523Q_oHwhNUud1be1qk,7055
53
53
  dcicutils/redis_utils.py,sha256=VJ-7g8pOZqR1ZCtdcjKz3-6as2DMUcs1b1zG6wSprH4,6462
54
54
  dcicutils/s3_utils.py,sha256=LauLFQGvZLfpBJ81tYMikjLd3SJRz2R_FrL1n4xSlyI,28868
55
- dcicutils/schema_utils.py,sha256=jitlaKKsskZKg8PXIc702j4nTvuC5t0Nq8cB1QYyOi4,9850
55
+ dcicutils/schema_utils.py,sha256=3Gd9QboOjQ3FHFawerylvYYU8Lor1Ma2pFv4JmezCdg,5501
56
56
  dcicutils/scripts/publish_to_pypi.py,sha256=LFzNHIQK2EXFr88YcfctyA_WKEBFc1ElnSjWrCXedPM,13889
57
57
  dcicutils/scripts/run_license_checker.py,sha256=z2keYnRDZsHQbTeo1XORAXSXNJK5axVzL5LjiNqZ7jE,4184
58
58
  dcicutils/secrets_utils.py,sha256=8dppXAsiHhJzI6NmOcvJV5ldvKkQZzh3Fl-cb8Wm7MI,19745
@@ -66,8 +66,8 @@ dcicutils/trace_utils.py,sha256=g8kwV4ebEy5kXW6oOrEAUsurBcCROvwtZqz9fczsGRE,1769
66
66
  dcicutils/validation_utils.py,sha256=cMZIU2cY98FYtzK52z5WUYck7urH6JcqOuz9jkXpqzg,14797
67
67
  dcicutils/variant_utils.py,sha256=2H9azNx3xAj-MySg-uZ2SFqbWs4kZvf61JnK6b-h4Qw,4343
68
68
  dcicutils/zip_utils.py,sha256=rnjNv_k6L9jT2SjDSgVXp4BEJYLtz9XN6Cl2Fy-tqnM,2027
69
- dcicutils-8.7.0.1b36.dist-info/LICENSE.txt,sha256=qnwSmfnEWMl5l78VPDEzAmEbLVrRqQvfUQiHT0ehrOo,1102
70
- dcicutils-8.7.0.1b36.dist-info/METADATA,sha256=bcSyvmUzkOl-wgR4SJjnOybO9ryFelrfjHpLGFILiNE,3315
71
- dcicutils-8.7.0.1b36.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
72
- dcicutils-8.7.0.1b36.dist-info/entry_points.txt,sha256=8wbw5csMIgBXhkwfgsgJeuFcoUc0WsucUxmOyml2aoA,209
73
- dcicutils-8.7.0.1b36.dist-info/RECORD,,
69
+ dcicutils-8.7.0.1b37.dist-info/LICENSE.txt,sha256=qnwSmfnEWMl5l78VPDEzAmEbLVrRqQvfUQiHT0ehrOo,1102
70
+ dcicutils-8.7.0.1b37.dist-info/METADATA,sha256=p_b5H768OpaJuXp9IfbDntuVg2MIjyAnjvaZB5T7Vv4,3315
71
+ dcicutils-8.7.0.1b37.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
72
+ dcicutils-8.7.0.1b37.dist-info/entry_points.txt,sha256=8wbw5csMIgBXhkwfgsgJeuFcoUc0WsucUxmOyml2aoA,209
73
+ dcicutils-8.7.0.1b37.dist-info/RECORD,,