pyPreservica 2.7.2__tar.gz → 2.7.3__tar.gz
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-2.7.2 → pypreservica-2.7.3}/PKG-INFO +10 -1
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/pyPreservica/__init__.py +1 -1
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/pyPreservica/uploadAPI.py +51 -50
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/pyPreservica/workflowAPI.py +4 -4
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/pyPreservica.egg-info/PKG-INFO +10 -1
- pypreservica-2.7.3/pyPreservica.egg-info/SOURCES.txt +45 -0
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/setup.py +1 -1
- pypreservica-2.7.3/tests/test_authority_records.py +20 -0
- pypreservica-2.7.3/tests/test_bitstream.py +77 -0
- pypreservica-2.7.3/tests/test_children.py +75 -0
- pypreservica-2.7.3/tests/test_content_api.py +83 -0
- pypreservica-2.7.3/tests/test_crawl_fs.py +27 -0
- pypreservica-2.7.3/tests/test_delete.py +17 -0
- pypreservica-2.7.3/tests/test_download.py +102 -0
- pypreservica-2.7.3/tests/test_entity.py +323 -0
- pypreservica-2.7.3/tests/test_export_opex.py +36 -0
- pypreservica-2.7.3/tests/test_identifier.py +131 -0
- pypreservica-2.7.3/tests/test_ingest.py +102 -0
- pypreservica-2.7.3/tests/test_integrity_check.py +43 -0
- pypreservica-2.7.3/tests/test_metadata.py +141 -0
- pypreservica-2.7.3/tests/test_par.py +49 -0
- pypreservica-2.7.3/tests/test_replace.py +36 -0
- pypreservica-2.7.3/tests/test_retention.py +133 -0
- pypreservica-2.7.3/tests/test_schema.py +99 -0
- pypreservica-2.7.3/tests/test_security.py +67 -0
- pypreservica-2.7.3/tests/test_thumbnail.py +41 -0
- pypreservica-2.7.3/tests/test_upload.py +151 -0
- pypreservica-2.7.3/tests/test_users.py +43 -0
- pypreservica-2.7.3/tests/test_workflow.py +37 -0
- pypreservica-2.7.3/tests/test_xml_metadata.py +20 -0
- pyPreservica-2.7.2/pyPreservica.egg-info/SOURCES.txt +0 -22
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/LICENSE.txt +0 -0
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/README.md +0 -0
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/pyPreservica/adminAPI.py +0 -0
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/pyPreservica/authorityAPI.py +0 -0
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/pyPreservica/common.py +0 -0
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/pyPreservica/contentAPI.py +0 -0
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/pyPreservica/entityAPI.py +0 -0
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/pyPreservica/mdformsAPI.py +0 -0
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/pyPreservica/monitorAPI.py +0 -0
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/pyPreservica/opex.py +0 -0
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/pyPreservica/parAPI.py +0 -0
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/pyPreservica/retentionAPI.py +0 -0
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/pyPreservica/webHooksAPI.py +0 -0
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/pyPreservica.egg-info/dependency_links.txt +0 -0
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/pyPreservica.egg-info/requires.txt +0 -0
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/pyPreservica.egg-info/top_level.txt +0 -0
- {pyPreservica-2.7.2 → pypreservica-2.7.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyPreservica
|
|
3
|
-
Version: 2.7.
|
|
3
|
+
Version: 2.7.3
|
|
4
4
|
Summary: Python library for the Preservica API
|
|
5
5
|
Home-page: https://pypreservica.readthedocs.io/
|
|
6
6
|
Author: James Carr
|
|
@@ -20,6 +20,15 @@ Classifier: Operating System :: OS Independent
|
|
|
20
20
|
Classifier: Topic :: System :: Archiving
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
22
|
License-File: LICENSE.txt
|
|
23
|
+
Requires-Dist: requests
|
|
24
|
+
Requires-Dist: urllib3
|
|
25
|
+
Requires-Dist: certifi
|
|
26
|
+
Requires-Dist: boto3
|
|
27
|
+
Requires-Dist: botocore
|
|
28
|
+
Requires-Dist: s3transfer
|
|
29
|
+
Requires-Dist: azure-storage-blob
|
|
30
|
+
Requires-Dist: tqdm
|
|
31
|
+
Requires-Dist: pyotp
|
|
23
32
|
|
|
24
33
|
|
|
25
34
|
# pyPreservica
|
|
@@ -99,8 +99,8 @@ def prettify(elem):
|
|
|
99
99
|
def __create_io__(xip=None, file_name=None, parent_folder=None, **kwargs):
|
|
100
100
|
if xip is None:
|
|
101
101
|
xip = Element('xip:XIP')
|
|
102
|
+
xip.set('xmlns:xip', 'http://preservica.com/XIP/v6.0')
|
|
102
103
|
assert xip is not None
|
|
103
|
-
xip.set('xmlns:xip', 'http://preservica.com/XIP/v6.0')
|
|
104
104
|
io = SubElement(xip, 'xip:InformationObject')
|
|
105
105
|
ref = SubElement(io, 'xip:Ref')
|
|
106
106
|
|
|
@@ -598,12 +598,12 @@ def generic_asset_package(preservation_files_dict=None, access_files_dict=None,
|
|
|
598
598
|
for identifier_key, identifier_value in identifier_map.items():
|
|
599
599
|
if identifier_key:
|
|
600
600
|
if identifier_value:
|
|
601
|
-
identifier = SubElement(xip, 'Identifier')
|
|
602
|
-
id_type = SubElement(identifier, "Type")
|
|
601
|
+
identifier = SubElement(xip, 'xip:Identifier')
|
|
602
|
+
id_type = SubElement(identifier, "xip:Type")
|
|
603
603
|
id_type.text = identifier_key
|
|
604
|
-
id_value = SubElement(identifier, "Value")
|
|
604
|
+
id_value = SubElement(identifier, "xip:Value")
|
|
605
605
|
id_value.text = identifier_value
|
|
606
|
-
id_io = SubElement(identifier, "Entity")
|
|
606
|
+
id_io = SubElement(identifier, "xip:Entity")
|
|
607
607
|
id_io.text = io_ref
|
|
608
608
|
|
|
609
609
|
if 'Asset_Metadata' in kwargs:
|
|
@@ -613,22 +613,22 @@ def generic_asset_package(preservation_files_dict=None, access_files_dict=None,
|
|
|
613
613
|
if metadata_path:
|
|
614
614
|
if os.path.exists(metadata_path) and os.path.isfile(metadata_path):
|
|
615
615
|
descriptive_metadata = xml.etree.ElementTree.parse(source=metadata_path)
|
|
616
|
-
metadata = SubElement(xip, 'Metadata', {'schemaUri': metadata_ns})
|
|
617
|
-
metadata_ref = SubElement(metadata, 'Ref')
|
|
616
|
+
metadata = SubElement(xip, 'xip:Metadata', {'schemaUri': metadata_ns})
|
|
617
|
+
metadata_ref = SubElement(metadata, 'xip:Ref')
|
|
618
618
|
metadata_ref.text = str(uuid.uuid4())
|
|
619
|
-
entity = SubElement(metadata, 'Entity')
|
|
619
|
+
entity = SubElement(metadata, 'xip:Entity')
|
|
620
620
|
entity.text = io_ref
|
|
621
|
-
content = SubElement(metadata, 'Content')
|
|
621
|
+
content = SubElement(metadata, 'xip:Content')
|
|
622
622
|
content.append(descriptive_metadata.getroot())
|
|
623
623
|
elif isinstance(metadata_path, str):
|
|
624
624
|
try:
|
|
625
625
|
descriptive_metadata = xml.etree.ElementTree.fromstring(metadata_path)
|
|
626
|
-
metadata = SubElement(xip, 'Metadata', {'schemaUri': metadata_ns})
|
|
627
|
-
metadata_ref = SubElement(metadata, 'Ref')
|
|
626
|
+
metadata = SubElement(xip, 'xip:Metadata', {'schemaUri': metadata_ns})
|
|
627
|
+
metadata_ref = SubElement(metadata, 'xip:Ref')
|
|
628
628
|
metadata_ref.text = str(uuid.uuid4())
|
|
629
|
-
entity = SubElement(metadata, 'Entity')
|
|
629
|
+
entity = SubElement(metadata, 'xip:Entity')
|
|
630
630
|
entity.text = io_ref
|
|
631
|
-
content = SubElement(metadata, 'Content')
|
|
631
|
+
content = SubElement(metadata, 'xip:Content')
|
|
632
632
|
content.append(descriptive_metadata)
|
|
633
633
|
except RuntimeError:
|
|
634
634
|
logging.info(f"Could not parse asset metadata in namespace {metadata_ns}")
|
|
@@ -712,71 +712,72 @@ def multi_asset_package(asset_file_list=None, export_folder=None, parent_folder=
|
|
|
712
712
|
os.mkdir(os.path.join(inner_folder, CONTENT_FOLDER))
|
|
713
713
|
|
|
714
714
|
asset_map = dict()
|
|
715
|
-
xip = Element('XIP')
|
|
715
|
+
xip = Element('xip:XIP')
|
|
716
|
+
xip.set('xmlns:xip', 'http://preservica.com/XIP/v6.0')
|
|
716
717
|
for file in asset_file_list:
|
|
717
718
|
default_asset_title = os.path.splitext(os.path.basename(file))[0]
|
|
718
719
|
xip, io_ref = __create_io__(xip, file_name=default_asset_title, parent_folder=parent_folder, **kwargs)
|
|
719
720
|
asset_map[file] = io_ref
|
|
720
|
-
representation = SubElement(xip, 'Representation')
|
|
721
|
-
io_link = SubElement(representation, 'InformationObject')
|
|
721
|
+
representation = SubElement(xip, 'xip:Representation')
|
|
722
|
+
io_link = SubElement(representation, 'xip:InformationObject')
|
|
722
723
|
io_link.text = io_ref
|
|
723
|
-
access_name = SubElement(representation, 'Name')
|
|
724
|
+
access_name = SubElement(representation, 'xip:Name')
|
|
724
725
|
access_name.text = "Preservation"
|
|
725
|
-
access_type = SubElement(representation, 'Type')
|
|
726
|
+
access_type = SubElement(representation, 'xip:Type')
|
|
726
727
|
access_type.text = "Preservation"
|
|
727
|
-
content_objects = SubElement(representation, 'ContentObjects')
|
|
728
|
-
content_object = SubElement(content_objects, 'ContentObject')
|
|
728
|
+
content_objects = SubElement(representation, 'xip:ContentObjects')
|
|
729
|
+
content_object = SubElement(content_objects, 'xip:ContentObject')
|
|
729
730
|
content_object_ref = str(uuid.uuid4())
|
|
730
731
|
content_object.text = content_object_ref
|
|
731
732
|
|
|
732
733
|
default_content_objects_title = os.path.splitext(os.path.basename(file))[0]
|
|
733
|
-
content_object = SubElement(xip, 'ContentObject')
|
|
734
|
-
ref_element = SubElement(content_object, "Ref")
|
|
734
|
+
content_object = SubElement(xip, 'xip:ContentObject')
|
|
735
|
+
ref_element = SubElement(content_object, "xip:Ref")
|
|
735
736
|
ref_element.text = content_object_ref
|
|
736
|
-
title = SubElement(content_object, "Title")
|
|
737
|
+
title = SubElement(content_object, "xip:Title")
|
|
737
738
|
title.text = default_content_objects_title
|
|
738
|
-
description = SubElement(content_object, "Description")
|
|
739
|
+
description = SubElement(content_object, "xip:Description")
|
|
739
740
|
description.text = default_content_objects_title
|
|
740
|
-
security_tag_element = SubElement(content_object, "SecurityTag")
|
|
741
|
+
security_tag_element = SubElement(content_object, "xip:SecurityTag")
|
|
741
742
|
security_tag_element.text = security_tag
|
|
742
|
-
custom_type = SubElement(content_object, "CustomType")
|
|
743
|
+
custom_type = SubElement(content_object, "xip:CustomType")
|
|
743
744
|
custom_type.text = content_type
|
|
744
|
-
parent = SubElement(content_object, "Parent")
|
|
745
|
+
parent = SubElement(content_object, "xip:Parent")
|
|
745
746
|
parent.text = io_ref
|
|
746
747
|
|
|
747
|
-
generation = SubElement(xip, 'Generation', {"original": "true", "active": "true"})
|
|
748
|
-
content_object = SubElement(generation, "ContentObject")
|
|
748
|
+
generation = SubElement(xip, 'xip:Generation', {"original": "true", "active": "true"})
|
|
749
|
+
content_object = SubElement(generation, "xip:ContentObject")
|
|
749
750
|
content_object.text = content_object_ref
|
|
750
|
-
label = SubElement(generation, "Label")
|
|
751
|
+
label = SubElement(generation, "xip:Label")
|
|
751
752
|
label.text = os.path.splitext(os.path.basename(file))[0]
|
|
752
|
-
effective_date = SubElement(generation, "EffectiveDate")
|
|
753
|
+
effective_date = SubElement(generation, "xip:EffectiveDate")
|
|
753
754
|
effective_date.text = datetime.now().isoformat()
|
|
754
|
-
bitstreams = SubElement(generation, "Bitstreams")
|
|
755
|
-
bitstream = SubElement(bitstreams, "Bitstream")
|
|
755
|
+
bitstreams = SubElement(generation, "xip:Bitstreams")
|
|
756
|
+
bitstream = SubElement(bitstreams, "xip:Bitstream")
|
|
756
757
|
bitstream.text = os.path.basename(file)
|
|
757
|
-
SubElement(generation, "Formats")
|
|
758
|
-
SubElement(generation, "Properties")
|
|
758
|
+
SubElement(generation, "xip:Formats")
|
|
759
|
+
SubElement(generation, "xip:Properties")
|
|
759
760
|
|
|
760
|
-
bitstream = SubElement(xip, 'Bitstream')
|
|
761
|
-
filename_element = SubElement(bitstream, "Filename")
|
|
761
|
+
bitstream = SubElement(xip, 'xip:Bitstream')
|
|
762
|
+
filename_element = SubElement(bitstream, "xip:Filename")
|
|
762
763
|
filename_element.text = os.path.basename(file)
|
|
763
|
-
filesize = SubElement(bitstream, "FileSize")
|
|
764
|
+
filesize = SubElement(bitstream, "xip:FileSize")
|
|
764
765
|
file_stats = os.stat(file)
|
|
765
766
|
filesize.text = str(file_stats.st_size)
|
|
766
|
-
physical_location = SubElement(bitstream, "PhysicalLocation")
|
|
767
|
-
fixities = SubElement(bitstream, "Fixities")
|
|
767
|
+
physical_location = SubElement(bitstream, "xip:PhysicalLocation")
|
|
768
|
+
fixities = SubElement(bitstream, "xip:Fixities")
|
|
768
769
|
fixity_result = fixity_callback(filename_element.text, file)
|
|
769
770
|
if type(fixity_result) == tuple:
|
|
770
|
-
fixity = SubElement(fixities, "Fixity")
|
|
771
|
-
fixity_algorithm_ref = SubElement(fixity, "FixityAlgorithmRef")
|
|
772
|
-
fixity_value = SubElement(fixity, "FixityValue")
|
|
771
|
+
fixity = SubElement(fixities, "xip:Fixity")
|
|
772
|
+
fixity_algorithm_ref = SubElement(fixity, "xip:FixityAlgorithmRef")
|
|
773
|
+
fixity_value = SubElement(fixity, "xip:FixityValue")
|
|
773
774
|
fixity_algorithm_ref.text = fixity_result[0]
|
|
774
775
|
fixity_value.text = fixity_result[1]
|
|
775
776
|
elif type(fixity_result) == dict:
|
|
776
777
|
for key, val in fixity_result.items():
|
|
777
|
-
fixity = SubElement(fixities, "Fixity")
|
|
778
|
-
fixity_algorithm_ref = SubElement(fixity, "FixityAlgorithmRef")
|
|
779
|
-
fixity_value = SubElement(fixity, "FixityValue")
|
|
778
|
+
fixity = SubElement(fixities, "xip:Fixity")
|
|
779
|
+
fixity_algorithm_ref = SubElement(fixity, "xip:FixityAlgorithmRef")
|
|
780
|
+
fixity_value = SubElement(fixity, "xip:FixityValue")
|
|
780
781
|
fixity_algorithm_ref.text = key
|
|
781
782
|
fixity_value.text = val
|
|
782
783
|
else:
|
|
@@ -790,12 +791,12 @@ def multi_asset_package(asset_file_list=None, export_folder=None, parent_folder=
|
|
|
790
791
|
for identifier_key, identifier_value in identifier_map_values.items():
|
|
791
792
|
if identifier_key:
|
|
792
793
|
if identifier_value:
|
|
793
|
-
identifier = SubElement(xip, 'Identifier')
|
|
794
|
-
id_type = SubElement(identifier, "Type")
|
|
794
|
+
identifier = SubElement(xip, 'xip:Identifier')
|
|
795
|
+
id_type = SubElement(identifier, "xip:Type")
|
|
795
796
|
id_type.text = identifier_key
|
|
796
|
-
id_value = SubElement(identifier, "Value")
|
|
797
|
+
id_value = SubElement(identifier, "xip:Value")
|
|
797
798
|
id_value.text = identifier_value
|
|
798
|
-
id_io = SubElement(identifier, "Entity")
|
|
799
|
+
id_io = SubElement(identifier, "xip:Entity")
|
|
799
800
|
id_io.text = io_ref
|
|
800
801
|
|
|
801
802
|
src_file = file
|
|
@@ -245,13 +245,13 @@ class WorkflowAPI(AuthenticatedAPI):
|
|
|
245
245
|
assert instance_id == w_id
|
|
246
246
|
workflow_instance = WorkflowInstance(int(instance_id))
|
|
247
247
|
started_element = entity_response.find(f".//{{{NS_WORKFLOW}}}Started")
|
|
248
|
-
if started_element:
|
|
248
|
+
if started_element is not None:
|
|
249
249
|
if hasattr(started_element, "text"):
|
|
250
250
|
workflow_instance.started = datetime.datetime.strptime(started_element.text,
|
|
251
251
|
'%Y-%m-%dT%H:%M:%S.%fZ')
|
|
252
252
|
|
|
253
253
|
finished_element = entity_response.find(f".//{{{NS_WORKFLOW}}}Finished")
|
|
254
|
-
if finished_element:
|
|
254
|
+
if finished_element is not None:
|
|
255
255
|
if hasattr(finished_element, "text"):
|
|
256
256
|
workflow_instance.finished = datetime.datetime.strptime(finished_element.text,
|
|
257
257
|
'%Y-%m-%dT%H:%M:%S.%fZ')
|
|
@@ -353,13 +353,13 @@ class WorkflowAPI(AuthenticatedAPI):
|
|
|
353
353
|
workflow_instance = WorkflowInstance(int(instance_id))
|
|
354
354
|
|
|
355
355
|
started_element = instance.find(f".//{{{NS_WORKFLOW}}}Started")
|
|
356
|
-
if started_element:
|
|
356
|
+
if started_element is not None:
|
|
357
357
|
if hasattr(started_element, "text"):
|
|
358
358
|
workflow_instance.started = datetime.datetime.strptime(started_element.text,
|
|
359
359
|
'%Y-%m-%dT%H:%M:%S.%fZ')
|
|
360
360
|
|
|
361
361
|
finished_element = instance.find(f".//{{{NS_WORKFLOW}}}Finished")
|
|
362
|
-
if finished_element:
|
|
362
|
+
if finished_element is not None:
|
|
363
363
|
if hasattr(finished_element, "text"):
|
|
364
364
|
workflow_instance.finished = datetime.datetime.strptime(finished_element.text,
|
|
365
365
|
'%Y-%m-%dT%H:%M:%S.%fZ')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyPreservica
|
|
3
|
-
Version: 2.7.
|
|
3
|
+
Version: 2.7.3
|
|
4
4
|
Summary: Python library for the Preservica API
|
|
5
5
|
Home-page: https://pypreservica.readthedocs.io/
|
|
6
6
|
Author: James Carr
|
|
@@ -20,6 +20,15 @@ Classifier: Operating System :: OS Independent
|
|
|
20
20
|
Classifier: Topic :: System :: Archiving
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
22
|
License-File: LICENSE.txt
|
|
23
|
+
Requires-Dist: requests
|
|
24
|
+
Requires-Dist: urllib3
|
|
25
|
+
Requires-Dist: certifi
|
|
26
|
+
Requires-Dist: boto3
|
|
27
|
+
Requires-Dist: botocore
|
|
28
|
+
Requires-Dist: s3transfer
|
|
29
|
+
Requires-Dist: azure-storage-blob
|
|
30
|
+
Requires-Dist: tqdm
|
|
31
|
+
Requires-Dist: pyotp
|
|
23
32
|
|
|
24
33
|
|
|
25
34
|
# pyPreservica
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
LICENSE.txt
|
|
2
|
+
README.md
|
|
3
|
+
setup.py
|
|
4
|
+
pyPreservica/__init__.py
|
|
5
|
+
pyPreservica/adminAPI.py
|
|
6
|
+
pyPreservica/authorityAPI.py
|
|
7
|
+
pyPreservica/common.py
|
|
8
|
+
pyPreservica/contentAPI.py
|
|
9
|
+
pyPreservica/entityAPI.py
|
|
10
|
+
pyPreservica/mdformsAPI.py
|
|
11
|
+
pyPreservica/monitorAPI.py
|
|
12
|
+
pyPreservica/opex.py
|
|
13
|
+
pyPreservica/parAPI.py
|
|
14
|
+
pyPreservica/retentionAPI.py
|
|
15
|
+
pyPreservica/uploadAPI.py
|
|
16
|
+
pyPreservica/webHooksAPI.py
|
|
17
|
+
pyPreservica/workflowAPI.py
|
|
18
|
+
pyPreservica.egg-info/PKG-INFO
|
|
19
|
+
pyPreservica.egg-info/SOURCES.txt
|
|
20
|
+
pyPreservica.egg-info/dependency_links.txt
|
|
21
|
+
pyPreservica.egg-info/requires.txt
|
|
22
|
+
pyPreservica.egg-info/top_level.txt
|
|
23
|
+
tests/test_authority_records.py
|
|
24
|
+
tests/test_bitstream.py
|
|
25
|
+
tests/test_children.py
|
|
26
|
+
tests/test_content_api.py
|
|
27
|
+
tests/test_crawl_fs.py
|
|
28
|
+
tests/test_delete.py
|
|
29
|
+
tests/test_download.py
|
|
30
|
+
tests/test_entity.py
|
|
31
|
+
tests/test_export_opex.py
|
|
32
|
+
tests/test_identifier.py
|
|
33
|
+
tests/test_ingest.py
|
|
34
|
+
tests/test_integrity_check.py
|
|
35
|
+
tests/test_metadata.py
|
|
36
|
+
tests/test_par.py
|
|
37
|
+
tests/test_replace.py
|
|
38
|
+
tests/test_retention.py
|
|
39
|
+
tests/test_schema.py
|
|
40
|
+
tests/test_security.py
|
|
41
|
+
tests/test_thumbnail.py
|
|
42
|
+
tests/test_upload.py
|
|
43
|
+
tests/test_users.py
|
|
44
|
+
tests/test_workflow.py
|
|
45
|
+
tests/test_xml_metadata.py
|
|
@@ -21,7 +21,7 @@ if sys.argv[-1] == 'publish':
|
|
|
21
21
|
# This call to setup() does all the work
|
|
22
22
|
setup(
|
|
23
23
|
name=PKG,
|
|
24
|
-
version="2.7.
|
|
24
|
+
version="2.7.3",
|
|
25
25
|
description="Python library for the Preservica API",
|
|
26
26
|
long_description=README,
|
|
27
27
|
long_description_content_type="text/markdown",
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from pyPreservica import *
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def test_get_tables():
|
|
6
|
+
client = AuthorityAPI()
|
|
7
|
+
results = client.tables()
|
|
8
|
+
assert isinstance(results, set)
|
|
9
|
+
for table in results:
|
|
10
|
+
assert isinstance(table, Table)
|
|
11
|
+
assert table.name in ["Countries", 'Physical Storage']
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def test_get_records():
|
|
15
|
+
client = AuthorityAPI()
|
|
16
|
+
tables = client.tables()
|
|
17
|
+
for tab in tables:
|
|
18
|
+
records = client.records(tab)
|
|
19
|
+
|
|
20
|
+
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from pyPreservica import *
|
|
5
|
+
|
|
6
|
+
ASSET_ID = "b14848b5-4c4d-4d8a-b394-3b764069ee93"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def test_get_representations():
|
|
10
|
+
client = EntityAPI()
|
|
11
|
+
asset = client.asset(ASSET_ID)
|
|
12
|
+
assert asset is not None
|
|
13
|
+
representations = client.representations(asset)
|
|
14
|
+
assert len(representations) == 2
|
|
15
|
+
preservation_representations = list(filter(lambda x: x.rep_type == "Preservation", representations))
|
|
16
|
+
assert len(preservation_representations) == 1
|
|
17
|
+
representation = preservation_representations.pop()
|
|
18
|
+
assert representation.asset.title == asset.title
|
|
19
|
+
assert representation.rep_type == "Preservation"
|
|
20
|
+
assert representation.name == "Preservation-1"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_get_generations():
|
|
24
|
+
client = EntityAPI()
|
|
25
|
+
asset = client.asset(ASSET_ID)
|
|
26
|
+
assert asset is not None
|
|
27
|
+
representations = client.representations(asset)
|
|
28
|
+
assert len(representations) == 2
|
|
29
|
+
preservation_representations = list(filter(lambda x: x.rep_type == "Preservation", representations))
|
|
30
|
+
assert len(preservation_representations) == 1
|
|
31
|
+
representation = preservation_representations.pop()
|
|
32
|
+
assert representation.asset.title == asset.title
|
|
33
|
+
assert representation.rep_type == "Preservation"
|
|
34
|
+
assert representation.name == "Preservation-1"
|
|
35
|
+
content_objects = client.content_objects(representation)
|
|
36
|
+
assert len(content_objects) == 1
|
|
37
|
+
content_object = content_objects[0]
|
|
38
|
+
assert content_object.asset == asset
|
|
39
|
+
generations = client.generations(content_object)
|
|
40
|
+
assert len(generations) == 1
|
|
41
|
+
generation = generations[0]
|
|
42
|
+
assert generation.active is True
|
|
43
|
+
assert generation.original is True
|
|
44
|
+
assert generation.format_group == "tiff"
|
|
45
|
+
access_representations = list(filter(lambda x: x.rep_type == "Access", representations))
|
|
46
|
+
assert len(access_representations) == 1
|
|
47
|
+
representation = access_representations.pop()
|
|
48
|
+
assert representation.asset.title == asset.title
|
|
49
|
+
assert representation.rep_type == "Access"
|
|
50
|
+
assert representation.name == "Access Copy"
|
|
51
|
+
content_objects = client.content_objects(representation)
|
|
52
|
+
assert len(content_objects) == 1
|
|
53
|
+
content_object = content_objects[0]
|
|
54
|
+
assert content_object.asset == asset
|
|
55
|
+
generations = client.generations(content_object)
|
|
56
|
+
assert len(generations) == 1
|
|
57
|
+
generation = generations[0]
|
|
58
|
+
assert generation.active is True
|
|
59
|
+
assert generation.original is False
|
|
60
|
+
assert generation.format_group == "jpeg"
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def test_get_bitstream_content():
|
|
64
|
+
client = EntityAPI()
|
|
65
|
+
asset = client.asset(ASSET_ID)
|
|
66
|
+
preservation_representations = list(filter(lambda x: x.rep_type == "Preservation", client.representations(asset)))
|
|
67
|
+
preservation_content_objects = client.content_objects(preservation_representations.pop())
|
|
68
|
+
generation = client.generations(preservation_content_objects[0])[0]
|
|
69
|
+
assert generation.format_group == "tiff"
|
|
70
|
+
assert len(generation.bitstreams) == 1
|
|
71
|
+
bitstream = generation.bitstreams[0]
|
|
72
|
+
assert bitstream.filename == "LC-USZ62-51820.tiff"
|
|
73
|
+
assert bitstream.length == 1942466
|
|
74
|
+
client.bitstream_content(bitstream, bitstream.filename)
|
|
75
|
+
assert os.path.isfile(bitstream.filename) is True
|
|
76
|
+
assert Path(bitstream.filename).stat().st_size == 1942466
|
|
77
|
+
os.remove(bitstream.filename)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import xml
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from pyPreservica import *
|
|
5
|
+
|
|
6
|
+
FOLDER_ID = "ebd977f6-bebd-4ecf-99be-e054989f9af4"
|
|
7
|
+
ASSET_ID = "683f9db7-ff81-4859-9c03-f68cfa5d9c3d"
|
|
8
|
+
CO_ID = "0f2997f7-728c-4e55-9f92-381ed1260d70"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_get_root_folders():
|
|
12
|
+
client = EntityAPI()
|
|
13
|
+
paged_set = client.children(None)
|
|
14
|
+
assert paged_set.total > 0
|
|
15
|
+
objs = set()
|
|
16
|
+
for f in paged_set.results:
|
|
17
|
+
assert f.entity_type == EntityType.FOLDER
|
|
18
|
+
assert f.parent is None
|
|
19
|
+
objs.add(f)
|
|
20
|
+
assert len(objs) == paged_set.total
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_get_root_folders_descendants():
|
|
24
|
+
client = EntityAPI()
|
|
25
|
+
for f in client.descendants(None):
|
|
26
|
+
assert f.entity_type == EntityType.FOLDER
|
|
27
|
+
assert f.parent is None
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_get_root_folder1():
|
|
31
|
+
client = EntityAPI()
|
|
32
|
+
paged_set = client.children()
|
|
33
|
+
assert paged_set.total > 0
|
|
34
|
+
objs = set()
|
|
35
|
+
for f in paged_set.results:
|
|
36
|
+
assert f.entity_type == EntityType.FOLDER
|
|
37
|
+
assert f.parent is None
|
|
38
|
+
objs.add(f)
|
|
39
|
+
assert len(objs) == paged_set.total
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_get_root_folders_paged():
|
|
43
|
+
client = EntityAPI()
|
|
44
|
+
objs = set()
|
|
45
|
+
url = None
|
|
46
|
+
while True:
|
|
47
|
+
paged_set = client.children(None, maximum=3, next_page=url)
|
|
48
|
+
assert paged_set.total > 0
|
|
49
|
+
for f in paged_set.results:
|
|
50
|
+
assert f.entity_type == EntityType.FOLDER
|
|
51
|
+
assert f.parent is None
|
|
52
|
+
objs.add(f)
|
|
53
|
+
url = paged_set.next_page
|
|
54
|
+
if url is None:
|
|
55
|
+
break
|
|
56
|
+
assert len(objs) == paged_set.total
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_get_children_of_folder():
|
|
60
|
+
client = EntityAPI()
|
|
61
|
+
paged_set = client.children(FOLDER_ID)
|
|
62
|
+
assert paged_set.total == 171
|
|
63
|
+
for f in paged_set.results:
|
|
64
|
+
assert f.entity_type == EntityType.ASSET
|
|
65
|
+
assert f.parent == FOLDER_ID
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def test_get_children_of_folder_descendants():
|
|
69
|
+
client = EntityAPI()
|
|
70
|
+
objs = set()
|
|
71
|
+
for f in client.descendants(FOLDER_ID):
|
|
72
|
+
assert f.entity_type == EntityType.ASSET
|
|
73
|
+
assert f.parent == FOLDER_ID
|
|
74
|
+
objs.add(f)
|
|
75
|
+
assert len(objs) == 171
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from pyPreservica import *
|
|
4
|
+
|
|
5
|
+
FOLDER_ID = "ebd977f6-bebd-4ecf-99be-e054989f9af4"
|
|
6
|
+
ASSET_ID = "683f9db7-ff81-4859-9c03-f68cfa5d9c3d"
|
|
7
|
+
CO_ID = "0f2997f7-728c-4e55-9f92-381ed1260d70"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_get_asset_details():
|
|
11
|
+
client = ContentAPI()
|
|
12
|
+
json_dict = client.object_details(EntityType.ASSET, ASSET_ID)
|
|
13
|
+
assert json_dict is not None
|
|
14
|
+
assert json_dict['id'] == 'sdb:IO|683f9db7-ff81-4859-9c03-f68cfa5d9c3d'
|
|
15
|
+
assert json_dict['name'] == 'LC-USZ62-20901'
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_download_asset():
|
|
19
|
+
client = ContentAPI()
|
|
20
|
+
filename = client.download(ASSET_ID, "filename.img")
|
|
21
|
+
assert os.path.exists(filename)
|
|
22
|
+
os.remove(filename)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_download_folder():
|
|
26
|
+
client = ContentAPI()
|
|
27
|
+
with pytest.raises(RuntimeError):
|
|
28
|
+
filename = client.download(FOLDER_ID, "filename.img")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_get_thumbnail_small():
|
|
32
|
+
client = ContentAPI()
|
|
33
|
+
small = client.thumbnail("IO", "464444f7-8a6e-40f3-86c3-1dd2a51cfeeb", "filename.img", Thumbnail.SMALL)
|
|
34
|
+
assert os.path.exists(small)
|
|
35
|
+
os.remove(small)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_get_thumbnail_med():
|
|
39
|
+
client = ContentAPI()
|
|
40
|
+
med = client.thumbnail("IO", "8d268bed-93d7-449b-91e4-2e7e86562a07", "filename.img", Thumbnail.MEDIUM)
|
|
41
|
+
assert os.path.exists(med)
|
|
42
|
+
os.remove(med)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_get_thumbnail_large():
|
|
46
|
+
client = ContentAPI()
|
|
47
|
+
large = client.thumbnail("IO", "d5048e76-79c5-4ca7-99c9-a202c8f6dc8b", "filename.img", Thumbnail.LARGE)
|
|
48
|
+
assert os.path.exists(large)
|
|
49
|
+
os.remove(large)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_get_indexed_fields():
|
|
53
|
+
client = ContentAPI()
|
|
54
|
+
fields = client.indexed_fields()
|
|
55
|
+
assert fields is not None
|
|
56
|
+
assert 'xip.title' in fields
|
|
57
|
+
assert 'xip.description' in fields
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test_simple_search_list():
|
|
61
|
+
client = ContentAPI()
|
|
62
|
+
results = list(client.simple_search_list(query="pyPreservica"))
|
|
63
|
+
assert len(results) == 2
|
|
64
|
+
assert results.pop()['xip.reference'] == '9fd239eb-19a3-4a46-9495-40fd9a5d8f93'
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def test_simple_search_list2():
|
|
68
|
+
client = ContentAPI()
|
|
69
|
+
|
|
70
|
+
columns = ["xip.reference", "xip.title", "xip.description", "xip.document_type"]
|
|
71
|
+
|
|
72
|
+
results = list(client.simple_search_list("pyPreservica", 25, columns))
|
|
73
|
+
assert len(results) == 2
|
|
74
|
+
assert results.pop()['xip.reference'] == '9fd239eb-19a3-4a46-9495-40fd9a5d8f93'
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def test_field_search():
|
|
78
|
+
search = ContentAPI()
|
|
79
|
+
for result in search.search_index_filter_list(query="%", filter_values={"xip.security_descriptor": "open",
|
|
80
|
+
"xip.document_type": "IO",
|
|
81
|
+
"xip.parent_hierarchy": FOLDER_ID}):
|
|
82
|
+
assert result is not None
|
|
83
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from pyPreservica import *
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def test_crawl_fs():
|
|
6
|
+
path = "./test_data/"
|
|
7
|
+
bucket = "com.preservica.dev.preview.sales.autoupload"
|
|
8
|
+
|
|
9
|
+
client = UploadAPI()
|
|
10
|
+
entity = EntityAPI()
|
|
11
|
+
|
|
12
|
+
parent = entity.folder("daa88307-4a0b-4962-a5a9-6a1387f9f876")
|
|
13
|
+
|
|
14
|
+
for e in entity.all_descendants(parent):
|
|
15
|
+
if e.entity_type == EntityType.ASSET:
|
|
16
|
+
entity.delete_asset(e, "delete", "delete")
|
|
17
|
+
else:
|
|
18
|
+
entity.delete_folder(e, "delete", "delete")
|
|
19
|
+
|
|
20
|
+
client.crawl_filesystem(filesystem_path=path, bucket_name=bucket,
|
|
21
|
+
preservica_parent="daa88307-4a0b-4962-a5a9-6a1387f9f876")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from pyPreservica import *
|
|
3
|
+
|
|
4
|
+
FOLDER_ID = "ebd977f6-bebd-4ecf-99be-e054989f9af4"
|
|
5
|
+
ASSET_ID = "683f9db7-ff81-4859-9c03-f68cfa5d9c3d"
|
|
6
|
+
CO_ID = "0f2997f7-728c-4e55-9f92-381ed1260d70"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def test_delete_folder():
|
|
10
|
+
client = EntityAPI()
|
|
11
|
+
folder = client.folder(FOLDER_ID)
|
|
12
|
+
assert folder
|
|
13
|
+
new_folder = client.create_folder(title="title", description="description", security_tag="open",
|
|
14
|
+
parent=folder.parent)
|
|
15
|
+
assert folder.parent == new_folder.parent
|
|
16
|
+
ref = client.delete_folder(new_folder, "operator", "supervisor")
|
|
17
|
+
assert ref == new_folder.reference
|