pyPreservica 3.2.2__py3-none-any.whl → 3.2.3__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.
Potentially problematic release.
This version of pyPreservica might be problematic. Click here for more details.
- pyPreservica/__init__.py +1 -1
- pyPreservica/adminAPI.py +19 -13
- pyPreservica/authorityAPI.py +1 -1
- pyPreservica/common.py +10 -5
- pyPreservica/entityAPI.py +85 -29
- pyPreservica/mdformsAPI.py +20 -0
- pyPreservica/webHooksAPI.py +1 -0
- {pypreservica-3.2.2.dist-info → pypreservica-3.2.3.dist-info}/METADATA +1 -1
- pypreservica-3.2.3.dist-info/RECORD +20 -0
- pypreservica-3.2.2.dist-info/RECORD +0 -20
- {pypreservica-3.2.2.dist-info → pypreservica-3.2.3.dist-info}/WHEEL +0 -0
- {pypreservica-3.2.2.dist-info → pypreservica-3.2.3.dist-info}/licenses/LICENSE.txt +0 -0
- {pypreservica-3.2.2.dist-info → pypreservica-3.2.3.dist-info}/top_level.txt +0 -0
pyPreservica/__init__.py
CHANGED
pyPreservica/adminAPI.py
CHANGED
|
@@ -10,7 +10,7 @@ licence: Apache License 2.0
|
|
|
10
10
|
"""
|
|
11
11
|
import csv
|
|
12
12
|
import xml.etree.ElementTree
|
|
13
|
-
from typing import List, Any
|
|
13
|
+
from typing import List, Any, Union
|
|
14
14
|
|
|
15
15
|
from pyPreservica.common import *
|
|
16
16
|
|
|
@@ -36,7 +36,7 @@ class AdminAPI(AuthenticatedAPI):
|
|
|
36
36
|
request = self.session.delete(f'{self.protocol}://{self.server}/api/admin/security/roles/{role_name}',
|
|
37
37
|
headers=headers)
|
|
38
38
|
if request.status_code == requests.codes.no_content:
|
|
39
|
-
return
|
|
39
|
+
return None
|
|
40
40
|
elif request.status_code == requests.codes.unauthorized:
|
|
41
41
|
self.token = self.__token__()
|
|
42
42
|
return self.delete_system_role(role_name)
|
|
@@ -61,7 +61,7 @@ class AdminAPI(AuthenticatedAPI):
|
|
|
61
61
|
request = self.session.delete(f'{self.protocol}://{self.server}/api/admin/security/tags/{tag_name}',
|
|
62
62
|
headers=headers)
|
|
63
63
|
if request.status_code == requests.codes.no_content:
|
|
64
|
-
return
|
|
64
|
+
return None
|
|
65
65
|
elif request.status_code == requests.codes.unauthorized:
|
|
66
66
|
self.token = self.__token__()
|
|
67
67
|
return self.delete_security_tag(tag_name)
|
|
@@ -211,7 +211,7 @@ class AdminAPI(AuthenticatedAPI):
|
|
|
211
211
|
headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/xml;charset=UTF-8'}
|
|
212
212
|
request = self.session.delete(f'{self.protocol}://{self.server}/api/admin/users/{username}', headers=headers)
|
|
213
213
|
if request.status_code == requests.codes.no_content:
|
|
214
|
-
return
|
|
214
|
+
return None
|
|
215
215
|
elif request.status_code == requests.codes.unauthorized:
|
|
216
216
|
self.token = self.__token__()
|
|
217
217
|
return self.delete_user(username)
|
|
@@ -463,7 +463,7 @@ class AdminAPI(AuthenticatedAPI):
|
|
|
463
463
|
params=params,
|
|
464
464
|
data=xml_data)
|
|
465
465
|
if request.status_code == requests.codes.created:
|
|
466
|
-
return
|
|
466
|
+
return None
|
|
467
467
|
elif request.status_code == requests.codes.unauthorized:
|
|
468
468
|
self.token = self.__token__()
|
|
469
469
|
return self.add_xml_schema(name, description, originalName, xml_data)
|
|
@@ -513,7 +513,7 @@ class AdminAPI(AuthenticatedAPI):
|
|
|
513
513
|
params=params,
|
|
514
514
|
data=xml_data)
|
|
515
515
|
if request.status_code == requests.codes.created:
|
|
516
|
-
return
|
|
516
|
+
return None
|
|
517
517
|
elif request.status_code == requests.codes.unauthorized:
|
|
518
518
|
self.token = self.__token__()
|
|
519
519
|
return self.add_xml_document(name, xml_data, document_type)
|
|
@@ -543,13 +543,14 @@ class AdminAPI(AuthenticatedAPI):
|
|
|
543
543
|
f"{self.protocol}://{self.server}/api/admin/documents/{document['ApiId']}",
|
|
544
544
|
headers=headers)
|
|
545
545
|
if request.status_code == requests.codes.no_content:
|
|
546
|
-
return
|
|
546
|
+
return None
|
|
547
547
|
elif request.status_code == requests.codes.unauthorized:
|
|
548
548
|
self.token = self.__token__()
|
|
549
549
|
return self.delete_xml_document(uri)
|
|
550
550
|
else:
|
|
551
551
|
logger.error(request.content.decode('utf-8'))
|
|
552
552
|
raise RuntimeError(request.status_code, "delete_xml_document failed")
|
|
553
|
+
return None
|
|
553
554
|
|
|
554
555
|
def delete_xml_schema(self, uri: str):
|
|
555
556
|
"""
|
|
@@ -572,15 +573,16 @@ class AdminAPI(AuthenticatedAPI):
|
|
|
572
573
|
request = self.session.delete(f"{self.protocol}://{self.server}/api/admin/schemas/{schema['ApiId']}",
|
|
573
574
|
headers=headers)
|
|
574
575
|
if request.status_code == requests.codes.no_content:
|
|
575
|
-
return
|
|
576
|
+
return None
|
|
576
577
|
elif request.status_code == requests.codes.unauthorized:
|
|
577
578
|
self.token = self.__token__()
|
|
578
579
|
return self.delete_xml_schema(uri)
|
|
579
580
|
else:
|
|
580
581
|
logger.error(request.content.decode('utf-8'))
|
|
581
582
|
raise RuntimeError(request.status_code, "delete_xml_schema failed")
|
|
583
|
+
return None
|
|
582
584
|
|
|
583
|
-
def xml_schema(self, uri: str) -> str:
|
|
585
|
+
def xml_schema(self, uri: str) -> Union[str, None]:
|
|
584
586
|
"""
|
|
585
587
|
Fetch the metadata schema XSD document as a string by its URI
|
|
586
588
|
|
|
@@ -607,8 +609,9 @@ class AdminAPI(AuthenticatedAPI):
|
|
|
607
609
|
else:
|
|
608
610
|
logger.error(request.content.decode('utf-8'))
|
|
609
611
|
raise RuntimeError(request.status_code, "xml_schema failed")
|
|
612
|
+
return None
|
|
610
613
|
|
|
611
|
-
def xml_document(self, uri: str) -> str:
|
|
614
|
+
def xml_document(self, uri: str) -> Union[str, None]:
|
|
612
615
|
"""
|
|
613
616
|
fetch the metadata XML document as a string by its URI
|
|
614
617
|
|
|
@@ -634,6 +637,7 @@ class AdminAPI(AuthenticatedAPI):
|
|
|
634
637
|
else:
|
|
635
638
|
logger.error(request.content.decode('utf-8'))
|
|
636
639
|
raise RuntimeError(request.status_code, "xml_document failed")
|
|
640
|
+
return None
|
|
637
641
|
|
|
638
642
|
def xml_documents(self) -> List:
|
|
639
643
|
"""
|
|
@@ -754,7 +758,7 @@ class AdminAPI(AuthenticatedAPI):
|
|
|
754
758
|
logger.error(request.content.decode('utf-8'))
|
|
755
759
|
raise RuntimeError(request.status_code, "xml_transforms failed")
|
|
756
760
|
|
|
757
|
-
def xml_transform(self, input_uri: str, output_uri: str) -> str:
|
|
761
|
+
def xml_transform(self, input_uri: str, output_uri: str) -> Union[str, None]:
|
|
758
762
|
"""
|
|
759
763
|
fetch the XML transform as a string by its URIs
|
|
760
764
|
|
|
@@ -782,6 +786,7 @@ class AdminAPI(AuthenticatedAPI):
|
|
|
782
786
|
else:
|
|
783
787
|
logger.error(request.content.decode('utf-8'))
|
|
784
788
|
raise RuntimeError(request.status_code, "xml_transform failed")
|
|
789
|
+
return None
|
|
785
790
|
|
|
786
791
|
def delete_xml_transform(self, input_uri: str, output_uri: str):
|
|
787
792
|
"""
|
|
@@ -808,13 +813,14 @@ class AdminAPI(AuthenticatedAPI):
|
|
|
808
813
|
f"{self.protocol}://{self.server}/api/admin/transforms/{transform['ApiId']}",
|
|
809
814
|
headers=headers)
|
|
810
815
|
if request.status_code == requests.codes.no_content:
|
|
811
|
-
return
|
|
816
|
+
return None
|
|
812
817
|
elif request.status_code == requests.codes.unauthorized:
|
|
813
818
|
self.token = self.__token__()
|
|
814
819
|
return self.delete_xml_transform(input_uri, output_uri)
|
|
815
820
|
else:
|
|
816
821
|
logger.error(request.content.decode('utf-8'))
|
|
817
822
|
raise RuntimeError(request.status_code, "delete_xml_transform failed")
|
|
823
|
+
return None
|
|
818
824
|
|
|
819
825
|
def add_xml_transform(self, name: str, input_uri: str, output_uri: str, purpose: str, originalName: str,
|
|
820
826
|
xml_data: Any):
|
|
@@ -860,7 +866,7 @@ class AdminAPI(AuthenticatedAPI):
|
|
|
860
866
|
params=params,
|
|
861
867
|
data=xml_data)
|
|
862
868
|
if request.status_code == requests.codes.created:
|
|
863
|
-
return
|
|
869
|
+
return None
|
|
864
870
|
|
|
865
871
|
if request.status_code == requests.codes.unauthorized:
|
|
866
872
|
self.token = self.__token__()
|
pyPreservica/authorityAPI.py
CHANGED
|
@@ -54,7 +54,7 @@ class AuthorityAPI(AuthenticatedAPI):
|
|
|
54
54
|
self.token = self.__token__()
|
|
55
55
|
return self.delete_record(reference)
|
|
56
56
|
if response.status_code == requests.codes.no_content:
|
|
57
|
-
return
|
|
57
|
+
return None
|
|
58
58
|
else:
|
|
59
59
|
exception = HTTPException("", response.status_code, response.url, "delete_record",
|
|
60
60
|
response.content.decode('utf-8'))
|
pyPreservica/common.py
CHANGED
|
@@ -673,19 +673,24 @@ class AuthenticatedAPI:
|
|
|
673
673
|
logger.error(f"The AdminAPI requires the user to have ROLE_SDB_MANAGER_USER")
|
|
674
674
|
raise RuntimeError(f"The API requires the user to have at least the ROLE_SDB_MANAGER_USER")
|
|
675
675
|
|
|
676
|
-
def _find_user_roles_(self) -> list:
|
|
676
|
+
def _find_user_roles_(self) -> list[str]:
|
|
677
677
|
"""
|
|
678
678
|
Get a list of roles for the user
|
|
679
679
|
:return list of roles:
|
|
680
680
|
"""
|
|
681
|
-
headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/
|
|
681
|
+
headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/json'}
|
|
682
682
|
request = self.session.get(f"{self.protocol}://{self.server}/api/user/details", headers=headers)
|
|
683
|
+
logger.debug(request.headers)
|
|
683
684
|
if request.status_code == requests.codes.ok:
|
|
684
|
-
|
|
685
|
+
json_document = str(request.content.decode('utf-8'))
|
|
686
|
+
logger.debug(json_document)
|
|
687
|
+
roles: list[str] = json.loads(json_document)['roles']
|
|
685
688
|
return roles
|
|
686
689
|
elif request.status_code == requests.codes.unauthorized:
|
|
687
690
|
self.token = self.__token__()
|
|
688
691
|
return self._find_user_roles_()
|
|
692
|
+
return []
|
|
693
|
+
|
|
689
694
|
|
|
690
695
|
def security_tags_base(self, with_permissions: bool = False) -> dict:
|
|
691
696
|
"""
|
|
@@ -847,7 +852,7 @@ class AuthenticatedAPI:
|
|
|
847
852
|
with open('credentials.properties', 'wt', encoding="utf-8") as configfile:
|
|
848
853
|
config.write(configfile)
|
|
849
854
|
|
|
850
|
-
def manager_token(self, username: str, password: str):
|
|
855
|
+
def manager_token(self, username: str, password: str) -> str:
|
|
851
856
|
data = {'username': username, 'password': password, 'tenant': self.tenant}
|
|
852
857
|
response = self.session.post(f'{self.protocol}://{self.server}/api/accesstoken/login', data=data)
|
|
853
858
|
if response.status_code == requests.codes.ok:
|
|
@@ -859,7 +864,7 @@ class AuthenticatedAPI:
|
|
|
859
864
|
logger.error(str(response.content))
|
|
860
865
|
RuntimeError(response.status_code, "Could not generate valid manager approval token")
|
|
861
866
|
|
|
862
|
-
def __token__(self):
|
|
867
|
+
def __token__(self) -> str:
|
|
863
868
|
"""
|
|
864
869
|
Generate am API token to use to authenticate calls
|
|
865
870
|
:return: API Token
|
pyPreservica/entityAPI.py
CHANGED
|
@@ -82,28 +82,28 @@ class EntityAPI(AuthenticatedAPI):
|
|
|
82
82
|
|
|
83
83
|
def bitstream_bytes(self, bitstream: Bitstream, chunk_size: int = CHUNK_SIZE) -> Union[BytesIO, None]:
|
|
84
84
|
"""
|
|
85
|
-
|
|
85
|
+
Download a file represented as a Bitstream to a byteIO array
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
Returns the byteIO
|
|
88
|
+
Returns None if the file does not contain the correct number of bytes (default 2k)
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
:param chunk_size: The buffer copy chunk size in bytes default
|
|
91
|
+
:param bitstream: A Bitstream object
|
|
92
|
+
:type bitstream: Bitstream
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
:return: The file in bytes
|
|
95
|
+
:rtype: byteIO
|
|
96
96
|
"""
|
|
97
97
|
if not isinstance(bitstream, Bitstream):
|
|
98
98
|
logger.error("bitstream_content argument is not a Bitstream object")
|
|
99
99
|
raise RuntimeError("bitstream_bytes argument is not a Bitstream object")
|
|
100
|
-
with self.session.get(bitstream.content_url, headers={HEADER_TOKEN: self.token}, stream=True) as
|
|
101
|
-
if
|
|
100
|
+
with self.session.get(bitstream.content_url, headers={HEADER_TOKEN: self.token}, stream=True) as response:
|
|
101
|
+
if response.status_code == requests.codes.unauthorized:
|
|
102
102
|
self.token = self.__token__()
|
|
103
103
|
return self.bitstream_bytes(bitstream)
|
|
104
|
-
elif
|
|
104
|
+
elif response.status_code == requests.codes.ok:
|
|
105
105
|
file_bytes = BytesIO()
|
|
106
|
-
for chunk in
|
|
106
|
+
for chunk in response.iter_content(chunk_size=chunk_size):
|
|
107
107
|
file_bytes.write(chunk)
|
|
108
108
|
file_bytes.seek(0)
|
|
109
109
|
if file_bytes.getbuffer().nbytes == bitstream.length:
|
|
@@ -113,8 +113,8 @@ class EntityAPI(AuthenticatedAPI):
|
|
|
113
113
|
logger.error("Downloaded file size did not match the Preservica held value")
|
|
114
114
|
return None
|
|
115
115
|
else:
|
|
116
|
-
exception = HTTPException(bitstream.filename,
|
|
117
|
-
|
|
116
|
+
exception = HTTPException(bitstream.filename, response.status_code, response.url, "bitstream_content",
|
|
117
|
+
response.content.decode('utf-8'))
|
|
118
118
|
logger.error(exception)
|
|
119
119
|
raise exception
|
|
120
120
|
|
|
@@ -131,23 +131,25 @@ class EntityAPI(AuthenticatedAPI):
|
|
|
131
131
|
url: str = f'{self.protocol}://{self.server}/api/entity/content-objects/{bitstream.co_ref}/generations/{bitstream.gen_index}/bitstreams/{bitstream.bs_index}/storage-locations'
|
|
132
132
|
|
|
133
133
|
with self.session.get(url, headers={HEADER_TOKEN: self.token}, stream=True) as request:
|
|
134
|
-
if request.status_code == requests.codes.
|
|
135
|
-
self.token = self.__token__()
|
|
136
|
-
return self.bitstream_location(bitstream)
|
|
137
|
-
elif request.status_code == requests.codes.ok:
|
|
134
|
+
if request.status_code == requests.codes.ok:
|
|
138
135
|
xml_response = str(request.content.decode('utf-8'))
|
|
139
136
|
entity_response = xml.etree.ElementTree.fromstring(xml_response)
|
|
140
137
|
logger.debug(xml_response)
|
|
141
138
|
locations = entity_response.find(f'.//{{{self.entity_ns}}}StorageLocation')
|
|
142
139
|
for adapter in locations:
|
|
143
140
|
storage_locations.append(adapter.attrib['name'])
|
|
141
|
+
return storage_locations
|
|
142
|
+
|
|
143
|
+
if request.status_code == requests.codes.unauthorized:
|
|
144
|
+
self.token = self.__token__()
|
|
145
|
+
return self.bitstream_location(bitstream)
|
|
144
146
|
else:
|
|
145
147
|
exception = HTTPException(bitstream.filename, request.status_code, request.url, "bitstream_location",
|
|
146
148
|
request.content.decode('utf-8'))
|
|
147
149
|
logger.error(exception)
|
|
148
150
|
raise exception
|
|
149
151
|
|
|
150
|
-
|
|
152
|
+
|
|
151
153
|
|
|
152
154
|
def bitstream_content(self, bitstream: Bitstream, filename: str, chunk_size: int = CHUNK_SIZE) -> Union[int, None]:
|
|
153
155
|
"""
|
|
@@ -760,7 +762,7 @@ class EntityAPI(AuthenticatedAPI):
|
|
|
760
762
|
end_point = f"{entity.path}/{entity.reference}/links/{relationship.api_id}"
|
|
761
763
|
request = self.session.delete(f'{self.protocol}://{self.server}/api/entity/{end_point}', headers=headers)
|
|
762
764
|
if request.status_code == requests.codes.no_content:
|
|
763
|
-
|
|
765
|
+
return None
|
|
764
766
|
elif request.status_code == requests.codes.unauthorized:
|
|
765
767
|
self.token = self.__token__()
|
|
766
768
|
return self.__delete_relationship(relationship)
|
|
@@ -779,7 +781,7 @@ class EntityAPI(AuthenticatedAPI):
|
|
|
779
781
|
:type: page_size: int
|
|
780
782
|
|
|
781
783
|
:param entity: The Source Entity
|
|
782
|
-
:type: entity: Entity
|
|
784
|
+
:type: entity: An Entity type such as Asset, Folder etc
|
|
783
785
|
|
|
784
786
|
:return: Generator
|
|
785
787
|
:rtype: Relationship
|
|
@@ -847,7 +849,7 @@ class EntityAPI(AuthenticatedAPI):
|
|
|
847
849
|
|
|
848
850
|
return PagedSet(results, has_more, int(total_hits.text), url)
|
|
849
851
|
elif request.status_code == requests.codes.unauthorized:
|
|
850
|
-
self.__relationships__(entity=entity, maximum=maximum, next_page=next_page)
|
|
852
|
+
return self.__relationships__(entity=entity, maximum=maximum, next_page=next_page)
|
|
851
853
|
else:
|
|
852
854
|
exception = HTTPException(entity.reference, request.status_code, request.url, "relationships",
|
|
853
855
|
request.content.decode('utf-8'))
|
|
@@ -1108,6 +1110,7 @@ class EntityAPI(AuthenticatedAPI):
|
|
|
1108
1110
|
if 'CustomType' in response:
|
|
1109
1111
|
content_object.custom_type = response['CustomType']
|
|
1110
1112
|
return content_object
|
|
1113
|
+
return None
|
|
1111
1114
|
elif request.status_code == requests.codes.unauthorized:
|
|
1112
1115
|
self.token = self.__token__()
|
|
1113
1116
|
return self.save(entity)
|
|
@@ -1296,9 +1299,9 @@ class EntityAPI(AuthenticatedAPI):
|
|
|
1296
1299
|
for uri, schema_name in entity.metadata.items():
|
|
1297
1300
|
if schema == schema_name:
|
|
1298
1301
|
return self.metadata(uri)
|
|
1299
|
-
return
|
|
1302
|
+
return None
|
|
1300
1303
|
|
|
1301
|
-
def metadata_tag_for_entity(self, entity: Entity, schema: str, tag: str, isXpath: bool = False) -> str:
|
|
1304
|
+
def metadata_tag_for_entity(self, entity: Entity, schema: str, tag: str, isXpath: bool = False) -> Union[str, None]:
|
|
1302
1305
|
"""
|
|
1303
1306
|
Retrieve the first value of the tag from a metadata template given by schema
|
|
1304
1307
|
|
|
@@ -1313,10 +1316,11 @@ class EntityAPI(AuthenticatedAPI):
|
|
|
1313
1316
|
xml_doc = self.metadata_for_entity(entity, schema)
|
|
1314
1317
|
if xml_doc:
|
|
1315
1318
|
xml_object = xml.etree.ElementTree.fromstring(xml_doc)
|
|
1316
|
-
if isXpath
|
|
1319
|
+
if not isXpath:
|
|
1317
1320
|
return xml_object.find(f'.//{{*}}{tag}').text
|
|
1318
1321
|
else:
|
|
1319
1322
|
return xml_object.find(tag).text
|
|
1323
|
+
return None
|
|
1320
1324
|
|
|
1321
1325
|
def security_tag_sync(self, entity: EntityT, new_tag: str) -> EntityT:
|
|
1322
1326
|
"""
|
|
@@ -1413,6 +1417,7 @@ class EntityAPI(AuthenticatedAPI):
|
|
|
1413
1417
|
return self.folder(reference)
|
|
1414
1418
|
if entity_type is EntityType.ASSET:
|
|
1415
1419
|
return self.asset(reference)
|
|
1420
|
+
return None
|
|
1416
1421
|
|
|
1417
1422
|
def add_physical_asset(self, title: str, description: str, parent: Folder, security_tag: str = "open") -> Asset:
|
|
1418
1423
|
"""
|
|
@@ -1460,11 +1465,62 @@ class EntityAPI(AuthenticatedAPI):
|
|
|
1460
1465
|
logger.error(exception)
|
|
1461
1466
|
raise exception
|
|
1462
1467
|
|
|
1463
|
-
def
|
|
1468
|
+
def merge_assets(self, assets: list[Asset], title: str, description: str) -> str:
|
|
1469
|
+
"""
|
|
1470
|
+
Create a new Asset with the content from each Asset in supplied list
|
|
1471
|
+
This call will create a new multipart Asset which contains all the content from list of Assets.
|
|
1472
|
+
|
|
1473
|
+
The return value is the progress status of the merge operation.
|
|
1474
|
+
"""
|
|
1475
|
+
|
|
1476
|
+
headers = {
|
|
1477
|
+
HEADER_TOKEN: self.token,
|
|
1478
|
+
"Content-Type": "application/xml;charset=UTF-8",
|
|
1479
|
+
"accept": "text/plain;charset=UTF-8",
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
merge_object = xml.etree.ElementTree.Element("MergeAction", {"xmlns": self.entity_ns, "xmlns:xip": self.xip_ns})
|
|
1483
|
+
xml.etree.ElementTree.SubElement(merge_object, "Title").text = str(title)
|
|
1484
|
+
xml.etree.ElementTree.SubElement(merge_object, "Description").text = str(description)
|
|
1485
|
+
for a in assets:
|
|
1486
|
+
xml.etree.ElementTree.SubElement(merge_object, "Entity", {
|
|
1487
|
+
"excludeIdentifiers": "true",
|
|
1488
|
+
"excludeLinks": "true",
|
|
1489
|
+
"excludeMetadata": "true",
|
|
1490
|
+
"ref": a.reference,
|
|
1491
|
+
"type": EntityType.ASSET.value}
|
|
1492
|
+
)
|
|
1493
|
+
# order_object = xml.etree.ElementTree.SubElement(merge_object, "Order")
|
|
1494
|
+
# for a in assets:
|
|
1495
|
+
# xml.etree.ElementTree.SubElement(order_object, "Entity", {
|
|
1496
|
+
# "ref": a.reference,
|
|
1497
|
+
# "type": EntityType.CONTENT_OBJECT.value}
|
|
1498
|
+
# )
|
|
1499
|
+
xml_request = xml.etree.ElementTree.tostring(merge_object, encoding="utf-8")
|
|
1500
|
+
print(xml_request)
|
|
1501
|
+
request = self.session.post(
|
|
1502
|
+
f"{self.protocol}://{self.server}/api/entity/actions/merges", data=xml_request, headers=headers)
|
|
1503
|
+
if request.status_code == requests.codes.accepted:
|
|
1504
|
+
return request.content.decode('utf-8')
|
|
1505
|
+
elif request.status_code == requests.codes.unauthorized:
|
|
1506
|
+
self.token = self.__token__()
|
|
1507
|
+
return self.merge_assets(assets, title, description)
|
|
1508
|
+
else:
|
|
1509
|
+
exception = HTTPException(
|
|
1510
|
+
"",
|
|
1511
|
+
request.status_code,
|
|
1512
|
+
request.url,
|
|
1513
|
+
"merge_assets",
|
|
1514
|
+
request.content.decode("utf-8"),
|
|
1515
|
+
)
|
|
1516
|
+
logger.error(exception)
|
|
1517
|
+
raise exception
|
|
1518
|
+
|
|
1519
|
+
def merge_folder(self, folder: Folder) -> str:
|
|
1464
1520
|
"""
|
|
1465
1521
|
Create a new Asset with the content from each Asset in the Folder
|
|
1466
1522
|
|
|
1467
|
-
This call will create a new
|
|
1523
|
+
This call will create a new multipart Asset which contains all the content from the Folder.
|
|
1468
1524
|
|
|
1469
1525
|
The new Asset which is created will have the same title, description and parent as the Folder.
|
|
1470
1526
|
|
|
@@ -1495,7 +1551,6 @@ class EntityAPI(AuthenticatedAPI):
|
|
|
1495
1551
|
logger.error(exception)
|
|
1496
1552
|
raise exception
|
|
1497
1553
|
|
|
1498
|
-
|
|
1499
1554
|
def asset(self, reference: str) -> Asset:
|
|
1500
1555
|
"""
|
|
1501
1556
|
Retrieve an Asset by its reference
|
|
@@ -2118,7 +2173,7 @@ class EntityAPI(AuthenticatedAPI):
|
|
|
2118
2173
|
params=params, headers=headers)
|
|
2119
2174
|
|
|
2120
2175
|
if request.status_code == requests.codes.ok:
|
|
2121
|
-
|
|
2176
|
+
return None
|
|
2122
2177
|
elif request.status_code == requests.codes.unauthorized:
|
|
2123
2178
|
self.token = self.__token__()
|
|
2124
2179
|
return self._event_actions(entity, maximum=maximum)
|
|
@@ -2262,6 +2317,7 @@ class EntityAPI(AuthenticatedAPI):
|
|
|
2262
2317
|
else:
|
|
2263
2318
|
url = next_url.text
|
|
2264
2319
|
return PagedSet(result_list, has_more, int(total_hits.text), url)
|
|
2320
|
+
return None
|
|
2265
2321
|
|
|
2266
2322
|
def entity_from_event(self, event_id: str) -> Generator:
|
|
2267
2323
|
self.token = self.__token__()
|
pyPreservica/mdformsAPI.py
CHANGED
|
@@ -451,6 +451,26 @@ class MetadataGroupsAPI(AuthenticatedAPI):
|
|
|
451
451
|
raise exception
|
|
452
452
|
|
|
453
453
|
|
|
454
|
+
def delete_form(self, form_id: str):
|
|
455
|
+
"""
|
|
456
|
+
Delete a form by its ID
|
|
457
|
+
"""
|
|
458
|
+
headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/json;charset=UTF-8'}
|
|
459
|
+
url = f'{self.protocol}://{self.server}/api/metadata/forms/{form_id}'
|
|
460
|
+
with self.session.delete(url, headers=headers) as request:
|
|
461
|
+
if request.status_code == requests.codes.unauthorized:
|
|
462
|
+
self.token = self.__token__()
|
|
463
|
+
return self.delete_form(form_id)
|
|
464
|
+
elif request.status_code == requests.codes.no_content:
|
|
465
|
+
return None
|
|
466
|
+
else:
|
|
467
|
+
exception = HTTPException(None, request.status_code, request.url, "delete_form",
|
|
468
|
+
request.content.decode('utf-8'))
|
|
469
|
+
logger.error(exception)
|
|
470
|
+
raise exception
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
|
|
454
474
|
def form(self, form_id: str) -> dict:
|
|
455
475
|
"""
|
|
456
476
|
Return a Form as a JSON dict object
|
pyPreservica/webHooksAPI.py
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
pyPreservica/__init__.py,sha256=7KtbyFynwHrkpSFRvS5LxftRefR9J9OxiIzThnhDNnM,1250
|
|
2
|
+
pyPreservica/adminAPI.py,sha256=Ls7uJA2Lu5t2k5vOFqrOlbZxmDrSp1-JuD_5z10w9w0,37990
|
|
3
|
+
pyPreservica/authorityAPI.py,sha256=A52sFiAK4E4mlend_dknNIOW2BEwKXcLFI02anZBt3U,9211
|
|
4
|
+
pyPreservica/common.py,sha256=OpF6JuQt424sGAfDQ4r_fV32YMuz3kYfQYJ0psxIWTo,39191
|
|
5
|
+
pyPreservica/contentAPI.py,sha256=ZvX2aGQEaksmw-m-oEUI6daVSqFe_IcE1cGwCNbSCDQ,22286
|
|
6
|
+
pyPreservica/entityAPI.py,sha256=jxB_8Zd4QCxbpXrBm9ilJ7UfBi0ux85k5DGZ7Jgm2yI,132421
|
|
7
|
+
pyPreservica/mdformsAPI.py,sha256=D6p7uD2qNY76P6_k5MSaXnrYMp487hDXwladYvASejI,20052
|
|
8
|
+
pyPreservica/monitorAPI.py,sha256=LJOUrynBOWKlNiYpZ1iH8qB1oIIuKX1Ms1SRBcuXohA,6274
|
|
9
|
+
pyPreservica/opex.py,sha256=ccra1S4ojUXS3PlbU8WfxajOkJrwG4OykBnNrYP_jus,4875
|
|
10
|
+
pyPreservica/parAPI.py,sha256=f0ZUxLd0U-BW6kBx5K7W2Pv7NjG3MkTNydmxQ3U1ZVE,9296
|
|
11
|
+
pyPreservica/retentionAPI.py,sha256=QUTCbN4P3IpqmrebU_wd3n5ZVcyxVLTFAli8Y_GxOW4,24843
|
|
12
|
+
pyPreservica/settingsAPI.py,sha256=jXnMOCq3mimta6E-Os3J1I1if2pYsjLpOazAx8L-ZQI,10721
|
|
13
|
+
pyPreservica/uploadAPI.py,sha256=uX67mW-2q7FmjtXQ759GwHPL6Zs7R-iE8-86PBApvbY,99823
|
|
14
|
+
pyPreservica/webHooksAPI.py,sha256=KMObsdHp_0K0HjJUl5oaFh-vs21GCAQZo2ZTKkY38R8,6872
|
|
15
|
+
pyPreservica/workflowAPI.py,sha256=OcOiiUdrQerbPllrkj1lWpmuW0jTuyyV0urwPSYcd_U,17561
|
|
16
|
+
pypreservica-3.2.3.dist-info/licenses/LICENSE.txt,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
|
|
17
|
+
pypreservica-3.2.3.dist-info/METADATA,sha256=2kWPpvUUWzzrvqLnKgaL0hErw-w9sooNr909g0L_xV4,3077
|
|
18
|
+
pypreservica-3.2.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
19
|
+
pypreservica-3.2.3.dist-info/top_level.txt,sha256=iIBh6NAznYQHOV8mv_y_kGKSDITek9rANyFDwJsbU-c,13
|
|
20
|
+
pypreservica-3.2.3.dist-info/RECORD,,
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
pyPreservica/__init__.py,sha256=tLUJ6UX2RCmqbq_evT5ZlorC4T9sI7Opv83-E7Rvzj4,1250
|
|
2
|
-
pyPreservica/adminAPI.py,sha256=aMN2twcUZOFoGx2yapC6GVtBTdYHUJFA-5bdWVkCwS8,37773
|
|
3
|
-
pyPreservica/authorityAPI.py,sha256=jpf_m9i-IakyNVooi2yELuKt4yhX73hWqQNbPRHZx2g,9206
|
|
4
|
-
pyPreservica/common.py,sha256=CLfHI0Fec_wp1zngqw7-iIl2Yp3hG0ohjuhdl-K84hU,39030
|
|
5
|
-
pyPreservica/contentAPI.py,sha256=ZvX2aGQEaksmw-m-oEUI6daVSqFe_IcE1cGwCNbSCDQ,22286
|
|
6
|
-
pyPreservica/entityAPI.py,sha256=mELG2TxnFBCuDtsrZ2eRNc8EF-D6dI-dumzTfK976TQ,129974
|
|
7
|
-
pyPreservica/mdformsAPI.py,sha256=_hBjT4-OzgLQGDfYX7b_01P27wc-RmsCEu57VtyAdh8,19173
|
|
8
|
-
pyPreservica/monitorAPI.py,sha256=LJOUrynBOWKlNiYpZ1iH8qB1oIIuKX1Ms1SRBcuXohA,6274
|
|
9
|
-
pyPreservica/opex.py,sha256=ccra1S4ojUXS3PlbU8WfxajOkJrwG4OykBnNrYP_jus,4875
|
|
10
|
-
pyPreservica/parAPI.py,sha256=f0ZUxLd0U-BW6kBx5K7W2Pv7NjG3MkTNydmxQ3U1ZVE,9296
|
|
11
|
-
pyPreservica/retentionAPI.py,sha256=QUTCbN4P3IpqmrebU_wd3n5ZVcyxVLTFAli8Y_GxOW4,24843
|
|
12
|
-
pyPreservica/settingsAPI.py,sha256=jXnMOCq3mimta6E-Os3J1I1if2pYsjLpOazAx8L-ZQI,10721
|
|
13
|
-
pyPreservica/uploadAPI.py,sha256=uX67mW-2q7FmjtXQ759GwHPL6Zs7R-iE8-86PBApvbY,99823
|
|
14
|
-
pyPreservica/webHooksAPI.py,sha256=B3C6PV_3JLlJrr9PtsTzL-21M0msx8Mnj18Xb3Bv4RE,6814
|
|
15
|
-
pyPreservica/workflowAPI.py,sha256=OcOiiUdrQerbPllrkj1lWpmuW0jTuyyV0urwPSYcd_U,17561
|
|
16
|
-
pypreservica-3.2.2.dist-info/licenses/LICENSE.txt,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
|
|
17
|
-
pypreservica-3.2.2.dist-info/METADATA,sha256=_sr1wxUFF5oIuFQB6A90sDUAw88cWb11jhQ-kJGSBrk,3077
|
|
18
|
-
pypreservica-3.2.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
19
|
-
pypreservica-3.2.2.dist-info/top_level.txt,sha256=iIBh6NAznYQHOV8mv_y_kGKSDITek9rANyFDwJsbU-c,13
|
|
20
|
-
pypreservica-3.2.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|