pyPreservica 2.8.2__py3-none-any.whl → 2.9.1__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.
pyPreservica/__init__.py CHANGED
@@ -7,7 +7,7 @@ licence: Apache License 2.0
7
7
 
8
8
  """
9
9
  from .common import *
10
- from .contentAPI import ContentAPI
10
+ from .contentAPI import ContentAPI, Field, SortOrder
11
11
  from .entityAPI import EntityAPI
12
12
  from .uploadAPI import UploadAPI, simple_asset_package, complex_asset_package, cvs_to_xsd, cvs_to_xml, \
13
13
  cvs_to_cmis_xslt, csv_to_search_xml, generic_asset_package, upload_config, multi_asset_package
@@ -23,6 +23,6 @@ from .mdformsAPI import MetadataGroupsAPI, Group, GroupField, GroupFieldType
23
23
  __author__ = "James Carr (drjamescarr@gmail.com)"
24
24
 
25
25
  # Version of the pyPreservica package
26
- __version__ = "2.8.2"
26
+ __version__ = "2.9.1"
27
27
 
28
28
  __license__ = "Apache License Version 2.0"
@@ -10,11 +10,28 @@ licence: Apache License 2.0
10
10
  """
11
11
 
12
12
  import csv
13
- from typing import Generator, Callable
13
+ from typing import Generator, Callable, Optional
14
14
  from pyPreservica.common import *
15
15
 
16
16
  logger = logging.getLogger(__name__)
17
17
 
18
+ class SortOrder(Enum):
19
+ asc = 1
20
+ desc = 2
21
+
22
+ class Field:
23
+ name: str
24
+ value: Optional[str]
25
+ operator: Optional[str]
26
+ sort_order: Optional[SortOrder]
27
+
28
+ def __init__(self, name: str, value: str, operator: Optional[str]=None, sort_order: Optional[SortOrder]=None):
29
+ self.name = name
30
+ self.value = value
31
+ self.operator = operator
32
+ self.sort_order = sort_order
33
+
34
+
18
35
 
19
36
  class ContentAPI(AuthenticatedAPI):
20
37
 
@@ -212,6 +229,93 @@ class ContentAPI(AuthenticatedAPI):
212
229
  writer.writeheader()
213
230
  writer.writerows(self.search_index_filter_list(query, page_size, filter_values, sort_values))
214
231
 
