pyPreservica 2.7.3__tar.gz → 2.7.4__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.3 → pypreservica-2.7.4}/PKG-INFO +1 -1
- {pypreservica-2.7.3 → pypreservica-2.7.4}/pyPreservica/__init__.py +1 -1
- {pypreservica-2.7.3 → pypreservica-2.7.4}/pyPreservica/common.py +30 -4
- {pypreservica-2.7.3 → pypreservica-2.7.4}/pyPreservica/contentAPI.py +9 -5
- {pypreservica-2.7.3 → pypreservica-2.7.4}/pyPreservica/entityAPI.py +7 -3
- {pypreservica-2.7.3 → pypreservica-2.7.4}/pyPreservica/mdformsAPI.py +7 -2
- {pypreservica-2.7.3 → pypreservica-2.7.4}/pyPreservica/retentionAPI.py +5 -3
- {pypreservica-2.7.3 → pypreservica-2.7.4}/pyPreservica/uploadAPI.py +100 -48
- {pypreservica-2.7.3 → pypreservica-2.7.4}/pyPreservica/workflowAPI.py +7 -3
- {pypreservica-2.7.3 → pypreservica-2.7.4}/pyPreservica.egg-info/PKG-INFO +1 -1
- {pypreservica-2.7.3 → pypreservica-2.7.4}/setup.py +1 -1
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_crawl_fs.py +1 -1
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_ingest.py +1 -1
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_workflow.py +2 -2
- {pypreservica-2.7.3 → pypreservica-2.7.4}/LICENSE.txt +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/README.md +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/pyPreservica/adminAPI.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/pyPreservica/authorityAPI.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/pyPreservica/monitorAPI.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/pyPreservica/opex.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/pyPreservica/parAPI.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/pyPreservica/webHooksAPI.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/pyPreservica.egg-info/SOURCES.txt +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/pyPreservica.egg-info/dependency_links.txt +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/pyPreservica.egg-info/requires.txt +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/pyPreservica.egg-info/top_level.txt +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/setup.cfg +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_authority_records.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_bitstream.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_children.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_content_api.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_delete.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_download.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_entity.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_export_opex.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_identifier.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_integrity_check.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_metadata.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_par.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_replace.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_retention.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_schema.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_security.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_thumbnail.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_upload.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_users.py +0 -0
- {pypreservica-2.7.3 → pypreservica-2.7.4}/tests/test_xml_metadata.py +0 -0
|
@@ -477,10 +477,10 @@ class Entity:
|
|
|
477
477
|
def __repr__(self):
|
|
478
478
|
return self.__str__()
|
|
479
479
|
|
|
480
|
-
def has_metadata(self):
|
|
480
|
+
def has_metadata(self) -> bool:
|
|
481
481
|
return bool(self.metadata)
|
|
482
482
|
|
|
483
|
-
def metadata_namespaces(self):
|
|
483
|
+
def metadata_namespaces(self) -> list:
|
|
484
484
|
return list(self.metadata.values())
|
|
485
485
|
|
|
486
486
|
|
|
@@ -714,11 +714,33 @@ class AuthenticatedAPI:
|
|
|
714
714
|
|
|
715
715
|
return entity_dict
|
|
716
716
|
|
|
717
|
+
def edition(self) -> str:
|
|
718
|
+
"""
|
|
719
|
+
Return the edition of this tenancy
|
|
720
|
+
"""
|
|
721
|
+
if self.major_version < 8 and self.minor_version < 3:
|
|
722
|
+
raise RuntimeError("Entitlement API is only available when connected to a v7.3 System")
|
|
723
|
+
|
|
724
|
+
headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/json'}
|
|
725
|
+
|
|
726
|
+
response = self.session.get(f'{self.protocol}://{self.server}/api/entitlement/edition', headers=headers)
|
|
727
|
+
|
|
728
|
+
if response.status_code == requests.codes.ok:
|
|
729
|
+
return response.json()['edition']
|
|
730
|
+
elif response.status_code == requests.codes.unauthorized:
|
|
731
|
+
self.token = self.__token__()
|
|
732
|
+
return self.edition()
|
|
733
|
+
else:
|
|
734
|
+
exception = HTTPException("", response.status_code, response.url,
|
|
735
|
+
"edition", response.content.decode('utf-8'))
|
|
736
|
+
logger.error(exception)
|
|
737
|
+
raise exception
|
|
738
|
+
|
|
717
739
|
def __version_namespace__(self):
|
|
718
740
|
"""
|
|
719
741
|
Generate version specific namespaces from the server version
|
|
720
742
|
"""
|
|
721
|
-
if self.major_version
|
|
743
|
+
if self.major_version > 6:
|
|
722
744
|
self.xip_ns = f"{NS_XIP_ROOT}v{self.major_version}.{self.minor_version}"
|
|
723
745
|
self.entity_ns = f"{NS_ENTITY_ROOT}v{self.major_version}.{self.minor_version}"
|
|
724
746
|
self.rm_ns = f"{NS_RM_ROOT}v{6}.{2}"
|
|
@@ -857,12 +879,16 @@ class AuthenticatedAPI:
|
|
|
857
879
|
raise RuntimeError(response.status_code, msg)
|
|
858
880
|
|
|
859
881
|
def __init__(self, username: str = None, password: str = None, tenant: str = None, server: str = None,
|
|
860
|
-
use_shared_secret: bool = False, two_fa_secret_key: str = None,
|
|
882
|
+
use_shared_secret: bool = False, two_fa_secret_key: str = None,
|
|
883
|
+
protocol: str = "https", request_hook=None):
|
|
861
884
|
|
|
862
885
|
config = configparser.ConfigParser(interpolation=configparser.Interpolation())
|
|
863
886
|
config.read('credentials.properties', encoding='utf-8')
|
|
864
887
|
self.session: Session = requests.Session()
|
|
865
888
|
|
|
889
|
+
if request_hook is not None:
|
|
890
|
+
self.session.hooks['response'].append(request_hook)
|
|
891
|
+
|
|
866
892
|
retries = Retry(
|
|
867
893
|
total=3,
|
|
868
894
|
backoff_factor=0.1,
|
|
@@ -10,7 +10,7 @@ licence: Apache License 2.0
|
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
import csv
|
|
13
|
-
from typing import Generator
|
|
13
|
+
from typing import Generator, Callable
|
|
14
14
|
from pyPreservica.common import *
|
|
15
15
|
|
|
16
16
|
logger = logging.getLogger(__name__)
|
|
@@ -19,8 +19,10 @@ logger = logging.getLogger(__name__)
|
|
|
19
19
|
class ContentAPI(AuthenticatedAPI):
|
|
20
20
|
|
|
21
21
|
def __init__(self, username=None, password=None, tenant=None, server=None, use_shared_secret=False,
|
|
22
|
-
two_fa_secret_key: str = None, protocol: str = "https"):
|
|
23
|
-
|
|
22
|
+
two_fa_secret_key: str = None, protocol: str = "https", request_hook: Callable = None):
|
|
23
|
+
|
|
24
|
+
super().__init__(username, password, tenant, server, use_shared_secret, two_fa_secret_key,
|
|
25
|
+
protocol, request_hook)
|
|
24
26
|
self.callback = None
|
|
25
27
|
|
|
26
28
|
class SearchResult:
|
|
@@ -130,7 +132,8 @@ class ContentAPI(AuthenticatedAPI):
|
|
|
130
132
|
logger.error(f"indexed_fields failed with error code: {results.status_code}")
|
|
131
133
|
raise RuntimeError(results.status_code, f"indexed_fields failed with error code: {results.status_code}")
|
|
132
134
|
|
|
133
|
-
def simple_search_csv(self, query: str = "%", page_size: int = 50, csv_file="search.csv",
|
|
135
|
+
def simple_search_csv(self, query: str = "%", page_size: int = 50, csv_file="search.csv",
|
|
136
|
+
list_indexes: list = None):
|
|
134
137
|
if list_indexes is None or len(list_indexes) == 0:
|
|
135
138
|
metadata_fields = ["xip.reference", "xip.title", "xip.description", "xip.document_type",
|
|
136
139
|
"xip.parent_ref", "xip.security_descriptor"]
|
|
@@ -193,7 +196,8 @@ class ContentAPI(AuthenticatedAPI):
|
|
|
193
196
|
logger.error(f"search failed with error code: {results.status_code}")
|
|
194
197
|
raise RuntimeError(results.status_code, f"simple_search failed with error code: {results.status_code}")
|
|
195
198
|
|
|
196
|
-
def search_index_filter_csv(self, query: str = "%", csv_file="search.csv", page_size: int = 50,
|
|
199
|
+
def search_index_filter_csv(self, query: str = "%", csv_file="search.csv", page_size: int = 50,
|
|
200
|
+
filter_values: dict = None,
|
|
197
201
|
sort_values: dict = None):
|
|
198
202
|
if filter_values is None:
|
|
199
203
|
filter_values = {}
|
|
@@ -15,7 +15,7 @@ import xml.etree.ElementTree
|
|
|
15
15
|
from datetime import datetime, timedelta, timezone
|
|
16
16
|
from io import BytesIO
|
|
17
17
|
from time import sleep
|
|
18
|
-
from typing import Any, Generator, Tuple, Iterable, Union
|
|
18
|
+
from typing import Any, Generator, Tuple, Iterable, Union, Callable
|
|
19
19
|
|
|
20
20
|
from pyPreservica.common import *
|
|
21
21
|
|
|
@@ -34,8 +34,12 @@ class EntityAPI(AuthenticatedAPI):
|
|
|
34
34
|
"""
|
|
35
35
|
|
|
36
36
|
def __init__(self, username: str = None, password: str = None, tenant: str = None, server: str = None,
|
|
37
|
-
use_shared_secret: bool = False, two_fa_secret_key: str = None,
|
|
38
|
-
|
|
37
|
+
use_shared_secret: bool = False, two_fa_secret_key: str = None,
|
|
38
|
+
protocol: str = "https", request_hook: Callable = None):
|
|
39
|
+
|
|
40
|
+
super().__init__(username, password, tenant, server, use_shared_secret, two_fa_secret_key,
|
|
41
|
+
protocol, request_hook)
|
|
42
|
+
|
|
39
43
|
xml.etree.ElementTree.register_namespace("oai_dc", "http://www.openarchives.org/OAI/2.0/oai_dc/")
|
|
40
44
|
xml.etree.ElementTree.register_namespace("ead", "urn:isbn:1-931666-22-9")
|
|
41
45
|
|
|
@@ -10,14 +10,19 @@ licence: Apache License 2.0
|
|
|
10
10
|
"""
|
|
11
11
|
import json
|
|
12
12
|
import xml.etree.ElementTree
|
|
13
|
+
from typing import Callable
|
|
13
14
|
|
|
14
15
|
from pyPreservica.common import *
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
class MDFormsAPI(AuthenticatedAPI):
|
|
18
19
|
def __init__(self, username: str = None, password: str = None, tenant: str = None, server: str = None,
|
|
19
|
-
use_shared_secret: bool = False, two_fa_secret_key: str = None,
|
|
20
|
-
|
|
20
|
+
use_shared_secret: bool = False, two_fa_secret_key: str = None,
|
|
21
|
+
protocol: str = "https", request_hook: Callable = None):
|
|
22
|
+
|
|
23
|
+
super().__init__(username, password, tenant, server, use_shared_secret, two_fa_secret_key,
|
|
24
|
+
protocol, request_hook)
|
|
25
|
+
|
|
21
26
|
xml.etree.ElementTree.register_namespace("oai_dc", "http://www.openarchives.org/OAI/2.0/oai_dc/")
|
|
22
27
|
xml.etree.ElementTree.register_namespace("ead", "urn:isbn:1-931666-22-9")
|
|
23
28
|
|
|
@@ -11,7 +11,7 @@ licence: Apache License 2.0
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
import xml.etree.ElementTree
|
|
14
|
-
from typing import Set
|
|
14
|
+
from typing import Set, Callable
|
|
15
15
|
|
|
16
16
|
from pyPreservica.common import *
|
|
17
17
|
|
|
@@ -59,8 +59,10 @@ class RetentionPolicy:
|
|
|
59
59
|
class RetentionAPI(AuthenticatedAPI):
|
|
60
60
|
|
|
61
61
|
def __init__(self, username=None, password=None, tenant=None, server=None, use_shared_secret=False,
|
|
62
|
-
two_fa_secret_key: str = None, protocol: str = "https"):
|
|
63
|
-
|
|
62
|
+
two_fa_secret_key: str = None, protocol: str = "https", request_hook: Callable = None):
|
|
63
|
+
|
|
64
|
+
super().__init__(username, password, tenant, server, use_shared_secret, two_fa_secret_key,
|
|
65
|
+
protocol, request_hook)
|
|
64
66
|
if self.major_version < 7 and self.minor_version < 2:
|
|
65
67
|
raise RuntimeError("Retention API is only available when connected to a v6.2 System")
|
|
66
68
|
|
|
@@ -80,7 +80,8 @@ class PutObjectTask(s3transfer.tasks.Task):
|
|
|
80
80
|
class CompleteMultipartUploadTask(s3transfer.tasks.Task):
|
|
81
81
|
# Copied from s3transfer/tasks.py, changed to return a result.
|
|
82
82
|
def _main(self, client, bucket, key, upload_id, parts, extra_args):
|
|
83
|
-
return client.complete_multipart_upload(Bucket=bucket, Key=key, UploadId=upload_id,
|
|
83
|
+
return client.complete_multipart_upload(Bucket=bucket, Key=key, UploadId=upload_id,
|
|
84
|
+
MultipartUpload={"Parts": parts},
|
|
84
85
|
**extra_args, )
|
|
85
86
|
|
|
86
87
|
|
|
@@ -224,7 +225,8 @@ def __make_representation_multiple_co__(xip, rep_name, rep_type, rep_files, io_r
|
|
|
224
225
|
return refs_dict
|
|
225
226
|
|
|
226
227
|
|
|
227
|
-
def cvs_to_cmis_xslt(csv_file, xml_namespace, root_element, title="Metadata Title", export_folder=None,
|
|
228
|
+
def cvs_to_cmis_xslt(csv_file, xml_namespace, root_element, title="Metadata Title", export_folder=None,
|
|
229
|
+
additional_namespaces=None):
|
|
228
230
|
"""
|
|
229
231
|
Create a custom CMIS transform to display metadata within UA.
|
|
230
232
|
|
|
@@ -242,7 +244,8 @@ def cvs_to_cmis_xslt(csv_file, xml_namespace, root_element, title="Metadata Titl
|
|
|
242
244
|
|
|
243
245
|
namespaces = {"version": "2.0", "xmlns:xsl": "http://www.w3.org/1999/XSL/Transform",
|
|
244
246
|
"xmlns:fn": "http://www.w3.org/2005/xpath-functions", "xmlns:xs": "http://www.w3.org/2001/XMLSchema",
|
|
245
|
-
"xmlns:csv": xml_namespace, "xmlns": "http://www.tessella.com/sdb/cmis/metadata",
|
|
247
|
+
"xmlns:csv": xml_namespace, "xmlns": "http://www.tessella.com/sdb/cmis/metadata",
|
|
248
|
+
"exclude-result-prefixes": "csv"}
|
|
246
249
|
|
|
247
250
|
if additional_namespaces is not None:
|
|
248
251
|
for prefix, uri in additional_namespaces.items():
|
|
@@ -311,7 +314,8 @@ def cvs_to_xsd(csv_file, xml_namespace, root_element, export_folder=None, additi
|
|
|
311
314
|
headers.add(xml_tag)
|
|
312
315
|
break
|
|
313
316
|
|
|
314
|
-
namespaces = {"xmlns:xs": "http://www.w3.org/2001/XMLSchema", "attributeFormDefault": "unqualified",
|
|
317
|
+
namespaces = {"xmlns:xs": "http://www.w3.org/2001/XMLSchema", "attributeFormDefault": "unqualified",
|
|
318
|
+
"elementFormDefault": "qualified",
|
|
315
319
|
"targetNamespace": xml_namespace}
|
|
316
320
|
|
|
317
321
|
if additional_namespaces is not None:
|
|
@@ -333,7 +337,8 @@ def cvs_to_xsd(csv_file, xml_namespace, root_element, export_folder=None, additi
|
|
|
333
337
|
prefix, sep, tag = header.partition(":")
|
|
334
338
|
try:
|
|
335
339
|
namespace = additional_namespaces[prefix]
|
|
336
|
-
xml.etree.ElementTree.SubElement(xml_sequence, "xs:element",
|
|
340
|
+
xml.etree.ElementTree.SubElement(xml_sequence, "xs:element",
|
|
341
|
+
{"ref": header, "xmlns:" + prefix: namespace})
|
|
337
342
|
except KeyError:
|
|
338
343
|
xml.etree.ElementTree.SubElement(xml_sequence, "xs:element", {"type": "xs:string", "name": header})
|
|
339
344
|
else:
|
|
@@ -350,7 +355,8 @@ def cvs_to_xsd(csv_file, xml_namespace, root_element, export_folder=None, additi
|
|
|
350
355
|
return xsd_file
|
|
351
356
|
|
|
352
357
|
|
|
353
|
-
def csv_to_search_xml(csv_file, xml_namespace, root_element, title="Metadata Title", export_folder=None,
|
|
358
|
+
def csv_to_search_xml(csv_file, xml_namespace, root_element, title="Metadata Title", export_folder=None,
|
|
359
|
+
additional_namespaces=None):
|
|
354
360
|
"""
|
|
355
361
|
Create a custom Preservica search index based on the columns in a csv file
|
|
356
362
|
|
|
@@ -400,7 +406,8 @@ def csv_to_search_xml(csv_file, xml_namespace, root_element, title="Metadata Tit
|
|
|
400
406
|
return search_xml
|
|
401
407
|
|
|
402
408
|
|
|
403
|
-
def cvs_to_xml(csv_file, xml_namespace, root_element, file_name_column="filename", export_folder=None,
|
|
409
|
+
def cvs_to_xml(csv_file, xml_namespace, root_element, file_name_column="filename", export_folder=None,
|
|
410
|
+
additional_namespaces=None):
|
|
404
411
|
"""
|
|
405
412
|
Export the rows of a CSV file as XML metadata documents which can be added to Preservica assets
|
|
406
413
|
|
|
@@ -451,7 +458,8 @@ def cvs_to_xml(csv_file, xml_namespace, root_element, file_name_column="filename
|
|
|
451
458
|
yield name
|
|
452
459
|
|
|
453
460
|
|
|
454
|
-
def generic_asset_package(preservation_files_dict=None, access_files_dict=None, export_folder=None, parent_folder=None,
|
|
461
|
+
def generic_asset_package(preservation_files_dict=None, access_files_dict=None, export_folder=None, parent_folder=None,
|
|
462
|
+
compress=True,
|
|
455
463
|
**kwargs):
|
|
456
464
|
# some basic validation
|
|
457
465
|
if export_folder is None:
|
|
@@ -501,8 +509,10 @@ def generic_asset_package(preservation_files_dict=None, access_files_dict=None,
|
|
|
501
509
|
if has_preservation_files:
|
|
502
510
|
for representation_name in preservation_files_dict.keys():
|
|
503
511
|
preservation_files_list = preservation_files_dict[representation_name]
|
|
504
|
-
preservation_refs_dict = __make_representation_multiple_co__(xip, rep_name=representation_name,
|
|
505
|
-
|
|
512
|
+
preservation_refs_dict = __make_representation_multiple_co__(xip, rep_name=representation_name,
|
|
513
|
+
rep_type="Preservation",
|
|
514
|
+
rep_files=preservation_files_list,
|
|
515
|
+
io_ref=io_ref)
|
|
506
516
|
preservation_representation_refs_dict[representation_name] = preservation_refs_dict
|
|
507
517
|
|
|
508
518
|
if has_access_files:
|
|
@@ -519,13 +529,16 @@ def generic_asset_package(preservation_files_dict=None, access_files_dict=None,
|
|
|
519
529
|
default_content_objects_title = os.path.splitext(os.path.basename(filename))[0]
|
|
520
530
|
|
|
521
531
|
preservation_content_title = kwargs.get('Preservation_Content_Title', default_content_objects_title)
|
|
522
|
-
preservation_content_description = kwargs.get('Preservation_Content_Description',
|
|
532
|
+
preservation_content_description = kwargs.get('Preservation_Content_Description',
|
|
533
|
+
default_content_objects_title)
|
|
523
534
|
|
|
524
535
|
if isinstance(preservation_content_title, dict):
|
|
525
|
-
preservation_content_title = preservation_content_title.get("filename",
|
|
536
|
+
preservation_content_title = preservation_content_title.get("filename",
|
|
537
|
+
default_content_objects_title)
|
|
526
538
|
|
|
527
539
|
if isinstance(preservation_content_description, dict):
|
|
528
|
-
preservation_content_description = preservation_content_description.get("filename",
|
|
540
|
+
preservation_content_description = preservation_content_description.get("filename",
|
|
541
|
+
default_content_objects_title)
|
|
529
542
|
|
|
530
543
|
__make_content_objects__(xip, preservation_content_title, content_ref, io_ref, security_tag,
|
|
531
544
|
preservation_content_description, content_type)
|
|
@@ -545,7 +558,8 @@ def generic_asset_package(preservation_files_dict=None, access_files_dict=None,
|
|
|
545
558
|
if isinstance(access_content_description, dict):
|
|
546
559
|
access_content_description = access_content_title.get("filename", default_content_objects_title)
|
|
547
560
|
|
|
548
|
-
__make_content_objects__(xip, access_content_title, content_ref, io_ref, security_tag,
|
|
561
|
+
__make_content_objects__(xip, access_content_title, content_ref, io_ref, security_tag,
|
|
562
|
+
access_content_description,
|
|
549
563
|
content_type)
|
|
550
564
|
|
|
551
565
|
if has_preservation_files:
|
|
@@ -816,7 +830,8 @@ def multi_asset_package(asset_file_list=None, export_folder=None, parent_folder=
|
|
|
816
830
|
return top_level_folder + ".zip"
|
|
817
831
|
|
|
818
832
|
|
|
819
|
-
def complex_asset_package(preservation_files_list=None, access_files_list=None, export_folder=None, parent_folder=None,
|
|
833
|
+
def complex_asset_package(preservation_files_list=None, access_files_list=None, export_folder=None, parent_folder=None,
|
|
834
|
+
compress=True,
|
|
820
835
|
**kwargs):
|
|
821
836
|
"""
|
|
822
837
|
|
|
@@ -909,13 +924,15 @@ def complex_asset_package(preservation_files_list=None, access_files_list=None,
|
|
|
909
924
|
if has_preservation_files:
|
|
910
925
|
# add the content objects
|
|
911
926
|
representation_name = kwargs.get('Preservation_Representation_Name', "Preservation")
|
|
912
|
-
preservation_refs_dict = __make_representation_multiple_co__(xip, rep_name=representation_name,
|
|
927
|
+
preservation_refs_dict = __make_representation_multiple_co__(xip, rep_name=representation_name,
|
|
928
|
+
rep_type="Preservation",
|
|
913
929
|
rep_files=preservation_files_list, io_ref=io_ref)
|
|
914
930
|
|
|
915
931
|
if has_access_files:
|
|
916
932
|
# add the content objects
|
|
917
933
|
access_name = kwargs.get('Access_Representation_Name', "Access")
|
|
918
|
-
access_refs_dict = __make_representation_multiple_co__(xip, rep_name=access_name, rep_type="Access",
|
|
934
|
+
access_refs_dict = __make_representation_multiple_co__(xip, rep_name=access_name, rep_type="Access",
|
|
935
|
+
rep_files=access_files_list,
|
|
919
936
|
io_ref=io_ref)
|
|
920
937
|
|
|
921
938
|
if has_preservation_files:
|
|
@@ -923,7 +940,8 @@ def complex_asset_package(preservation_files_list=None, access_files_list=None,
|
|
|
923
940
|
for content_ref, filename in preservation_refs_dict.items():
|
|
924
941
|
default_content_objects_title = os.path.splitext(os.path.basename(filename))[0]
|
|
925
942
|
preservation_content_title = kwargs.get('Preservation_Content_Title', default_content_objects_title)
|
|
926
|
-
preservation_content_description = kwargs.get('Preservation_Content_Description',
|
|
943
|
+
preservation_content_description = kwargs.get('Preservation_Content_Description',
|
|
944
|
+
default_content_objects_title)
|
|
927
945
|
|
|
928
946
|
if isinstance(preservation_content_title, dict):
|
|
929
947
|
preservation_content_title = preservation_content_title[filename]
|
|
@@ -931,7 +949,8 @@ def complex_asset_package(preservation_files_list=None, access_files_list=None,
|
|
|
931
949
|
if isinstance(preservation_content_description, dict):
|
|
932
950
|
preservation_content_description = preservation_content_description[filename]
|
|
933
951
|
|
|
934
|
-
__make_content_objects__(xip, preservation_content_title, content_ref, io_ref, security_tag,
|
|
952
|
+
__make_content_objects__(xip, preservation_content_title, content_ref, io_ref, security_tag,
|
|
953
|
+
preservation_content_description,
|
|
935
954
|
content_type)
|
|
936
955
|
|
|
937
956
|
if has_access_files:
|
|
@@ -948,7 +967,8 @@ def complex_asset_package(preservation_files_list=None, access_files_list=None,
|
|
|
948
967
|
if isinstance(access_content_description, dict):
|
|
949
968
|
access_content_title = access_content_title[filename]
|
|
950
969
|
|
|
951
|
-
__make_content_objects__(xip, access_content_title, content_ref, io_ref, security_tag,
|
|
970
|
+
__make_content_objects__(xip, access_content_title, content_ref, io_ref, security_tag,
|
|
971
|
+
access_content_description, content_type)
|
|
952
972
|
|
|
953
973
|
if has_preservation_files:
|
|
954
974
|
|
|
@@ -956,7 +976,8 @@ def complex_asset_package(preservation_files_list=None, access_files_list=None,
|
|
|
956
976
|
|
|
957
977
|
for content_ref, filename in preservation_refs_dict.items():
|
|
958
978
|
preservation_file_name = os.path.basename(filename)
|
|
959
|
-
__make_generation__(xip, preservation_file_name, content_ref, preservation_generation_label,
|
|
979
|
+
__make_generation__(xip, preservation_file_name, content_ref, preservation_generation_label,
|
|
980
|
+
PRESERVATION_CONTENT_FOLDER)
|
|
960
981
|
|
|
961
982
|
if has_access_files:
|
|
962
983
|
|
|
@@ -1071,7 +1092,8 @@ def complex_asset_package(preservation_files_list=None, access_files_list=None,
|
|
|
1071
1092
|
return top_level_folder + ".zip"
|
|
1072
1093
|
|
|
1073
1094
|
|
|
1074
|
-
def simple_asset_package(preservation_file=None, access_file=None, export_folder=None, parent_folder=None,
|
|
1095
|
+
def simple_asset_package(preservation_file=None, access_file=None, export_folder=None, parent_folder=None,
|
|
1096
|
+
compress=True, **kwargs):
|
|
1075
1097
|
"""
|
|
1076
1098
|
Create a Preservica package containing a single Asset from a single preservation file
|
|
1077
1099
|
and an optional access file.
|
|
@@ -1131,7 +1153,8 @@ def _unpad(s):
|
|
|
1131
1153
|
|
|
1132
1154
|
class UploadAPI(AuthenticatedAPI):
|
|
1133
1155
|
|
|
1134
|
-
def ingest_tweet(self, twitter_user=None, tweet_id: int = 0, twitter_consumer_key=None, twitter_secret_key=None,
|
|
1156
|
+
def ingest_tweet(self, twitter_user=None, tweet_id: int = 0, twitter_consumer_key=None, twitter_secret_key=None,
|
|
1157
|
+
folder=None,
|
|
1135
1158
|
callback=None, **kwargs):
|
|
1136
1159
|
|
|
1137
1160
|
"""
|
|
@@ -1175,7 +1198,8 @@ class UploadAPI(AuthenticatedAPI):
|
|
|
1175
1198
|
video_name_document_.close()
|
|
1176
1199
|
return video_name_, True
|
|
1177
1200
|
|
|
1178
|
-
entity_client = pyPreservica.EntityAPI(username=self.username, password=self.password, server=self.server,
|
|
1201
|
+
entity_client = pyPreservica.EntityAPI(username=self.username, password=self.password, server=self.server,
|
|
1202
|
+
tenant=self.tenant)
|
|
1179
1203
|
if hasattr(folder, "reference"):
|
|
1180
1204
|
folder = entity_client.folder(folder.reference)
|
|
1181
1205
|
else:
|
|
@@ -1313,7 +1337,8 @@ class UploadAPI(AuthenticatedAPI):
|
|
|
1313
1337
|
os.remove(ob)
|
|
1314
1338
|
os.remove("metadata.xml")
|
|
1315
1339
|
|
|
1316
|
-
def ingest_twitter_feed(self, twitter_user=None, num_tweets: int = 25, twitter_consumer_key=None,
|
|
1340
|
+
def ingest_twitter_feed(self, twitter_user=None, num_tweets: int = 25, twitter_consumer_key=None,
|
|
1341
|
+
twitter_secret_key=None, folder=None,
|
|
1317
1342
|
callback=None, **kwargs):
|
|
1318
1343
|
|
|
1319
1344
|
"""
|
|
@@ -1358,7 +1383,8 @@ class UploadAPI(AuthenticatedAPI):
|
|
|
1358
1383
|
video_name_document_.flush()
|
|
1359
1384
|
return video_name_, True
|
|
1360
1385
|
|
|
1361
|
-
entity_client = pyPreservica.EntityAPI(username=self.username, password=self.password, server=self.server,
|
|
1386
|
+
entity_client = pyPreservica.EntityAPI(username=self.username, password=self.password, server=self.server,
|
|
1387
|
+
tenant=self.tenant)
|
|
1362
1388
|
if hasattr(folder, "reference"):
|
|
1363
1389
|
folder = entity_client.folder(folder.reference)
|
|
1364
1390
|
else:
|
|
@@ -1489,7 +1515,8 @@ class UploadAPI(AuthenticatedAPI):
|
|
|
1489
1515
|
asset_title = kwargs.get("Title", text)
|
|
1490
1516
|
asset_description = kwargs.get("Description", full_text)
|
|
1491
1517
|
|
|
1492
|
-
p = complex_asset_package(preservation_files_list=content_objects, parent_folder=folder,
|
|
1518
|
+
p = complex_asset_package(preservation_files_list=content_objects, parent_folder=folder,
|
|
1519
|
+
Title=asset_title,
|
|
1493
1520
|
Description=asset_description, CustomType="Tweet", Identifiers=identifiers,
|
|
1494
1521
|
Asset_Metadata=asset_metadata, SecurityTag=security_tag)
|
|
1495
1522
|
self.upload_zip_package(p, folder=folder, callback=callback)
|
|
@@ -1573,7 +1600,8 @@ class UploadAPI(AuthenticatedAPI):
|
|
|
1573
1600
|
duration = meta.get('duration')
|
|
1574
1601
|
|
|
1575
1602
|
package = simple_asset_package(preservation_file=f"{vid_id}.mp4", parent_folder=parent_folder, Title=title,
|
|
1576
|
-
Description=description, Identifiers=identifier_map,
|
|
1603
|
+
Description=description, Identifiers=identifier_map,
|
|
1604
|
+
Asset_Metadata=descriptive_metadata,
|
|
1577
1605
|
Preservation_Content_Title=title, SecurityTag=security_tag)
|
|
1578
1606
|
|
|
1579
1607
|
self.upload_zip_package(path_to_zip_package=package, folder=parent_folder, callback=callback)
|
|
@@ -1594,7 +1622,8 @@ class UploadAPI(AuthenticatedAPI):
|
|
|
1594
1622
|
self.token = self.__token__()
|
|
1595
1623
|
return self.upload_credentials(location_id)
|
|
1596
1624
|
else:
|
|
1597
|
-
exception = HTTPException(location_id, request.status_code, request.url, "upload_credentials",
|
|
1625
|
+
exception = HTTPException(location_id, request.status_code, request.url, "upload_credentials",
|
|
1626
|
+
request.content.decode('utf-8'))
|
|
1598
1627
|
logger.error(exception)
|
|
1599
1628
|
raise exception
|
|
1600
1629
|
|
|
@@ -1613,7 +1642,8 @@ class UploadAPI(AuthenticatedAPI):
|
|
|
1613
1642
|
self.token = self.__token__()
|
|
1614
1643
|
return self.upload_locations()
|
|
1615
1644
|
else:
|
|
1616
|
-
exception = HTTPException("", request.status_code, request.url, "upload_locations",
|
|
1645
|
+
exception = HTTPException("", request.status_code, request.url, "upload_locations",
|
|
1646
|
+
request.content.decode('utf-8'))
|
|
1617
1647
|
logger.error(exception)
|
|
1618
1648
|
raise exception
|
|
1619
1649
|
|
|
@@ -1625,7 +1655,8 @@ class UploadAPI(AuthenticatedAPI):
|
|
|
1625
1655
|
"""
|
|
1626
1656
|
return self.upload_locations()
|
|
1627
1657
|
|
|
1628
|
-
def crawl_filesystem(self, filesystem_path, bucket_name, preservica_parent, callback: bool = False,
|
|
1658
|
+
def crawl_filesystem(self, filesystem_path, bucket_name, preservica_parent, callback: bool = False,
|
|
1659
|
+
security_tag: str = "open",
|
|
1629
1660
|
delete_after_upload: bool = True, max_MB_ingested: int = -1):
|
|
1630
1661
|
|
|
1631
1662
|
def get_parent(client, identifier, parent_reference):
|
|
@@ -1652,8 +1683,10 @@ class UploadAPI(AuthenticatedAPI):
|
|
|
1652
1683
|
return folder
|
|
1653
1684
|
|
|
1654
1685
|
from pyPreservica import EntityAPI
|
|
1655
|
-
entity_client = EntityAPI(username=self.username, password=self.password, server=self.server,
|
|
1656
|
-
|
|
1686
|
+
entity_client = EntityAPI(username=self.username, password=self.password, server=self.server,
|
|
1687
|
+
tenant=self.tenant,
|
|
1688
|
+
two_fa_secret_key=self.two_fa_secret_key, use_shared_secret=self.shared_secret,
|
|
1689
|
+
protocol=self.protocol)
|
|
1657
1690
|
|
|
1658
1691
|
if preservica_parent:
|
|
1659
1692
|
parent = entity_client.folder(preservica_parent)
|
|
@@ -1697,8 +1730,14 @@ class UploadAPI(AuthenticatedAPI):
|
|
|
1697
1730
|
else:
|
|
1698
1731
|
progress_display = None
|
|
1699
1732
|
|
|
1700
|
-
|
|
1701
|
-
|
|
1733
|
+
if bucket_name is None:
|
|
1734
|
+
self.upload_zip_package(path_to_zip_package=package, callback=progress_display,
|
|
1735
|
+
delete_after_upload=delete_after_upload)
|
|
1736
|
+
else:
|
|
1737
|
+
self.upload_zip_package_to_S3(path_to_zip_package=package, bucket_name=bucket_name,
|
|
1738
|
+
callback=progress_display,
|
|
1739
|
+
delete_after_upload=delete_after_upload)
|
|
1740
|
+
|
|
1702
1741
|
logger.info(f"Uploaded " + "{:.1f}".format(bytes_ingested / (1024 * 1024)) + " MB")
|
|
1703
1742
|
|
|
1704
1743
|
if max_MB_ingested > 0:
|
|
@@ -1706,7 +1745,8 @@ class UploadAPI(AuthenticatedAPI):
|
|
|
1706
1745
|
logger.info(f"Reached Max Upload Limit")
|
|
1707
1746
|
break
|
|
1708
1747
|
|
|
1709
|
-
def upload_zip_to_Source(self, path_to_zip_package, container_name, folder=None, delete_after_upload=False,
|
|
1748
|
+
def upload_zip_to_Source(self, path_to_zip_package, container_name, folder=None, delete_after_upload=False,
|
|
1749
|
+
show_progress=False):
|
|
1710
1750
|
|
|
1711
1751
|
"""
|
|
1712
1752
|
Uploads a zip file package to either an Azure container or S3 bucket
|
|
@@ -1727,13 +1767,17 @@ class UploadAPI(AuthenticatedAPI):
|
|
|
1727
1767
|
callback = None
|
|
1728
1768
|
if show_progress:
|
|
1729
1769
|
callback = UploadProgressConsoleCallback(path_to_zip_package)
|
|
1730
|
-
self.upload_zip_package_to_S3(path_to_zip_package=path_to_zip_package, bucket_name=container_name,
|
|
1770
|
+
self.upload_zip_package_to_S3(path_to_zip_package=path_to_zip_package, bucket_name=container_name,
|
|
1771
|
+
folder=folder,
|
|
1731
1772
|
callback=callback, delete_after_upload=delete_after_upload)
|
|
1732
1773
|
else:
|
|
1733
|
-
self.upload_zip_package_to_Azure(path_to_zip_package=path_to_zip_package,
|
|
1734
|
-
|
|
1774
|
+
self.upload_zip_package_to_Azure(path_to_zip_package=path_to_zip_package,
|
|
1775
|
+
container_name=container_name, folder=folder,
|
|
1776
|
+
delete_after_upload=delete_after_upload,
|
|
1777
|
+
show_progress=show_progress)
|
|
1735
1778
|
|
|
1736
|
-
def upload_zip_package_to_Azure(self, path_to_zip_package, container_name, folder=None, delete_after_upload=False,
|
|
1779
|
+
def upload_zip_package_to_Azure(self, path_to_zip_package, container_name, folder=None, delete_after_upload=False,
|
|
1780
|
+
show_progress=False):
|
|
1737
1781
|
|
|
1738
1782
|
"""
|
|
1739
1783
|
Uploads a zip file package to an Azure container connected to a Preservica Cloud System
|
|
@@ -1746,7 +1790,8 @@ class UploadAPI(AuthenticatedAPI):
|
|
|
1746
1790
|
"""
|
|
1747
1791
|
|
|
1748
1792
|
if (self.major_version < 7) and (self.minor_version < 5):
|
|
1749
|
-
raise RuntimeError(
|
|
1793
|
+
raise RuntimeError(
|
|
1794
|
+
"This call [upload_zip_package_to_Azure] is only available against v6.5 systems and above")
|
|
1750
1795
|
|
|
1751
1796
|
from azure.storage.blob import ContainerClient
|
|
1752
1797
|
|
|
@@ -1774,11 +1819,13 @@ class UploadAPI(AuthenticatedAPI):
|
|
|
1774
1819
|
|
|
1775
1820
|
if show_progress:
|
|
1776
1821
|
with tqdm.wrapattr(open(path_to_zip_package, 'rb'), "read", total=len_bytes) as data:
|
|
1777
|
-
blob_client = container.upload_blob(name=upload_key, data=data, metadata=metadata,
|
|
1822
|
+
blob_client = container.upload_blob(name=upload_key, data=data, metadata=metadata,
|
|
1823
|
+
length=len_bytes)
|
|
1778
1824
|
properties = blob_client.get_blob_properties()
|
|
1779
1825
|
else:
|
|
1780
1826
|
with open(path_to_zip_package, "rb") as data:
|
|
1781
|
-
blob_client = container.upload_blob(name=upload_key, data=data, metadata=metadata,
|
|
1827
|
+
blob_client = container.upload_blob(name=upload_key, data=data, metadata=metadata,
|
|
1828
|
+
length=len_bytes)
|
|
1782
1829
|
properties = blob_client.get_blob_properties()
|
|
1783
1830
|
|
|
1784
1831
|
if delete_after_upload:
|
|
@@ -1786,7 +1833,8 @@ class UploadAPI(AuthenticatedAPI):
|
|
|
1786
1833
|
|
|
1787
1834
|
return properties
|
|
1788
1835
|
|
|
1789
|
-
def upload_zip_package_to_S3(self, path_to_zip_package, bucket_name, folder=None, callback=None,
|
|
1836
|
+
def upload_zip_package_to_S3(self, path_to_zip_package, bucket_name, folder=None, callback=None,
|
|
1837
|
+
delete_after_upload=False):
|
|
1790
1838
|
|
|
1791
1839
|
"""
|
|
1792
1840
|
Uploads a zip file package to an S3 bucket connected to a Preservica Cloud System
|
|
@@ -1815,7 +1863,8 @@ class UploadAPI(AuthenticatedAPI):
|
|
|
1815
1863
|
session_token = credentials['sessionToken']
|
|
1816
1864
|
endpoint = credentials['endpoint']
|
|
1817
1865
|
|
|
1818
|
-
session = boto3.Session(aws_access_key_id=access_key, aws_secret_access_key=secret_key,
|
|
1866
|
+
session = boto3.Session(aws_access_key_id=access_key, aws_secret_access_key=secret_key,
|
|
1867
|
+
aws_session_token=session_token)
|
|
1819
1868
|
s3 = session.resource(service_name="s3")
|
|
1820
1869
|
|
|
1821
1870
|
logger.debug(f"S3 Session: {s3}")
|
|
@@ -1834,7 +1883,8 @@ class UploadAPI(AuthenticatedAPI):
|
|
|
1834
1883
|
|
|
1835
1884
|
metadata_map = {'Metadata': metadata}
|
|
1836
1885
|
|
|
1837
|
-
s3_object.upload_file(path_to_zip_package, Callback=callback, ExtraArgs=metadata_map,
|
|
1886
|
+
s3_object.upload_file(path_to_zip_package, Callback=callback, ExtraArgs=metadata_map,
|
|
1887
|
+
Config=transfer_config)
|
|
1838
1888
|
|
|
1839
1889
|
if delete_after_upload:
|
|
1840
1890
|
os.remove(path_to_zip_package)
|
|
@@ -1860,7 +1910,8 @@ class UploadAPI(AuthenticatedAPI):
|
|
|
1860
1910
|
endpoint = f'{self.protocol}://{self.server}/api/s3/buckets'
|
|
1861
1911
|
self.token = self.__token__()
|
|
1862
1912
|
|
|
1863
|
-
s3_client = boto3.client('s3', endpoint_url=endpoint, aws_access_key_id=self.token,
|
|
1913
|
+
s3_client = boto3.client('s3', endpoint_url=endpoint, aws_access_key_id=self.token,
|
|
1914
|
+
aws_secret_access_key="NOT_USED",
|
|
1864
1915
|
config=Config(s3={'addressing_style': 'path'}))
|
|
1865
1916
|
|
|
1866
1917
|
metadata = {}
|
|
@@ -1880,7 +1931,8 @@ class UploadAPI(AuthenticatedAPI):
|
|
|
1880
1931
|
transfer.CompleteMultipartUploadTask = CompleteMultipartUploadTask
|
|
1881
1932
|
transfer.upload_file = upload_file
|
|
1882
1933
|
|
|
1883
|
-
response = transfer.upload_file(self=transfer, filename=path_to_zip_package, bucket=bucket, key=key_id,
|
|
1934
|
+
response = transfer.upload_file(self=transfer, filename=path_to_zip_package, bucket=bucket, key=key_id,
|
|
1935
|
+
extra_args=metadata,
|
|
1884
1936
|
callback=callback)
|
|
1885
1937
|
|
|
1886
1938
|
if delete_after_upload:
|
|
@@ -11,6 +11,7 @@ licence: Apache License 2.0
|
|
|
11
11
|
|
|
12
12
|
import uuid
|
|
13
13
|
import datetime
|
|
14
|
+
from typing import Callable
|
|
14
15
|
from xml.etree import ElementTree
|
|
15
16
|
|
|
16
17
|
from pyPreservica.common import *
|
|
@@ -21,7 +22,7 @@ logger = logging.getLogger(__name__)
|
|
|
21
22
|
class WorkflowInstance:
|
|
22
23
|
"""
|
|
23
24
|
Defines a workflow Instance.
|
|
24
|
-
The workflow Instance is context which has been executed
|
|
25
|
+
The workflow Instance is a context which has been executed
|
|
25
26
|
"""
|
|
26
27
|
|
|
27
28
|
def __init__(self, instance_id: int):
|
|
@@ -79,8 +80,11 @@ class WorkflowAPI(AuthenticatedAPI):
|
|
|
79
80
|
workflow_types = ['Ingest', 'Access', 'Transformation', 'DataManagement']
|
|
80
81
|
|
|
81
82
|
def __init__(self, username: str = None, password: str = None, tenant: str = None, server: str = None,
|
|
82
|
-
use_shared_secret: bool = False, two_fa_secret_key: str = None,
|
|
83
|
-
|
|
83
|
+
use_shared_secret: bool = False, two_fa_secret_key: str = None,
|
|
84
|
+
protocol: str = "https", request_hook: Callable = None):
|
|
85
|
+
|
|
86
|
+
super().__init__(username, password, tenant, server, use_shared_secret, two_fa_secret_key,
|
|
87
|
+
protocol, request_hook)
|
|
84
88
|
self.base_url = "sdb/rest/workflow"
|
|
85
89
|
|
|
86
90
|
def get_workflow_contexts_by_type(self, workflow_type: str):
|
|
@@ -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.4",
|
|
25
25
|
description="Python library for the Preservica API",
|
|
26
26
|
long_description=README,
|
|
27
27
|
long_description_content_type="text/markdown",
|
|
@@ -11,7 +11,7 @@ def test_get_workflow_contexts():
|
|
|
11
11
|
def test_get_workflow_contexts2():
|
|
12
12
|
workflow = WorkflowAPI()
|
|
13
13
|
workflows = workflow.get_workflow_contexts("com.preservica.core.workflow.ingest")
|
|
14
|
-
assert len(workflows) ==
|
|
14
|
+
assert len(workflows) == 1
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
def test_get_workflow_contexts3():
|
|
@@ -24,7 +24,7 @@ def test_get_workflow_contexts_type():
|
|
|
24
24
|
workflow = WorkflowAPI()
|
|
25
25
|
|
|
26
26
|
workflows = workflow.get_workflow_contexts_by_type("Ingest")
|
|
27
|
-
assert len(workflows) ==
|
|
27
|
+
assert len(workflows) == 6
|
|
28
28
|
|
|
29
29
|
workflows = workflow.get_workflow_contexts_by_type("Access")
|
|
30
30
|
assert len(workflows) == 5
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|