pyPreservica 0.9.9__py3-none-any.whl → 3.3.4__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.
@@ -0,0 +1,229 @@
1
+ """
2
+ pyPreservica ControlledVocabularyAPI module definition
3
+
4
+ A client library for the Preservica Repository web services Webhook API
5
+ https://us.preservica.com/api/reference-metadata/documentation.html
6
+
7
+ author: James Carr
8
+ licence: Apache License 2.0
9
+
10
+ """
11
+
12
+ import csv
13
+ from typing import List, Set
14
+
15
+ from pyPreservica.common import *
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+ BASE_ENDPOINT = '/api/reference-metadata'
20
+
21
+
22
+ class Table:
23
+ def __init__(self, reference: str, name: str, security_tag: str, displayField: str, metadataConnections: list):
24
+ self.reference = reference
25
+ self.name = name
26
+ self.security_tag = security_tag
27
+ self.displayField = displayField
28
+ self.metadataConnections = metadataConnections
29
+ self.fields = None
30
+
31
+ def __str__(self):
32
+ return f"Ref:\t\t\t{self.reference}\n" \
33
+ f"Name:\t\t\t{self.name}\n" \
34
+ f"Security Tag:\t{self.security_tag}\n" \
35
+ f"Display Field:\t\t\t{self.displayField}\n" \
36
+ f"Metadata Connections:\t\t\t{self.metadataConnections}\n" \
37
+ f"Fields:\t\t\t{self.fields}\n"
38
+
39
+
40
+ class AuthorityAPI(AuthenticatedAPI):
41
+
42
+ def delete_record(self, reference: str):
43
+ """
44
+ Delete a record from a table by its reference
45
+
46
+ :param reference: The reference of the record to delete
47
+ :type: reference: str
48
+
49
+ """
50
+ headers = {HEADER_TOKEN: self.token, 'accept': 'application/json;charset=UTF-8'}
51
+ response = self.session.delete(f'{self.protocol}://{self.server}{BASE_ENDPOINT}/records/{reference}',
52
+ headers=headers)
53
+ if response.status_code == requests.codes.unauthorized:
54
+ self.token = self.__token__()
55
+ return self.delete_record(reference)
56
+ if response.status_code == requests.codes.no_content:
57
+ return None
58
+ else:
59
+ exception = HTTPException("", response.status_code, response.url, "delete_record",
60
+ response.content.decode('utf-8'))
61
+ logger.error(exception)
62
+ raise exception
63
+
64
+ def add_records(self, table: Table, csv_file, encoding=None):
65
+ """
66
+ Add new records to an existing table from a CSV document
67
+
68
+ :param table: The Table to add the record to
69
+ :type: table: Table
70
+
71
+ :param csv_file: The path to the CSV document
72
+ :type: csv_file: str
73
+
74
+ :param encoding: The encoding used to open the csv document
75
+ :type: encoding: str
76
+
77
+ """
78
+ with open(csv_file, newline='', encoding=encoding) as csvfile:
79
+ reader = csv.DictReader(csvfile)
80
+ for row in reader:
81
+ if ('ID' in row) or ('id' in row):
82
+ pass
83
+ else:
84
+ row['id'] = reader.line_num
85
+ self.add_record(table, row)
86
+
87
+ def add_record(self, table: Table, record: dict):
88
+ """
89
+ Add a new record to an existing table
90
+
91
+ :param table: The Table to add the record to
92
+ :type: table: Table
93
+
94
+ :param record: The record as a dictionary
95
+ :type: record: dict
96
+
97
+ :return: A single record
98
+ :rtype: dict
99
+
100
+ """
101
+ headers = {HEADER_TOKEN: self.token, 'accept': 'application/json;charset=UTF-8'}
102
+
103
+ body = {"securityDescriptor": "open", "fieldValues": []}
104
+ for key, val in record.items():
105
+ body["fieldValues"].append({"name": str(key).lower(), "value": val})
106
+
107
+ response = self.session.post(f'{self.protocol}://{self.server}{BASE_ENDPOINT}/tables/{table.reference}/records',
108
+ headers=headers, json=body)
109
+
110
+ if response.status_code == requests.codes.unauthorized:
111
+ self.token = self.__token__()
112
+ return self.add_record(table, record)
113
+ if response.status_code == requests.codes.created:
114
+ return str(response.content.decode('utf-8'))
115
+ else:
116
+ exception = HTTPException("", response.status_code, response.url, "add_record",
117
+ response.content.decode('utf-8'))
118
+ logger.error(exception)
119
+ raise exception
120
+
121
+ def record(self, reference: str) -> dict:
122
+ """
123
+ Return a record by its reference
124
+
125
+ :param reference: The reference of the record
126
+ :type: reference: str
127
+
128
+ :return: A single record
129
+ :rtype: dict
130
+
131
+ """
132
+ headers = {HEADER_TOKEN: self.token, 'accept': 'application/json;charset=UTF-8'}
133
+ response = self.session.get(f'{self.protocol}://{self.server}{BASE_ENDPOINT}/records/{reference}',
134
+ headers=headers)
135
+ if response.status_code == requests.codes.unauthorized:
136
+ self.token = self.__token__()
137
+ return self.record(reference)
138
+ if response.status_code == requests.codes.ok:
139
+ json_response = str(response.content.decode('utf-8'))
140
+ return json.loads(json_response)
141
+ else:
142
+ exception = HTTPException("", response.status_code, response.url, "record",
143
+ response.content.decode('utf-8'))
144
+ logger.error(exception)
145
+ raise exception
146
+
147
+ def records(self, table: Table) -> List[dict]:
148
+ """
149
+ Return all records from a table
150
+
151
+ :param table: The authority table to return the records from
152
+ :type: table: Table
153
+
154
+ :return: List of records
155
+ :rtype: list[dict]
156
+
157
+ """
158
+ headers = {HEADER_TOKEN: self.token, 'accept': 'application/json;charset=UTF-8'}
159
+ response = self.session.get(f'{self.protocol}://{self.server}{BASE_ENDPOINT}/tables/{table.reference}/records',
160
+ headers=headers, params={"expand": "true"})
161
+ if response.status_code == requests.codes.unauthorized:
162
+ self.token = self.__token__()
163
+ return self.records(table)
164
+ if response.status_code == requests.codes.ok:
165
+ json_response = str(response.content.decode('utf-8'))
166
+ return json.loads(json_response)['records']
167
+ else:
168
+ exception = HTTPException("", response.status_code, response.url, "records",
169
+ response.content.decode('utf-8'))
170
+ logger.error(exception)
171
+ raise exception
172
+
173
+ def table(self, reference: str) -> Table:
174
+ """
175
+ fetch an authority table by its reference
176
+
177
+ :param reference: The reference for the authority table
178
+ :type: reference: str
179
+
180
+ :return: An authority table of interest
181
+ :rtype: Table
182
+
183
+ """
184
+ headers = {HEADER_TOKEN: self.token, 'accept': 'application/json;charset=UTF-8'}
185
+ response = self.session.get(f'{self.protocol}://{self.server}{BASE_ENDPOINT}/tables/{reference}',
186
+ headers=headers)
187
+ if response.status_code == requests.codes.unauthorized:
188
+ self.token = self.__token__()
189
+ return self.table(reference)
190
+ if response.status_code == requests.codes.ok:
191
+ json_response = str(response.content.decode('utf-8'))
192
+ doc = json.loads(json_response)
193
+ table = Table(doc['ref'], doc['name'], doc['securityDescriptor'], doc['displayField'],
194
+ doc['metadataConnections'])
195
+ table.fields = doc['fields']
196
+ return table
197
+ else:
198
+ exception = HTTPException("", response.status_code, response.url, "table",
199
+ response.content.decode('utf-8'))
200
+ logger.error(exception)
201
+ raise exception
202
+
203
+ def tables(self) -> Set[Table]:
204
+ """
205
+ List reference metadata tables
206
+
207
+ :return: Set of authority tables
208
+ :rtype: set(Table)
209
+
210
+ """
211
+ headers = {HEADER_TOKEN: self.token, 'accept': 'application/json;charset=UTF-8'}
212
+ response = self.session.get(f'{self.protocol}://{self.server}{BASE_ENDPOINT}/tables', headers=headers)
213
+ if response.status_code == requests.codes.unauthorized:
214
+ self.token = self.__token__()
215
+ return self.tables()
216
+ if response.status_code == requests.codes.ok:
217
+ json_response = str(response.content.decode('utf-8'))
218
+ doc = json.loads(json_response)
219
+ results = set()
220
+ for table in doc['tables']:
221
+ t = Table(table['ref'], table['name'], table['securityDescriptor'], table['displayField'],
222
+ table['metadataConnections'])
223
+ results.add(t)
224
+ return results
225
+ else:
226
+ exception = HTTPException("", response.status_code, response.url, "tables",
227
+ response.content.decode('utf-8'))
228
+ logger.error(exception)
229
+ raise exception