232
+ def search_fields(self, query: str = "%", fields: list[Field]=None, page_size: int = 25) -> Generator:
233
+ """
234
+ Run a search query with multiple fields
235
+
236
+ :param query: The main search query.
237
+ :param fields: List of search fields
238
+ :param page_size: The default search page size
239
+ :return: search result
240
+ """
241
+ search_result = self._search_fields(query=query, fields=fields, start_index=0, page_size=page_size)
242
+ for e in search_result.results_list:
243
+ yield e
244
+ found = len(search_result.results_list)
245
+ while search_result.hits > found:
246
+ search_result = self._search_fields(query=query, fields=fields, start_index=found, page_size=page_size)
247
+ for e in search_result.results_list:
248
+ yield e
249
+ found = found + len(search_result.results_list)
250
+
251
+ def _search_fields(self, query: str = "%", fields: list[Field]=None, start_index: int = 0, page_size: int = 25):
252
+
253
+ start_from = str(start_index)
254
+ headers = {'Content-Type': 'application/x-www-form-urlencoded', HEADER_TOKEN: self.token}
255
+
256
+ if fields is None:
257
+ fields = []
258
+
259
+ field_list = []
260
+ sort_list = []
261
+ metadata_elements = []
262
+ for field in fields:
263
+ metadata_elements.append(field.name)
264
+ if field.value is None or field.value == "":
265
+ field_list.append('{' f' "name": "{field.name}", "values": [] ' + '}')
266
+ elif field.operator == "NOT":
267
+ field_list.append('{' f' "name": "{field.name}", "values": ["{field.value}"], "operator": "NOT" ' + '}')
268
+ else:
269
+ field_list.append('{' f' "name": "{field.name}", "values": ["{field.value}"] ' + '}')
270
+
271
+ if field.sort_order is not None:
272
+ sort_list.append(f'{{"sortFields": ["{field.name}"], "sortOrder": "{field.sort_order.name}"}}')
273
+
274
+
275
+ filter_terms = ','.join(field_list)
276
+
277
+ if len(sort_list) == 0:
278
+ query_term = ('{ "q": "%s", "fields": [ %s ] }' % (query, filter_terms))
279
+ else:
280
+ sort_terms = ','.join(sort_list)
281
+ query_term = ('{ "q": "%s", "fields": [ %s ], "sort": [ %s ]}' % (query, filter_terms, sort_terms))
282
+
283
+ if len(metadata_elements) == 0:
284
+ metadata_elements.append("xip.title")
285
+
286
+
287
+ payload = {'start': start_from, 'max': str(page_size), 'metadata': list(metadata_elements), 'q': query_term}
288
+ logger.debug(payload)
289
+ results = self.session.post(f'{self.protocol}://{self.server}/api/content/search', data=payload,
290
+ headers=headers)
291
+ results_list = []
292
+ if results.status_code == requests.codes.ok:
293
+ json_doc = results.json()
294
+ metadata = json_doc['value']['metadata']
295
+ refs = list(json_doc['value']['objectIds'])
296
+ refs = list(map(lambda x: content_api_identifier_to_type(x), refs))
297
+ hits = int(json_doc['value']['totalHits'])
298
+
299
+ for m_row, r_row in zip(metadata, refs):
300
+ results_map = {'xip.reference': r_row[1]}
301
+ for li in m_row:
302
+ results_map[li['name']] = li['value']
303
+ results_list.append(results_map)
304
+ next_start = start_index + page_size
305
+
306
+ if self.callback is not None:
307
+ value = str(f'{len(results_list) + start_index}:{hits}')
308
+ self.callback(value)
309
+
310
+ search_results = self.SearchResult(metadata, refs, hits, results_list, next_start)
311
+ return search_results
312
+ elif results.status_code == requests.codes.unauthorized:
313
+ self.token = self.__token__()
314
+ return self._search_predicates(query, predicates, start_index, page_size)
315
+ else:
316
+ logger.error(f"search failed with error code: {results.status_code}")
317
+ raise RuntimeError(results.status_code, f"search_index_filter failed")
318
+
215
319
  def search_index_filter_list(self, query: str = "%", page_size: int = 25, filter_values: dict = None,
216
320
  sort_values: dict = None) -> Generator:
217
321
  """
pyPreservica/entityAPI.py CHANGED
@@ -572,6 +572,76 @@ class EntityAPI(AuthenticatedAPI):
572
572
  logger.error(exception)
573
573
  raise exception
574
574
 
575
+ def update_identifiers(self, entity: Entity, identifier_type: str = None, identifier_value: str = None):
576
+ """
577
+ Update external identifiers based on Entity and Type
578
+
579
+ Returns the internal identifier DB Key
580
+
581
+ :param entity: The entity to delete identifiers from
582
+ :param identifier_type: The type of the identifier to delete.
583
+ :param identifier_value: The value of the identifier to delete.
584
+ """
585
+
586
+ if (self.major_version < 7) and (self.minor_version < 1):
587
+ raise RuntimeError("update_identifiers API call is not available when connected to a v6.0 System")
588
+
589
+ headers = {HEADER_TOKEN: self.token}
590
+ response = self.session.get(
591
+ f'{self.protocol}://{self.server}/api/entity/{entity.path}/{entity.reference}/identifiers',
592
+ headers=headers)
593
+
594
+ if response.status_code == requests.codes.ok:
595
+ xml_response = str(response.content.decode('utf-8'))
596
+ entity_response = xml.etree.ElementTree.fromstring(xml_response)
597
+ identifier_list = entity_response.findall(f'.//{{{self.xip_ns}}}Identifier')
598
+ for identifier_element in identifier_list:
599
+ _ref = _type = _value = _aipid = None
600
+ for identifier in identifier_element:
601
+ if identifier.tag.endswith("Entity"):
602
+ _ref = identifier.text
603
+ if identifier.tag.endswith("Type") and identifier_type is not None:
604
+ _type = identifier.text
605
+ if identifier.tag.endswith("Value") and identifier_value is not None:
606
+ _value = identifier.text
607
+ if identifier.tag.endswith("ApiId"):
608
+ _aipid = identifier.text
609
+ if _ref == entity.reference and _type == identifier_type:
610
+
611
+ headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/xml;charset=UTF-8'}
612
+
613
+ xml_object = xml.etree.ElementTree.Element('Identifier', {"xmlns": self.xip_ns})
614
+ xml.etree.ElementTree.SubElement(xml_object, "Type").text = identifier_type
615
+ xml.etree.ElementTree.SubElement(xml_object, "Value").text = identifier_value
616
+ xml.etree.ElementTree.SubElement(xml_object, "Entity").text = entity.reference
617
+ xml_request = xml.etree.ElementTree.tostring(xml_object, encoding='utf-8')
618
+
619
+ put_response = self.session.put(
620
+ f'{self.protocol}://{self.server}/api/entity/{entity.path}/{entity.reference}/identifiers/{_aipid}',
621
+ headers=headers, data=xml_request)
622
+ if put_response.status_code == requests.codes.ok:
623
+ xml_string = str(put_response.content.decode("utf-8"))
624
+ identifier_response = xml.etree.ElementTree.fromstring(xml_string)
625
+ aip_id = identifier_response.find(f'.//{{{self.xip_ns}}}ApiId')
626
+ if hasattr(aip_id, 'text'):
627
+ return aip_id.text
628
+ else:
629
+ return None
630
+ if put_response.status_code == requests.codes.unauthorized:
631
+ self.token = self.__token__()
632
+ return self.update_identifiers(entity, identifier_type, identifier_value)
633
+ if put_response.status_code == requests.codes.no_content:
634
+ pass
635
+ else:
636
+ return None
637
+ return entity
638
+ elif response.status_code == requests.codes.unauthorized:
639
+ self.token = self.__token__()
640
+ return self.update_identifiers(entity, identifier_type, identifier_value)
641
+ else:
642
+ logger.error(response)
643
+ raise RuntimeError(response.status_code, "update_identifiers failed")
644
+
575
645
  def delete_relationships(self, entity: Entity, relationship_type: str = None):
576
646
  """
577
647
  Delete a relationship between two entities by its internal id
@@ -2275,6 +2345,8 @@ class EntityAPI(AuthenticatedAPI):
2275
2345
  entity_response = xml.etree.ElementTree.fromstring(req.content.decode("utf-8"))
2276
2346
  status = entity_response.find(".//{http://status.preservica.com}Status")
2277
2347
  if hasattr(status, 'text'):
2348
+ if status.text == "COMPLETED":
2349
+ return entity.reference
2278
2350
  if status.text == "PENDING":
2279
2351
  headers = {HEADER_TOKEN: self.manager_token(manager_username, manager_password),
2280
2352
  'Content-Type': 'application/xml;charset=UTF-8'}
@@ -96,6 +96,8 @@ def _object_from_json_(json_doc: dict) -> Group:
96
96
  gf.editable = bool(field['editable'])
97
97
  if 'values' in field:
98
98
  for v in field['values']:
99
+ if gf.values is None:
100
+ gf.values = []
99
101
  gf.values.append(str(v))
100
102
  if 'defaultValue' in field:
101
103
  gf.default = str(field['defaultValue'])
