dcicutils 8.7.0.1b35__py3-none-any.whl → 8.7.0.1b37__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
 
@@ -73,6 +71,7 @@ class PortalObject:
73
71
  for identifying_property in identifying_properties:
74
72
  if (identifying_value := self._data.get(identifying_property)):
75
73
  if identifying_property == "uuid":
74
+ identifying_paths.append(f"/{self.type}/{identifying_value}")
76
75
  identifying_paths.append(f"/{identifying_value}")
77
76
  # For now at least we include the path both with and without the schema type component,
78
77
  # as for some identifying values, it works (only) with, and some, it works (only) without.
@@ -111,55 +110,3 @@ class PortalObject:
111
110
  except Exception:
112
111
  pass
113
112
  return None, self.identifying_path
114
-
115
- def compare(self, value: Union[dict, PortalObject], consider_link_to: bool = False) -> dict:
116
- """
117
- Compares this Portal object against the given Portal object value; noting differences values of properites
118
- which they have in common; and properties which are in this Portal object and not in the given Portal object;
119
- we do NOT check the converse, i.e. properties in the given Portal object which are not in this Portal object.
120
- Returns a dictionary with a description of the differences.
121
- """
122
- def are_properties_equal(property_path: str, property_value_a: Any, property_value_b: Any) -> bool:
123
- if property_value_a == property_value_b:
124
- return True
125
- nonlocal self
126
- if (schema := self.schema) and (property_type := Schema.get_property_by_path(schema, property_path)):
127
- if link_to := property_type.get("linkTo"):
128
- if a := self._portal.get(f"/{link_to}/{property_value_a}", raw=True):
129
- if (a.status_code == 200) and (a := a.json()):
130
- if b := self._portal.get(f"/{link_to}/{property_value_b}", raw=True):
131
- if (b.status_code == 200) and (b := b.json()):
132
- return a == b
133
- return False
134
- return PortalObject._compare(self._data, value.data if isinstance(value, PortalObject) else value,
135
- compare=are_properties_equal if consider_link_to else None)
136
-
137
- _ARRAY_KEY_REGULAR_EXPRESSION = re.compile(rf"^({Schema._ARRAY_NAME_SUFFIX_CHAR}\d+)$")
138
-
139
- @staticmethod
140
- def _compare(a: dict, b: dict, compare: Optional[Callable] = None, _path: Optional[str] = None) -> dict:
141
- def key_to_path(key: str) -> Optional[str]: # noqa
142
- nonlocal _path
143
- if match := PortalObject._ARRAY_KEY_REGULAR_EXPRESSION.search(key):
144
- return f"{_path}{match.group(1)}" if _path else match.group(1)
145
- return f"{_path}.{key}" if _path else key
146
- def list_to_dictionary(value: list) -> dict: # noqa
147
- result = {}
148
- for index, item in enumerate(sorted(value)): # ignore array order
149
- result[f"#{index}"] = item
150
- return result
151
- diffs = {}
152
- for key in a:
153
- path = key_to_path(key)
154
- if key not in b:
155
- diffs[path] = {"value": a[key], "missing_value": True}
156
- else:
157
- if isinstance(a[key], dict) and isinstance(b[key], dict):
158
- diffs.update(PortalObject._compare(a[key], b[key], compare=compare, _path=path))
159
- elif isinstance(a[key], list) and isinstance(b[key], list):
160
- diffs.update(PortalObject._compare(list_to_dictionary(a[key]),
161
- list_to_dictionary(b[key]), compare=compare, _path=path))
162
- elif a[key] != b[key]:
163
- if not callable(compare) or not compare(path, a[key], b[key]):
164
- diffs[path] = {"value": a[key], "differing_value": b[key]}
165
- 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,79 +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
- TODO
212
- """
213
- return Schema.get_property_by_path(self._data, property_path)
214
-
215
- _ARRAY_NAME_SUFFIX_CHAR = "#"
216
- _DOTTED_NAME_DELIMITER_CHAR = "."
217
-
218
- @staticmethod
219
- def get_property_by_path(schema: dict, property_path: str) -> Optional[dict]:
220
- if not isinstance(schema, dict) or not isinstance(property_path, str):
221
- return None
222
- elif not (schema_properties := schema.get("properties")):
223
- return None
224
- property_paths = property_path.split(Schema._DOTTED_NAME_DELIMITER_CHAR)
225
- for property_index, property_name in enumerate(property_paths):
226
- property_name, array_specifiers = Schema._unarrayize_property_name(property_name)
227
- if not (property_value := schema_properties.get(property_name)):
228
- return None
229
- elif (property_type := property_value.get("type")) == "object":
230
- property_paths_tail = Schema._DOTTED_NAME_DELIMITER_CHAR.join(property_paths[property_index + 1:])
231
- return Schema.get_property_by_path(property_value, property_paths_tail)
232
- elif (property_type := property_value.get("type")) == "array":
233
- if not array_specifiers:
234
- if property_index == len(property_paths) - 1:
235
- return property_value
236
- return None
237
- for array_index in range(len(array_specifiers)):
238
- if property_type != "array":
239
- return None
240
- elif not (array_items := property_value.get("items")):
241
- return None
242
- property_type = (property_value := array_items).get("type")
243
- if property_type == "object":
244
- if property_index == len(property_paths) - 1:
245
- return property_value
246
- property_paths_tail = Schema._DOTTED_NAME_DELIMITER_CHAR.join(property_paths[property_index + 1:])
247
- return Schema.get_property_by_path(property_value, property_paths_tail)
248
- return property_value
249
-
250
- @staticmethod
251
- def _unarrayize_property_name(property_name: str) -> Tuple[str, Optional[List[int]]]:
252
- if len(components := (property_name := property_name.strip()).split(Schema._ARRAY_NAME_SUFFIX_CHAR)) < 2:
253
- return property_name, None
254
- unarrayized_property_name = components[0].strip()
255
- array_specifiers = []
256
- for component in components[1:]:
257
- if component.isdigit():
258
- array_specifiers.append(int(component))
259
- elif component == "":
260
- array_specifiers.append(0)
261
- else:
262
- return property_name, None
263
- 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.1b35
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=udjT_-IYWInTc-oXoh0Ie_xVYp28YEg3BRIlS88eUwQ,8352
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=h3VlIiBxE8EmxnfcXHF5KZhNeIZIA71LvqeIM-04gKY,9169
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.1b35.dist-info/LICENSE.txt,sha256=qnwSmfnEWMl5l78VPDEzAmEbLVrRqQvfUQiHT0ehrOo,1102
70
- dcicutils-8.7.0.1b35.dist-info/METADATA,sha256=v9eG3K-Qg11ZBSXujKZI_CGs6AYp8YCAp1OAe6Eywgo,3315
71
- dcicutils-8.7.0.1b35.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
72
- dcicutils-8.7.0.1b35.dist-info/entry_points.txt,sha256=8wbw5csMIgBXhkwfgsgJeuFcoUc0WsucUxmOyml2aoA,209
73
- dcicutils-8.7.0.1b35.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,,