dcicutils 8.5.0.1b2__py3-none-any.whl → 8.5.0.1b4__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/portal_utils.py CHANGED
@@ -23,15 +23,14 @@ class Portal:
23
23
  2. From a key dictionary, containing "key" and "secret" property values.
24
24
  3. From a key tuple, containing (in order) a key and secret values.
25
25
  4. From a keys file assumed to reside in ~/.{app}-keys.json where the given "app" value is either "smaht", "cgap",
26
- or "fourfront"; and where this file is assumed to contain a dictionary with a key equal to the given "env"
27
- value (e.g. smaht-localhost) and with a dictionary value containing "key" and "secret" property values; if
28
- an "app" value is not specified but the given "env" value begins with one of the app values then that value
29
- will be used, i.e. e.g. if env is "smaht-localhost" and app is unspecified than it is assumed to be "smaht".
26
+ or "fourfront"; where is assumed to contain a dictionary with a key for the given "env" value, e.g. smaht-local;
27
+ and with a dictionary value containing "key" and "secret" property values, and an optional "server" property;
28
+ if an "app" value is not specified but the given "env" value begins with one of the app values then that value
29
+ will be used, i.e. e.g. if "env" is "smaht-local" and app is unspecified than it is assumed to be "smaht".
30
30
  5. From a keys file as described above (#4) but rather than be identified by the given "env" value it
31
- is looked up by the given "server" name and the "server" key dictionary value in the key file.
31
+ is looked up via the given "server" name and the "server" key dictionary value in the key file.
32
32
  6. From a given "vapp" value (which is assumed to be a TestApp or VirtualApp).
33
- 7. From another Portal object.
34
- 8. From a a pyramid Router object.
33
+ 7. From another Portal object; or from a a pyramid Router object.
35
34
  """
36
35
  def __init__(self,
37
36
  arg: Optional[Union[VirtualApp, TestApp, Router, Portal, dict, tuple, str]] = None,
@@ -62,6 +61,7 @@ class Portal:
62
61
  self._server = portal._server
63
62
  self._key = portal._key
64
63
  self._key_pair = portal._key_pair
64
+ self._key_id = portal._key_id
65
65
  self._key_file = portal._key_file
66
66
  return
67
67
  self._vapp = None
@@ -70,6 +70,7 @@ class Portal:
70
70
  self._server = server
71
71
  self._key = None
72
72
  self._key_pair = None
73
+ self._key_id = None
73
74
  self._key_file = None
74
75
  if isinstance(portal, (VirtualApp, TestApp)):
75
76
  self._vapp = portal
@@ -95,6 +96,10 @@ class Portal:
95
96
  self._key = key_manager.get_keydict_for_server(self._server)
96
97
  self._key_pair = key_manager.keydict_to_keypair(self._key) if self._key else None
97
98
  self._key_file = key_manager.keys_file
99
+ if self._key and (key_id := self._key.get("key")):
100
+ self._key_id = key_id
101
+ elif self._key_pair and (key_id := self._key_pair[1]):
102
+ self._key_id = key_id
98
103
 
99
104
  @property
100
105
  def env(self):
@@ -116,6 +121,10 @@ class Portal:
116
121
  def key_pair(self):
117
122
  return self._key_pair
118
123
 
124
+ @property
125
+ def key_id(self):
126
+ return self._key_id
127
+
119
128
  @property
120
129
  def key_file(self):
121
130
  return self._key_file
@@ -206,13 +215,19 @@ class Portal:
206
215
  super_type_map_flattened[super_type_name] = breadth_first(super_type_map, super_type_name)
207
216
  return super_type_map_flattened
208
217
 
218
+ def ping(self) -> bool:
219
+ try:
220
+ return self.get("/health").status_code == 200
221
+ except Exception:
222
+ return False
223
+
209
224
  def _uri(self, uri: str) -> str:
210
225
  if not isinstance(uri, str) or not uri:
211
226
  return "/"
212
227
  if uri.lower().startswith("http://") or uri.lower().startswith("https://"):
213
228
  return uri
214
229
  uri = re.sub(r"/+", "/", uri)
215
- return (self._server + ("/" if uri.startswith("/") else "") + uri) if self._server else uri
230
+ return (self._server + ("/" if not uri.startswith("/") else "") + uri) if self._server else uri
216
231
 
217
232
  def _kwargs(self, **kwargs) -> dict:
218
233
  result_kwargs = {"headers":
@@ -42,8 +42,8 @@ StructuredDataSet = Type["StructuredDataSet"]
42
42
  class StructuredDataSet:
43
43
 
44
44
  def __init__(self, file: Optional[str] = None, portal: Optional[Union[VirtualApp, TestApp, Portal]] = None,
45
- schemas: Optional[List[dict]] = None, data: Optional[List[dict]] = None,
46
- order: Optional[List[str]] = None, prune: bool = True) -> None:
45
+ schemas: Optional[List[dict]] = None, autoadd: Optional[dict] = None,
46
+ data: Optional[List[dict]] = None, order: Optional[List[str]] = None, prune: bool = True) -> None:
47
47
  self.data = {} if not data else data # If portal is None then no schemas nor refs.
48
48
  self._portal = Portal(portal, data=self.data, schemas=schemas) if portal else None
49
49
  self._order = order
@@ -52,13 +52,14 @@ class StructuredDataSet:
52
52
  self._errors = {}
53
53
  self._resolved_refs = set()
54
54
  self._validated = False
55
+ self._autoadd_properties = autoadd if isinstance(autoadd, dict) and autoadd else None
55
56
  self._load_file(file) if file else None
56
57
 
57
58
  @staticmethod
58
59
  def load(file: str, portal: Optional[Union[VirtualApp, TestApp, Portal]] = None,
59
- schemas: Optional[List[dict]] = None,
60
+ schemas: Optional[List[dict]] = None, autoadd: Optional[dict] = None,
60
61
  order: Optional[List[str]] = None, prune: bool = True) -> StructuredDataSet:
61
- return StructuredDataSet(file=file, portal=portal, schemas=schemas, order=order, prune=prune)
62
+ return StructuredDataSet(file=file, portal=portal, schemas=schemas, autoadd=autoadd, order=order, prune=prune)
62
63
 
63
64
  def validate(self, force: bool = False) -> None:
64
65
  if self._validated and not force:
@@ -163,6 +164,8 @@ class StructuredDataSet:
163
164
  structured_row = structured_row_template.create_row()
164
165
  for column_name, value in row.items():
165
166
  structured_row_template.set_value(structured_row, column_name, value, reader.file, reader.row_number)
167
+ if self._autoadd_properties:
168
+ self._add_properties(structured_row, self._autoadd_properties, schema)
166
169
  self._add(type_name, structured_row)
167
170
  self._note_warning(reader.warnings, "reader")
168
171
  if schema:
@@ -177,6 +180,11 @@ class StructuredDataSet:
177
180
  else:
178
181
  self.data[type_name] = [data] if isinstance(data, dict) else data
179
182
 
183
+ def _add_properties(self, structured_row: dict, properties: dict, schema: Optional[dict] = None) -> None:
184
+ for name in properties:
185
+ if name not in structured_row and (not schema or schema.data.get("properties", {}).get(name)):
186
+ structured_row[name] = properties[name]
187
+
180
188
  def _note_warning(self, item: Optional[Union[dict, List[dict]]], group: str) -> None:
181
189
  self._note_issue(self._warnings, item, group)
182
190
 
@@ -317,7 +325,8 @@ class Schema:
317
325
 
318
326
  @staticmethod
319
327
  def load_by_name(name: str, portal: Portal) -> Optional[dict]:
320
- return Schema(portal.get_schema(Schema.type_name(name)), portal) if portal else None
328
+ schema_json = portal.get_schema(Schema.type_name(name)) if portal else None
329
+ return Schema(schema_json, portal) if schema_json else None
321
330
 
322
331
  def validate(self, data: dict) -> List[str]:
323
332
  errors = []
@@ -565,7 +574,9 @@ class Portal(PortalBase):
565
574
 
566
575
  @lru_cache(maxsize=256)
567
576
  def get_schema(self, schema_name: str) -> Optional[dict]:
568
- if (schemas := self.get_schemas()) and (schema := schemas.get(schema_name := Schema.type_name(schema_name))):
577
+ if not (schemas := self.get_schemas()):
578
+ return None
579
+ if schema := schemas.get(schema_name := Schema.type_name(schema_name)):
569
580
  return schema
570
581
  if schema_name == schema_name.upper() and (schema := schemas.get(schema_name.lower().title())):
571
582
  return schema
@@ -573,8 +584,9 @@ class Portal(PortalBase):
573
584
  return schema
574
585
 
575
586
  @lru_cache(maxsize=1)
576
- def get_schemas(self) -> dict:
577
- schemas = super().get_schemas()
587
+ def get_schemas(self) -> Optional[dict]:
588
+ if not (schemas := super().get_schemas()) or (schemas.get("status") == "error"):
589
+ return None
578
590
  if self._schemas:
579
591
  schemas = copy.deepcopy(schemas)
580
592
  for user_specified_schema in self._schemas:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dcicutils
3
- Version: 8.5.0.1b2
3
+ Version: 8.5.0.1b4
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
@@ -43,7 +43,7 @@ dcicutils/log_utils.py,sha256=7pWMc6vyrorUZQf-V-M3YC6zrPgNhuV_fzm9xqTPph0,10883
43
43
  dcicutils/misc_utils.py,sha256=nRjLEORY35YmJwTjO0fnauBPznaI_bkVasIW8PccDYM,100179
44
44
  dcicutils/obfuscation_utils.py,sha256=fo2jOmDRC6xWpYX49u80bVNisqRRoPskFNX3ymFAmjw,5963
45
45
  dcicutils/opensearch_utils.py,sha256=V2exmFYW8Xl2_pGFixF4I2Cc549Opwe4PhFi5twC0M8,1017
46
- dcicutils/portal_utils.py,sha256=OF1JPoDgEbvCvPKz0egcnmqGEOYWkamuBLRN_RpZFtk,14073
46
+ dcicutils/portal_utils.py,sha256=Wh918ZKpUJFbt7w6Bn5G7v-0k6ImOUWMFmE9Oxt1ZN4,14560
47
47
  dcicutils/project_utils.py,sha256=qPdCaFmWUVBJw4rw342iUytwdQC0P-XKpK4mhyIulMM,31250
48
48
  dcicutils/qa_checkers.py,sha256=cdXjeL0jCDFDLT8VR8Px78aS10hwNISOO5G_Zv2TZ6M,20534
49
49
  dcicutils/qa_utils.py,sha256=TT0SiJWiuxYvbsIyhK9VO4uV_suxhB6CpuC4qPacCzQ,160208
@@ -56,14 +56,14 @@ dcicutils/secrets_utils.py,sha256=8dppXAsiHhJzI6NmOcvJV5ldvKkQZzh3Fl-cb8Wm7MI,19
56
56
  dcicutils/sheet_utils.py,sha256=VlmzteONW5VF_Q4vo0yA5vesz1ViUah1MZ_yA1rwZ0M,33629
57
57
  dcicutils/snapshot_utils.py,sha256=ymP7PXH6-yEiXAt75w0ldQFciGNqWBClNxC5gfX2FnY,22961
58
58
  dcicutils/ssl_certificate_utils.py,sha256=F0ifz_wnRRN9dfrfsz7aCp4UDLgHEY8LaK7PjnNvrAQ,9707
59
- dcicutils/structured_data.py,sha256=qP7YoEnwrmH-NqNQ02UNmkOK_oYs4e7V4iR2L1NeopA,32514
59
+ dcicutils/structured_data.py,sha256=tMKBhq6OuM2t6iDxIPBFcxV66MiwmOHTBeACxhvkbiQ,33307
60
60
  dcicutils/task_utils.py,sha256=MF8ujmTD6-O2AC2gRGPHyGdUrVKgtr8epT5XU8WtNjk,8082
61
61
  dcicutils/trace_utils.py,sha256=g8kwV4ebEy5kXW6oOrEAUsurBcCROvwtZqz9fczsGRE,1769
62
62
  dcicutils/validation_utils.py,sha256=cMZIU2cY98FYtzK52z5WUYck7urH6JcqOuz9jkXpqzg,14797
63
63
  dcicutils/variant_utils.py,sha256=2H9azNx3xAj-MySg-uZ2SFqbWs4kZvf61JnK6b-h4Qw,4343
64
64
  dcicutils/zip_utils.py,sha256=0OXR0aLNwyLIZOzIFTM_5DOun7dxIv6TIZbFiithkO0,3276
65
- dcicutils-8.5.0.1b2.dist-info/LICENSE.txt,sha256=t0_-jIjqxNnymZoNJe-OltRIuuF8qfhN0ATlHyrUJPk,1102
66
- dcicutils-8.5.0.1b2.dist-info/METADATA,sha256=hhKDH81eiE03-Gg0ZnsQ6yBoweGZ3Y52_FbqvUb5woI,3314
67
- dcicutils-8.5.0.1b2.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
68
- dcicutils-8.5.0.1b2.dist-info/entry_points.txt,sha256=8wbw5csMIgBXhkwfgsgJeuFcoUc0WsucUxmOyml2aoA,209
69
- dcicutils-8.5.0.1b2.dist-info/RECORD,,
65
+ dcicutils-8.5.0.1b4.dist-info/LICENSE.txt,sha256=t0_-jIjqxNnymZoNJe-OltRIuuF8qfhN0ATlHyrUJPk,1102
66
+ dcicutils-8.5.0.1b4.dist-info/METADATA,sha256=Zpf8fTsgsuRfo8WDGkONHxtcf4SPWOFK_4iCNVAhB78,3314
67
+ dcicutils-8.5.0.1b4.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
68
+ dcicutils-8.5.0.1b4.dist-info/entry_points.txt,sha256=8wbw5csMIgBXhkwfgsgJeuFcoUc0WsucUxmOyml2aoA,209
69
+ dcicutils-8.5.0.1b4.dist-info/RECORD,,