@@ -9,7 +9,6 @@ licence: Apache License 2.0
9
9
 
10
10
  """
11
11
 
12
-
13
12
  import xml.etree.ElementTree
14
13
  from typing import Set, Callable
15
14
 
@@ -60,7 +59,6 @@ class RetentionAPI(AuthenticatedAPI):
60
59
 
61
60
  def __init__(self, username=None, password=None, tenant=None, server=None, use_shared_secret=False,
62
61
  two_fa_secret_key: str = None, protocol: str = "https", request_hook: Callable = None):
63
-
64
62
  super().__init__(username, password, tenant, server, use_shared_secret, two_fa_secret_key,
65
63
  protocol, request_hook)
66
64
  if self.major_version < 7 and self.minor_version < 2:
@@ -78,7 +76,8 @@ class RetentionAPI(AuthenticatedAPI):
78
76
 
79
77
  """
80
78
  headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/xml;charset=UTF-8'}
81
- request = self.session.get(f'{self.protocol}://{self.server}/api/entity/retention-policies/{reference}', headers=headers)
79
+ request = self.session.get(f'{self.protocol}://{self.server}/api/entity/retention-policies/{reference}',
80
+ headers=headers)
82
81
  if request.status_code == requests.codes.ok:
83
82
  xml_response = str(request.content.decode('utf-8'))
84
83
  logger.debug(xml_response)
@@ -92,14 +91,22 @@ class RetentionAPI(AuthenticatedAPI):
92
91
  security_tag = entity_response.find(f'.//{{{self.rm_ns}}}RetentionPolicy/{{{self.rm_ns}}}SecurityTag').text
93
92
  rp.security_tag = security_tag
94
93
  start_date_field = entity_response.find(
95
- f'.//{{{self.rm_ns}}}RetentionPolicy/{{{self.rm_ns}}}StartDateField').text
96
- rp.start_date_field = start_date_field
97
- period = entity_response.find(f'.//{{{self.rm_ns}}}RetentionPolicy/{{{self.rm_ns}}}Period').text
98
- rp.period = period
99
- period_unit = entity_response.find(f'.//{{{self.rm_ns}}}RetentionPolicy/{{{self.rm_ns}}}PeriodUnit').text
100
- rp.period_unit = period_unit
101
- expiry_action = entity_response.find(
102
- f'.//{{{self.rm_ns}}}RetentionPolicy/{{{self.rm_ns}}}ExpiryAction')
94
+ f'.//{{{self.rm_ns}}}RetentionPolicy/{{{self.rm_ns}}}StartDateField')
95
+ if start_date_field is not None:
96
+ rp.start_date_field = start_date_field.text
97
+ else:
98
+ start_date_field = None
99
+ period = entity_response.find(f'.//{{{self.rm_ns}}}RetentionPolicy/{{{self.rm_ns}}}Period')
100
+ if period is not None:
101
+ rp.period = period.text
102
+ else:
103
+ rp.period = None
104
+ period_unit = entity_response.find(f'.//{{{self.rm_ns}}}RetentionPolicy/{{{self.rm_ns}}}PeriodUnit')
105
+ if period_unit is not None:
106
+ rp.period_unit = period_unit.text
107
+ else:
108
+ rp.period_unit = None
109
+ expiry_action = entity_response.find(f'.//{{{self.rm_ns}}}RetentionPolicy/{{{self.rm_ns}}}ExpiryAction')
103
110
  if expiry_action is not None:
104
111
  rp.expiry_action = expiry_action.text
105
112
  else:
@@ -134,8 +141,9 @@ class RetentionAPI(AuthenticatedAPI):
134
141
  """
135
142
  headers = {HEADER_TOKEN: self.token, 'Content-Type': 'text/plain;charset=UTF-8'}
136
143
  data = str(status)
137
- request = self.session.put(f'{self.protocol}://{self.server}/api/entity/retention-policies/{reference}/assignable',
138
- headers=headers, data=data)
144
+ request = self.session.put(
145
+ f'{self.protocol}://{self.server}/api/entity/retention-policies/{reference}/assignable',
146
+ headers=headers, data=data)
139
147
  if request.status_code == requests.codes.ok:
140
148
  pass
141
149
  elif request.status_code == requests.codes.unauthorized:
@@ -230,7 +238,8 @@ class RetentionAPI(AuthenticatedAPI):
230
238
 
231
239
  xml_request = xml.etree.ElementTree.tostring(retention_policy, encoding='utf-8')
232
240
 
233
- request = self.session.put(f'{self.protocol}://{self.server}/api/entity/retention-policies/{reference}', data=xml_request,
241
+ request = self.session.put(f'{self.protocol}://{self.server}/api/entity/retention-policies/{reference}',
242
+ data=xml_request,
234
243
  headers=headers)
235
244
  if request.status_code == requests.codes.ok:
236
245
  return self.policy(reference)
@@ -374,7 +383,8 @@ class RetentionAPI(AuthenticatedAPI):
374
383
  """
375
384
  headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/xml;charset=UTF-8'}
376
385
  data = {'start': str(0), 'max': "250"}
377
- request = self.session.get(f'{self.protocol}://{self.server}/api/entity/retention-policies', data=data, headers=headers)
386
+ request = self.session.get(f'{self.protocol}://{self.server}/api/entity/retention-policies', data=data,
387
+ headers=headers)
378
388
  if request.status_code == requests.codes.ok:
379
389
  xml_response = str(request.content.decode('utf-8'))
380
390
  logger.debug(xml_response)
@@ -390,10 +400,10 @@ class RetentionAPI(AuthenticatedAPI):
390
400
  else:
391
401
  raise RuntimeError(request.status_code, "policies failed")
392
402
 
393
- def policies(self) -> Set[RetentionPolicy]:
403
+ def policies(self, maximum: int = 250, next_page: str = None) -> PagedSet:
394
404
  """
395
405
  Return a list of all retention policies
396
- Only returns the first 250 policies in the system
406
+ Returns a maxmium of 250 policies by default
397
407
 
398
408
 
399
409
  :return: Set of retention policies
@@ -401,22 +411,33 @@ class RetentionAPI(AuthenticatedAPI):
401
411
 
402
412
  """
403
413
  headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/xml;charset=UTF-8'}
404
- data = {'start': str(0), 'max': "250"}
405
- request = self.session.get(f'{self.protocol}://{self.server}/api/entity/retention-policies', data=data, headers=headers)
414
+
415
+ if next_page is None:
416
+ params = {'start': '0', 'max': str(maximum)}
417
+ request = self.session.get(f'{self.protocol}://{self.server}/api/entity/retention-policies', params=params,
418
+ headers=headers)
419
+ else:
420
+ request = self.session.get(next_page, headers=headers)
421
+
406
422
  if request.status_code == requests.codes.ok:
407
423
  xml_response = str(request.content.decode('utf-8'))
408
424
  entity_response = xml.etree.ElementTree.fromstring(xml_response)
409
425
  logger.debug(xml_response)
410
426
  result = set()
427
+ next_url = entity_response.find(f'.//{{{self.entity_ns}}}Paging/{{{self.entity_ns}}}Next')
411
428
  total_results = int(entity_response.find(
412
429
  f'.//{{{self.entity_ns}}}TotalResults').text)
413
- if total_results > 250:
414
- logger.error("Not all retention policies have been returned.")
415
430
  for assignment in entity_response.findall(f'.//{{{self.entity_ns}}}RetentionPolicy'):
416
431
  ref = assignment.attrib['ref']
417
432
  name = assignment.attrib['name']
418
433
  result.add(self.policy(reference=ref))
