pyPreservica 2.7.4__tar.gz → 2.8.0__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.
Files changed (49) hide show
  1. {pypreservica-2.7.4 → pypreservica-2.8.0}/PKG-INFO +1 -1
  2. {pypreservica-2.7.4 → pypreservica-2.8.0}/pyPreservica/__init__.py +2 -2
  3. pypreservica-2.8.0/pyPreservica/mdformsAPI.py +300 -0
  4. {pypreservica-2.7.4 → pypreservica-2.8.0}/pyPreservica.egg-info/PKG-INFO +1 -1
  5. {pypreservica-2.7.4 → pypreservica-2.8.0}/pyPreservica.egg-info/SOURCES.txt +1 -0
  6. {pypreservica-2.7.4 → pypreservica-2.8.0}/setup.py +1 -1
  7. pypreservica-2.8.0/tests/test_groups.py +8 -0
  8. pypreservica-2.7.4/pyPreservica/mdformsAPI.py +0 -105
  9. {pypreservica-2.7.4 → pypreservica-2.8.0}/LICENSE.txt +0 -0
  10. {pypreservica-2.7.4 → pypreservica-2.8.0}/README.md +0 -0
  11. {pypreservica-2.7.4 → pypreservica-2.8.0}/pyPreservica/adminAPI.py +0 -0
  12. {pypreservica-2.7.4 → pypreservica-2.8.0}/pyPreservica/authorityAPI.py +0 -0
  13. {pypreservica-2.7.4 → pypreservica-2.8.0}/pyPreservica/common.py +0 -0
  14. {pypreservica-2.7.4 → pypreservica-2.8.0}/pyPreservica/contentAPI.py +0 -0
  15. {pypreservica-2.7.4 → pypreservica-2.8.0}/pyPreservica/entityAPI.py +0 -0
  16. {pypreservica-2.7.4 → pypreservica-2.8.0}/pyPreservica/monitorAPI.py +0 -0
  17. {pypreservica-2.7.4 → pypreservica-2.8.0}/pyPreservica/opex.py +0 -0
  18. {pypreservica-2.7.4 → pypreservica-2.8.0}/pyPreservica/parAPI.py +0 -0
  19. {pypreservica-2.7.4 → pypreservica-2.8.0}/pyPreservica/retentionAPI.py +0 -0
  20. {pypreservica-2.7.4 → pypreservica-2.8.0}/pyPreservica/uploadAPI.py +0 -0
  21. {pypreservica-2.7.4 → pypreservica-2.8.0}/pyPreservica/webHooksAPI.py +0 -0
  22. {pypreservica-2.7.4 → pypreservica-2.8.0}/pyPreservica/workflowAPI.py +0 -0
  23. {pypreservica-2.7.4 → pypreservica-2.8.0}/pyPreservica.egg-info/dependency_links.txt +0 -0
  24. {pypreservica-2.7.4 → pypreservica-2.8.0}/pyPreservica.egg-info/requires.txt +0 -0
  25. {pypreservica-2.7.4 → pypreservica-2.8.0}/pyPreservica.egg-info/top_level.txt +0 -0
  26. {pypreservica-2.7.4 → pypreservica-2.8.0}/setup.cfg +0 -0
  27. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_authority_records.py +0 -0
  28. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_bitstream.py +0 -0
  29. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_children.py +0 -0
  30. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_content_api.py +0 -0
  31. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_crawl_fs.py +0 -0
  32. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_delete.py +0 -0
  33. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_download.py +0 -0
  34. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_entity.py +0 -0
  35. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_export_opex.py +0 -0
  36. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_identifier.py +0 -0
  37. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_ingest.py +0 -0
  38. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_integrity_check.py +0 -0
  39. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_metadata.py +0 -0
  40. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_par.py +0 -0
  41. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_replace.py +0 -0
  42. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_retention.py +0 -0
  43. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_schema.py +0 -0
  44. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_security.py +0 -0
  45. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_thumbnail.py +0 -0
  46. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_upload.py +0 -0
  47. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_users.py +0 -0
  48. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_workflow.py +0 -0
  49. {pypreservica-2.7.4 → pypreservica-2.8.0}/tests/test_xml_metadata.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyPreservica
3
- Version: 2.7.4
3
+ Version: 2.8.0
4
4
  Summary: Python library for the Preservica API
5
5
  Home-page: https://pypreservica.readthedocs.io/
6
6
  Author: James Carr
@@ -18,11 +18,11 @@ from .adminAPI import AdminAPI
18
18
  from .monitorAPI import MonitorAPI, MonitorCategory, MonitorStatus, MessageStatus
19
19
  from .webHooksAPI import WebHooksAPI, TriggerType, WebHookHandler
20
20
  from .authorityAPI import AuthorityAPI, Table
21
- from .mdformsAPI import MDFormsAPI
21
+ from .mdformsAPI import MetadataGroupsAPI, GroupFieldType, GroupField, Group
22
22
 
23
23
  __author__ = "James Carr (drjamescarr@gmail.com)"
24
24
 
25
25
  # Version of the pyPreservica package
26
- __version__ = "2.7.4"
26
+ __version__ = "2.8.0"
27
27
 
28
28
  __license__ = "Apache License Version 2.0"
@@ -0,0 +1,300 @@
1
+ """
2
+ pyPreservica MDFormsAPI module definition
3
+
4
+ A client library for the Preservica Repository web services Metadata API
5
+ https://demo.preservica.com/api/metadata/documentation.html
6
+
7
+ author: James Carr
8
+ licence: Apache License 2.0
9
+
10
+ """
11
+ import json
12
+ import xml.etree.ElementTree
13
+ from typing import Callable, List
14
+
15
+ from pyPreservica.common import *
16
+
17
+
18
+ class GroupFieldType(Enum):
19
+ STRING = "STRING"
20
+ LONG_STRING = "LONGSTRING"
21
+ DATE = "DATE"
22
+ NUMBER = "NUMBER"
23
+
24
+
25
+ class GroupField:
26
+ field_id: str
27
+ name: str
28
+ field_type: GroupFieldType
29
+ maxLength: int
30
+ default: str
31
+ visible: bool
32
+ editable: bool
33
+ minOccurs: int
34
+ maxOccurs: int
35
+ values: List[str]
36
+ indexed: bool
37
+
38
+ def __init__(self, field_id: str, name: str, field_type: GroupFieldType = GroupFieldType.STRING,
39
+ maxLength: int = -1, default: str = "", visible: bool = True, editable: bool = True,
40
+ minOccurs: int = 0, maxOccurs: int = 1, indexed: bool = True, values: List = None):
41
+ self.field_id = field_id
42
+ self.name = name
43
+ self.field_type = field_type
44
+ self.maxLength = maxLength
45
+ self.default = default
46
+ self.visible = visible
47
+ self.editable = editable
48
+ self.minOccurs = minOccurs
49
+ self.maxOccurs = maxOccurs
50
+ self.values = values
51
+ self.indexed = indexed
52
+
53
+ def __str__(self):
54
+ return (f"Field ID: {self.field_id}\n" + f"Field Name: {self.name}\n" + f"Field Type: {self.field_type}\n" +
55
+ f"Field Visible: {self.visible}\n" + f"Field Editable: {self.editable}\n")
56
+
57
+
58
+ class Group:
59
+ group_id: str
60
+ name: str
61
+ description: str
62
+ schemaUri: str
63
+ fields: List[GroupField] = []
64
+
65
+ def __str__(self):
66
+ return (f"Group ID: {self.group_id}\n" + f"Group Name: {self.name}\n" +
67
+ f"Group Description: {self.description}\n" + f"Group Schema URI: {self.schemaUri}")
68
+
69
+
70
+ class MetadataGroupsAPI(AuthenticatedAPI):
71
+ def __init__(self, username: str = None, password: str = None, tenant: str = None, server: str = None,
72
+ use_shared_secret: bool = False, two_fa_secret_key: str = None,
73
+ protocol: str = "https", request_hook: Callable = None):
74
+
75
+ super().__init__(username, password, tenant, server, use_shared_secret, two_fa_secret_key,
76
+ protocol, request_hook)
77
+
78
+ xml.etree.ElementTree.register_namespace("oai_dc", "http://www.openarchives.org/OAI/2.0/oai_dc/")
79
+ xml.etree.ElementTree.register_namespace("ead", "urn:isbn:1-931666-22-9")
80
+
81
+ def delete_group_namespace(self, schema: str):
82
+ """
83
+ Delete a new Metadata Group using its schema URI
84
+
85
+ :param schema: The Group namespace schema URI
86
+ :type schema: str
87
+
88
+ :return: None
89
+ :rtype: None
90
+
91
+ """
92
+ for group in self.groups():
93
+ if group.schemaUri == schema:
94
+ self.delete_group(group.group_id)
95
+
96
+ def delete_group(self, group_id: str):
97
+ """
98
+ Delete a new Metadata Group using its ID
99
+
100
+ :param group_id: Group ID
101
+ :type group_id: str
102
+
103
+ :return: None
104
+ :rtype: None
105
+
106
+ """
107
+ headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/json;charset=UTF-8'}
108
+ url = f'{self.protocol}://{self.server}/api/metadata/groups/{group_id}'
109
+ with self.session.delete(url, headers=headers) as request:
110
+ if request.status_code == requests.codes.unauthorized:
111
+ self.token = self.__token__()
112
+ return self.delete_group(group_id)
113
+ elif request.status_code == requests.codes.no_content:
114
+ return None
115
+ else:
116
+ exception = HTTPException(None, request.status_code, request.url, "delete_group",
117
+ request.content.decode('utf-8'))
118
+ logger.error(exception)
119
+ raise exception
120
+
121
+ def add_group(self, group_name: str, group_description: str, fields: List[GroupField]):
122
+ """
123
+ Create a new Metadata Group GroupFields
124
+
125
+ :param group_name: The name of the new Group
126
+ :type group_name: str
127
+
128
+ :param group_description: The description of the new Group
129
+ :type group_description: str
130
+
131
+ :param fields: The list of fields
132
+ :type fields: List[GroupField]
133
+
134
+ :return: JSON document
135
+ :rtype: str
136
+
137
+ """
138
+
139
+ fields_str_list = []
140
+ for field in fields:
141
+
142
+ values = ""
143
+ if (field.values is not None) and (len(field.values) > 0):
144
+ values = f"""\n"values" : [ {",".join('"' + item + '"' for item in field.values)} ],
145
+ """
146
+
147
+ fields_str = f"""{{
148
+ "id" : "{field.field_id}",
149
+ "name": "{field.name}",
150
+ "type": "{field.field_type.value}",
151
+ "minOccurs": "{field.minOccurs}",
152
+ "maxOccurs": "{field.maxOccurs}",
153
+ "visible": "{field.visible}", {values}
154
+ "editable": "{field.editable}",
155
+ "defaultValue": "{field.default}",
156
+ "indexed": "{field.indexed}"
157
+ }}"""
158
+
159
+ fields_str_list.append(fields_str)
160
+
161
+ json_doc = f"""{{
162
+ "name" : "{group_name}",
163
+ "description" : "{group_description}",
164
+ "fields" : [ {",".join(fields_str_list)} ]
165
+ }}"""
166
+
167
+ print(json_doc)
168
+
169
+ json_response = self.add_group_json(json_doc)
170
+ group_id = json_response['id']
171
+ return self.group(group_id)
172
+
173
+ def add_group_json(self, json_document: str) -> str:
174
+ """
175
+ Create a new Metadata Group using a JSON document
176
+
177
+ :param json_document: JSON document
178
+ :type json_document: str
179
+
180
+ :return: JSON document
181
+ :rtype: str
182
+
183
+ """
184
+ headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/json;charset=UTF-8'}
185
+ url = f'{self.protocol}://{self.server}/api/metadata/groups/'
186
+ with self.session.post(url, headers=headers, data=json_document) as request:
187
+ if request.status_code == requests.codes.unauthorized:
188
+ self.token = self.__token__()
189
+ return self.add_group_json(json_document)
190
+ elif request.status_code == requests.codes.created:
191
+ return json.loads(str(request.content.decode('utf-8')))
192
+ else:
193
+ exception = HTTPException(None, request.status_code, request.url, "add_group_json",
194
+ request.content.decode('utf-8'))
195
+ logger.error(exception)
196
+ raise exception
197
+
198
+ def group_json(self, group_id: str) -> str:
199
+ """
200
+ Return a Group as a JSON document
201
+
202
+ :param group_id: The Group id
203
+ :type group_id: str
204
+
205
+ :return: JSON document
206
+ :rtype: str
207
+
208
+ """
209
+ headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/json;charset=UTF-8'}
210
+ url = f'{self.protocol}://{self.server}/api/metadata/groups/{group_id}'
211
+ with self.session.get(url, headers=headers) as request:
212
+ if request.status_code == requests.codes.unauthorized:
213
+ self.token = self.__token__()
214
+ return self.group_json(group_id)
215
+ elif request.status_code == requests.codes.ok:
216
+ return str(request.content.decode('utf-8'))
217
+ else:
218
+ exception = HTTPException(None, request.status_code, request.url, "group_json",
219
+ request.content.decode('utf-8'))
220
+ logger.error(exception)
221
+ raise exception
222
+
223
+ def group(self, group_id: str) -> Group:
224
+ """
225
+ Return a Group object by its id
226
+
227
+ :param group_id: The Group id
228
+ :type group_id: str
229
+
230
+ :return: The Group
231
+ :rtype: Group
232
+
233
+ """
234
+ json_group = json.loads(self.group_json(group_id))
235
+ group: Group = Group()
236
+ group.group_id = json_group['id']
237
+ group.name = json_group['name']
238
+ group.description = json_group['description']
239
+ group.schemaUri = json_group['schemaUri']
240
+
241
+ for f in json_group['fields']:
242
+ gf: GroupField = GroupField(f['id'], f['name'])
243
+ if 'type' in f:
244
+ gf.field_type = f['type']
245
+ if 'visible' in f:
246
+ gf.visible = f['visible']
247
+ if 'editable' in f:
248
+ gf.editable = f['editable']
249
+ if 'indexed' in f:
250
+ gf.indexed = f['indexed']
251
+ if 'maxOccurs' in f:
252
+ gf.maxOccurs = f['maxOccurs']
253
+ if 'minOccurs' in f:
254
+ gf.minOccurs = f['minOccurs']
255
+ if 'values' in f:
256
+ gf.values = f['values']
257
+ group.fields.append(gf)
258
+ return group
259
+
260
+ def groups_json(self) -> str:
261
+ """
262
+ Return all the groups in the tenancy as a single json document
263
+
264
+ :return: JSON document
265
+ :rtype: str
266
+
267
+ """
268
+
269
+ headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/json;charset=UTF-8'}
270
+ url = f'{self.protocol}://{self.server}/api/metadata/groups'
271
+ with self.session.get(url, headers=headers) as request:
272
+ if request.status_code == requests.codes.unauthorized:
273
+ self.token = self.__token__()
274
+ return self.groups_json()
275
+ elif request.status_code == requests.codes.ok:
276
+ return str(request.content.decode('utf-8'))
277
+ else:
278
+ exception = HTTPException(None, request.status_code, request.url, "groups_json",
279
+ request.content.decode('utf-8'))
280
+ logger.error(exception)
281
+ raise exception
282
+
283
+ def groups(self) -> List[Group]:
284
+ """
285
+ Return all the groups in the tenancy
286
+
287
+ :return: list of Groups
288
+ :rtype: List[Group]
289
+
290
+ """
291
+ groups = json.loads(self.groups_json())['groups']
292
+ return_groups = []
293
+ for g in groups:
294
+ group: Group = Group()
295
+ group.group_id = g['id']
296
+ group.name = g['name']
297
+ group.description = g['description']
298
+ group.schemaUri = g['schemaUri']
299
+ return_groups.append(group)
300
+ return return_groups
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyPreservica
3
- Version: 2.7.4
3
+ Version: 2.8.0
4
4
  Summary: Python library for the Preservica API