419
- return result
434
+ has_more = True
435
+ url = None
436
+ if next_url is None:
437
+ has_more = False
438
+ else:
439
+ url = next_url.text
440
+ return PagedSet(result, has_more, total_results, url)
420
441
  elif request.status_code == requests.codes.unauthorized:
421
442
  self.token = self.__token__()
422
443
  return self.policies()
@@ -455,7 +476,11 @@ class RetentionAPI(AuthenticatedAPI):
455
476
  api_id = entity_response.find(f'.//{{{self.rm_ns}}}ApiId').text
456
477
  policy_ref = entity_response.find(f'.//{{{self.rm_ns}}}RetentionPolicy').text
457
478
  entity_ref = entity_response.find(f'.//{{{self.rm_ns}}}Entity').text
458
- start_date = entity_response.find(f'.//{{{self.rm_ns}}}StartDate').text
479
+ start_date = entity_response.find(f'.//{{{self.rm_ns}}}StartDate')
480
+ if start_date is not None:
481
+ start_date = start_date.text
482
+ else:
483
+ start_date = None
459
484
  assert entity_ref == entity.reference
460
485
  assert policy_ref == policy.reference
461
486
  return RetentionAssignment(entity_ref, policy_ref, api_id, start_date)
@@ -516,7 +541,11 @@ class RetentionAPI(AuthenticatedAPI):
516
541
  entity_ref = assignment.find(f'.//{{{self.rm_ns}}}Entity').text
517
542
  assert entity_ref == entity.reference
518
543
  policy = assignment.find(f'.//{{{self.rm_ns}}}RetentionPolicy').text
519
- start_date = assignment.find(f'.//{{{self.rm_ns}}}StartDate').text
544
+ start_date = assignment.find(f'.//{{{self.rm_ns}}}StartDate')
545
+ if start_date is not None:
546
+ start_date = start_date.text
547
+ else:
548
+ start_date = None
520
549
  expired = bool(assignment.find(f'.//{{{self.rm_ns}}}Expired').text == 'true')
521
550
  api_id = assignment.find(f'.//{{{self.rm_ns}}}ApiId').text
522
551
  ra = RetentionAssignment(entity_ref, policy, api_id, start_date, expired)
pyPreservica/uploadAPI.py CHANGED
@@ -1421,7 +1421,7 @@ class UploadAPI(AuthenticatedAPI):
1421
1421
  try:
1422
1422
  auth = tweepy.AppAuthHandler(twitter_consumer_key, twitter_secret_key)
1423
1423
  api = tweepy.API(auth, wait_on_rate_limit=True)
1424
- except TweepError:
1424
+ except RuntimeError:
1425
1425
  logger.error("No valid Twitter API keys. Could not authenticate")
1426
1426
  raise RuntimeError("No valid Twitter API keys. Could not authenticate")
1427
1427
  if api is not None:
@@ -1734,8 +1734,8 @@ class UploadAPI(AuthenticatedAPI):
1734
1734
  self.upload_zip_package(path_to_zip_package=package, callback=progress_display,
1735
1735
  delete_after_upload=delete_after_upload)
1736
1736
  else:
1737
- self.upload_zip_package_to_S3(path_to_zip_package=package, bucket_name=bucket_name,
1738
- callback=progress_display,
1737
+ self.upload_zip_to_Source(path_to_zip_package=package, container_name=bucket_name,
1738
+ show_progress= bool(progress_display is not None),
1739
1739
  delete_after_upload=delete_after_upload)
1740
1740
 
1741
1741
  logger.info(f"Uploaded " + "{:.1f}".format(bytes_ingested / (1024 * 1024)) + " MB")
@@ -74,6 +74,7 @@ class TriggerType(Enum):
74
74
  MOVED = "MOVED"
75
75
  INDEXED = "FULL_TEXT_INDEXED"
76
76
  SECURITY_CHANGED = "CHANGED_SECURITY_DESCRIPTOR"
77
+ INGEST_FAILED = "INGEST_FAILED"
77
78
 
78
79
 
79
80
  class WebHooksAPI(AuthenticatedAPI):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyPreservica
3
- Version: 2.8.2
3
+ Version: 2.9.1
4
4
  Summary: Python library for the Preservica API
5
5
  Home-page: https://pypreservica.readthedocs.io/
6
6
  Author: James Carr
@@ -15,6 +15,7 @@ Classifier: Programming Language :: Python :: 3.8
15
15
  Classifier: Programming Language :: Python :: 3.9
16
16
  Classifier: Programming Language :: Python :: 3.10
17
17
  Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
18
19
  Classifier: License :: OSI Approved :: Apache Software License
19
20
  Classifier: Operating System :: OS Independent
20
21
  Classifier: Topic :: System :: Archiving
@@ -34,12 +35,9 @@ Requires-Dist: pyotp
34
35
  # pyPreservica
35
36
 
36
37
 
37
- <!---
38
- [![Downloads](https://pepy.tech/badge/pyPreservica/month)](https://pepy.tech/project/pyPreservica/month)
39
- --->
40
-
41
38
  [![Supported Versions](https://img.shields.io/pypi/pyversions/pyPreservica.svg)](https://pypi.org/project/pyPreservica)
42
39
  [![CodeQL](https://github.com/carj/pyPreservica/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/carj/pyPreservica/actions/workflows/codeql-analysis.yml)
40
+ ![PyPI Downloads](https://static.pepy.tech/badge/pypreservica)
43
41
 
44
42
  Python language binding for the Preservica API
45
43
 
@@ -0,0 +1,19 @@
1
+ pyPreservica/__init__.py,sha256=AORR-EHoHqoqhU19-cJ2pNZ33l01fxM5-_zjOrgcdNo,1177
2
+ pyPreservica/adminAPI.py,sha256=511bc5KtrCAXbDyBk39dmDnxUVDaOu6xaiyu0jYhxa4,37781
3
+ pyPreservica/authorityAPI.py,sha256=Eule8g6LXr8c8SFcJgpRah4lH1FgevUItO5HhHDEaZE,9172
4
+ pyPreservica/common.py,sha256=yZNMlq8aOOLSbFS2DDHYBUWyN5ojDjYUYmcePVbUd44,37636
5
+ pyPreservica/contentAPI.py,sha256=WUl03HkywOF3D-RaTOS50jOmcR8X8YWmYCnAIJMfvBc,21886
6
+ pyPreservica/entityAPI.py,sha256=IqfFfmkEnttJEFuYy7aUAhXbaBL86BioMExcgtg31NE,118993
7
+ pyPreservica/mdformsAPI.py,sha256=7hPRITkoSAfOKcfS3u-KJl0Gd9tWUt4nEnX6cXq4xHs,13614
8
+ pyPreservica/monitorAPI.py,sha256=HD-PUPdSI9wGAa07e2_2_-FLINH8PoWUwpFogz7F-j4,6269
9
+ pyPreservica/opex.py,sha256=ccra1S4ojUXS3PlbU8WfxajOkJrwG4OykBnNrYP_jus,4875
10
+ pyPreservica/parAPI.py,sha256=bgaQvYfWNnzdD7ibKMV3ZV85pNkEdSoLsgVigoiFFfw,10771
11
+ pyPreservica/retentionAPI.py,sha256=31yKHbatxj9kt5vbqyTeg98nrMotd2iL4jsiNhcOLg4,24770
12
+ pyPreservica/uploadAPI.py,sha256=3XV3_i7mwp0IPcnx1sW4U01rkphtAzq5Se3G_l28wIM,96469
13
+ pyPreservica/webHooksAPI.py,sha256=_K3KUOsmwYf8qMa-mD47sAmNUW7Pzb9oKVpS0VoSbC0,6827
14
+ pyPreservica/workflowAPI.py,sha256=wDDR5_CsJ3dhX79E5mJaziAtgYb830J0ZpNJppzgvqk,17493
15
+ pyPreservica-2.9.1.dist-info/LICENSE.txt,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
16
+ pyPreservica-2.9.1.dist-info/METADATA,sha256=XpwI82CtlJsPW_xAW6zKMNhM9wgpwwv3aGMf2IhEew8,2779
17
+ pyPreservica-2.9.1.dist-info/WHEEL,sha256=YiKiUUeZQGmGJoR_0N1Y933DOBowq4AIvDe2-UIy8E4,91
18
+ pyPreservica-2.9.1.dist-info/top_level.txt,sha256=iIBh6NAznYQHOV8mv_y_kGKSDITek9rANyFDwJsbU-c,13
19
+ pyPreservica-2.9.1.dist-info/RECORD,,
@@ -1,19 +0,0 @@
1
- pyPreservica/__init__.py,sha256=6UJhvPCjdEjhKuNhURC9VU8lW_OIaHSQLv2SIXZmIKE,1159
2
- pyPreservica/adminAPI.py,sha256=511bc5KtrCAXbDyBk39dmDnxUVDaOu6xaiyu0jYhxa4,37781
3
- pyPreservica/authorityAPI.py,sha256=Eule8g6LXr8c8SFcJgpRah4lH1FgevUItO5HhHDEaZE,9172
4
- pyPreservica/common.py,sha256=yZNMlq8aOOLSbFS2DDHYBUWyN5ojDjYUYmcePVbUd44,37636
5
- pyPreservica/contentAPI.py,sha256=F3VwaybSUel0OfhWOckqfM77AVQCD1erHbu-Xrv4cd0,17388
6
- pyPreservica/entityAPI.py,sha256=f-RlCEtUq0KDB62LuSPy0Kb-lT6Hp2gPOmSiTeomqkM,114853
7
- pyPreservica/mdformsAPI.py,sha256=bjfs9ZVvlIovrhKztFsY_S5V5dwppO9tQVSxuGHLWVc,13531
8
- pyPreservica/monitorAPI.py,sha256=HD-PUPdSI9wGAa07e2_2_-FLINH8PoWUwpFogz7F-j4,6269
9
- pyPreservica/opex.py,sha256=ccra1S4ojUXS3PlbU8WfxajOkJrwG4OykBnNrYP_jus,4875
10
- pyPreservica/parAPI.py,sha256=bgaQvYfWNnzdD7ibKMV3ZV85pNkEdSoLsgVigoiFFfw,10771
11
- pyPreservica/retentionAPI.py,sha256=EmQvmUW_I_sPslCiTZDZ2uqloesjfxmmc5AQImWX2cs,23695
12
- pyPreservica/uploadAPI.py,sha256=Nl6Z4h1cW9TmZyrhVLPff3jSAnzCdkfn0xDJ9Q_ZhdI,96444
13
- pyPreservica/webHooksAPI.py,sha256=0wP-59mep8gtlIZ9P5vV68-HnNdTuuo2kzGcDWj0bNg,6790
14
- pyPreservica/workflowAPI.py,sha256=wDDR5_CsJ3dhX79E5mJaziAtgYb830J0ZpNJppzgvqk,17493
15
- pyPreservica-2.8.2.dist-info/LICENSE.txt,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
16
- pyPreservica-2.8.2.dist-info/METADATA,sha256=l0Uj8NmaGYxf_Fy7B8loUMCMF5JiNlDlnJ9Ai4TEkxI,2784
17
- pyPreservica-2.8.2.dist-info/WHEEL,sha256=YiKiUUeZQGmGJoR_0N1Y933DOBowq4AIvDe2-UIy8E4,91
18
- pyPreservica-2.8.2.dist-info/top_level.txt,sha256=iIBh6NAznYQHOV8mv_y_kGKSDITek9rANyFDwJsbU-c,13
19
- pyPreservica-2.8.2.dist-info/RECORD,,