5
5
  Home-page: https://pypreservica.readthedocs.io/
6
6
  Author: James Carr
@@ -29,6 +29,7 @@ tests/test_delete.py
29
29
  tests/test_download.py
30
30
  tests/test_entity.py
31
31
  tests/test_export_opex.py
32
+ tests/test_groups.py
32
33
  tests/test_identifier.py
33
34
  tests/test_ingest.py
34
35
  tests/test_integrity_check.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.4",
24
+ version="2.8.0",
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,8 @@
1
+ import pytest
2
+ from pyPreservica import *
3
+
4
+
5
+ def test_cam_get_all_groups():
6
+ client = MetadataGroupsAPI()
7
+ for g in client.groups():
8
+ assert isinstance(g, Group)
@@ -1,105 +0,0 @@
1
- """
2
- pyPreservica MDFormsAPI module definition
3
-
4
- A client library for the Preservica Repository web services Metadata API
5
- https://demo.preservica.com/api/metadata/documentation.html
6
-
7
- author: James Carr
8
- licence: Apache License 2.0
9
-
10
- """
11
- import json
12
- import xml.etree.ElementTree
13
- from typing import Callable
14
-
15
- from pyPreservica.common import *
16
-
17
-
18
- class MDFormsAPI(AuthenticatedAPI):
19
- def __init__(self, username: str = None, password: str = None, tenant: str = None, server: str = None,
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
-
26
- xml.etree.ElementTree.register_namespace("oai_dc", "http://www.openarchives.org/OAI/2.0/oai_dc/")
27
- xml.etree.ElementTree.register_namespace("ead", "urn:isbn:1-931666-22-9")
28
-
29
- def delete_group(self, id: str):
30
- """
31
- Delete a group
32
- :param id: Group ID
33
- :return:
34
- """
35
- headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/json;charset=UTF-8'}
36
- url = f'{self.protocol}://{self.server}/api/metadata/groups/{id}'
37
- with self.session.delete(url, headers=headers) as request:
38
- if request.status_code == requests.codes.unauthorized:
39
- self.token = self.__token__()
40
- return self.delete_group(id)
41
- elif request.status_code == requests.codes.no_content:
42
- return None
43
- else:
44
- exception = HTTPException(None, request.status_code, request.url, "delete_group",
45
- request.content.decode('utf-8'))
46
- logger.error(exception)
47
- raise exception
48
-
49
- def add_group(self, document):
50
- """
51
- Add a new group
52
- :return:
53
- """
54
- headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/json;charset=UTF-8'}
55
- url = f'{self.protocol}://{self.server}/api/metadata/groups/'
56
- with self.session.post(url, headers=headers, json=document) as request:
57
- if request.status_code == requests.codes.unauthorized:
58
- self.token = self.__token__()
59
- return self.add_group(document)
60
- elif request.status_code == requests.codes.created:
61
- return json.loads(str(request.content.decode('utf-8')))
62
- else:
63
- exception = HTTPException(None, request.status_code, request.url, "group",
64
- request.content.decode('utf-8'))
65
- logger.error(exception)
66
- raise exception
67
-
68
- def group(self, id: str):
69
- """
70
- Fetch a metadata Group by its id
71
- :param id: The group ID
72
- :return: JSON Document
73
- """
74
- headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/json;charset=UTF-8'}
75
- url = f'{self.protocol}://{self.server}/api/metadata/groups/{id}'
76
- with self.session.get(url, headers=headers) as request:
77
- if request.status_code == requests.codes.unauthorized:
78
- self.token = self.__token__()
79
- return self.group(id)
80
- elif request.status_code == requests.codes.ok:
81
- return json.loads(str(request.content.decode('utf-8')))
82
- else:
83
- exception = HTTPException(None, request.status_code, request.url, "group",
84
- request.content.decode('utf-8'))
85
- logger.error(exception)
86
- raise exception
87
-
88
- def groups(self):
89
- """
90
- Fetch all the Metadata Groups as JSON
91
- :return: JSON Document
92
- """
93
- headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/json;charset=UTF-8'}
94
- url = f'{self.protocol}://{self.server}/api/metadata/groups'
95
- with self.session.get(url, headers=headers) as request:
96
- if request.status_code == requests.codes.unauthorized:
97
- self.token = self.__token__()
98
- return self.groups()
99
- elif request.status_code == requests.codes.ok:
100
- return json.loads(str(request.content.decode('utf-8')))['groups']
101
- else:
102
- exception = HTTPException(None, request.status_code, request.url, "groups",
103
- request.content.decode('utf-8'))
104
- logger.error(exception)
105
- raise exception
File without changes
File without changes
File without changes