ds-caselaw-marklogic-api-client 23.0.2__py3-none-any.whl → 24.0.0__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 ds-caselaw-marklogic-api-client might be problematic. Click here for more details.
- caselawclient/Client.py +124 -76
- caselawclient/client_helpers/__init__.py +2 -2
- caselawclient/client_helpers/search_helpers.py +5 -3
- caselawclient/content_hash.py +2 -4
- caselawclient/errors.py +3 -6
- caselawclient/models/documents.py +39 -29
- caselawclient/models/judgments.py +1 -4
- caselawclient/models/neutral_citation_mixin.py +12 -15
- caselawclient/models/press_summaries.py +2 -5
- caselawclient/models/utilities/aws.py +9 -12
- caselawclient/models/utilities/dates.py +20 -0
- caselawclient/models/utilities/move.py +11 -10
- caselawclient/responses/search_response.py +4 -5
- caselawclient/responses/search_result.py +11 -10
- caselawclient/xml_helpers.py +3 -1
- caselawclient/xml_tools.py +6 -5
- {ds_caselaw_marklogic_api_client-23.0.2.dist-info → ds_caselaw_marklogic_api_client-24.0.0.dist-info}/METADATA +13 -11
- {ds_caselaw_marklogic_api_client-23.0.2.dist-info → ds_caselaw_marklogic_api_client-24.0.0.dist-info}/RECORD +20 -19
- {ds_caselaw_marklogic_api_client-23.0.2.dist-info → ds_caselaw_marklogic_api_client-24.0.0.dist-info}/LICENSE.md +0 -0
- {ds_caselaw_marklogic_api_client-23.0.2.dist-info → ds_caselaw_marklogic_api_client-24.0.0.dist-info}/WHEEL +0 -0
caselawclient/Client.py
CHANGED
|
@@ -36,10 +36,10 @@ from caselawclient.xquery_type_dicts import (
|
|
|
36
36
|
|
|
37
37
|
from . import xml_tools
|
|
38
38
|
from .content_hash import validate_content_hash
|
|
39
|
-
from .errors import MarklogicAPIError # noqa: F401
|
|
40
39
|
from .errors import (
|
|
41
40
|
DocumentNotFoundError,
|
|
42
41
|
GatewayTimeoutError,
|
|
42
|
+
MarklogicAPIError,
|
|
43
43
|
MarklogicBadRequestError,
|
|
44
44
|
MarklogicCheckoutConflictError,
|
|
45
45
|
MarklogicCommunicationError,
|
|
@@ -66,24 +66,18 @@ DEFAULT_USER_AGENT = f"ds-caselaw-marklogic-api-client/{VERSION}"
|
|
|
66
66
|
class NoResponse(Exception):
|
|
67
67
|
"""A requests HTTPError has no response. We expect this will never happen."""
|
|
68
68
|
|
|
69
|
-
pass
|
|
70
|
-
|
|
71
69
|
|
|
72
70
|
class MultipartResponseLongerThanExpected(Exception):
|
|
73
71
|
"""
|
|
74
72
|
MarkLogic has returned a multipart response with more than one part, where only a single part was expected.
|
|
75
73
|
"""
|
|
76
74
|
|
|
77
|
-
pass
|
|
78
|
-
|
|
79
75
|
|
|
80
76
|
class DocumentHasNoTypeCollection(Exception):
|
|
81
77
|
"""
|
|
82
78
|
A MarkLogic document is not part of a collection which identifies its document type.
|
|
83
79
|
"""
|
|
84
80
|
|
|
85
|
-
pass
|
|
86
|
-
|
|
87
81
|
|
|
88
82
|
def get_multipart_strings_from_marklogic_response(
|
|
89
83
|
response: requests.Response,
|
|
@@ -137,7 +131,7 @@ def get_single_string_from_marklogic_response(
|
|
|
137
131
|
|
|
138
132
|
elif part_count > 1:
|
|
139
133
|
raise MultipartResponseLongerThanExpected(
|
|
140
|
-
f"Response returned {part_count} multipart items, expected 1"
|
|
134
|
+
f"Response returned {part_count} multipart items, expected 1",
|
|
141
135
|
)
|
|
142
136
|
|
|
143
137
|
return parts[0]
|
|
@@ -156,7 +150,7 @@ def get_single_bytestring_from_marklogic_response(
|
|
|
156
150
|
|
|
157
151
|
elif part_count > 1:
|
|
158
152
|
raise MultipartResponseLongerThanExpected(
|
|
159
|
-
f"Response returned {part_count} multipart items, expected 1"
|
|
153
|
+
f"Response returned {part_count} multipart items, expected 1",
|
|
160
154
|
)
|
|
161
155
|
|
|
162
156
|
return parts[0]
|
|
@@ -206,7 +200,8 @@ class MarklogicApiClient:
|
|
|
206
200
|
self.user_agent = user_agent
|
|
207
201
|
|
|
208
202
|
def get_press_summaries_for_document_uri(
|
|
209
|
-
self,
|
|
203
|
+
self,
|
|
204
|
+
uri: DocumentURIString,
|
|
210
205
|
) -> list[PressSummary]:
|
|
211
206
|
"""
|
|
212
207
|
Returns a list of PressSummary objects associated with a given Document URI
|
|
@@ -220,7 +215,9 @@ class MarklogicApiClient:
|
|
|
220
215
|
return [PressSummary(uri.strip(".xml"), self) for uri in uris]
|
|
221
216
|
|
|
222
217
|
def get_document_by_uri(
|
|
223
|
-
self,
|
|
218
|
+
self,
|
|
219
|
+
uri: DocumentURIString,
|
|
220
|
+
query: Optional[str] = None,
|
|
224
221
|
) -> Document:
|
|
225
222
|
document_type_class = self.get_document_type_from_uri(uri)
|
|
226
223
|
return document_type_class(uri, self)
|
|
@@ -238,7 +235,7 @@ class MarklogicApiClient:
|
|
|
238
235
|
return PressSummary
|
|
239
236
|
else:
|
|
240
237
|
raise DocumentHasNoTypeCollection(
|
|
241
|
-
f"The document at URI {uri} is not part of a valid document type collection."
|
|
238
|
+
f"The document at URI {uri} is not part of a valid document type collection.",
|
|
242
239
|
)
|
|
243
240
|
|
|
244
241
|
def _get_error_code_class(self, error_code: str) -> Type[MarklogicAPIError]:
|
|
@@ -262,7 +259,8 @@ class MarklogicApiClient:
|
|
|
262
259
|
raise NoResponse
|
|
263
260
|
status_code = e.response.status_code
|
|
264
261
|
new_error_class = self.http_error_classes.get(
|
|
265
|
-
status_code,
|
|
262
|
+
status_code,
|
|
263
|
+
self.default_http_error_class,
|
|
266
264
|
)
|
|
267
265
|
try:
|
|
268
266
|
response_body = json.dumps(response.json(), indent=4)
|
|
@@ -276,13 +274,14 @@ class MarklogicApiClient:
|
|
|
276
274
|
new_error_class = self._get_error_code_class(error_code)
|
|
277
275
|
|
|
278
276
|
new_exception = new_error_class(
|
|
279
|
-
"{}. Response body:\n{}"
|
|
277
|
+
f"{e}. Response body:\n{response_body}",
|
|
280
278
|
)
|
|
281
279
|
new_exception.response = response
|
|
282
280
|
raise new_exception
|
|
283
281
|
|
|
284
282
|
def _format_uri_for_marklogic(
|
|
285
|
-
self,
|
|
283
|
+
self,
|
|
284
|
+
uri: DocumentURIString,
|
|
286
285
|
) -> MarkLogicDocumentURIString:
|
|
287
286
|
"""
|
|
288
287
|
MarkLogic requires a document URI that begins with a slash `/` and ends in `.xml`. This method ensures any takes
|
|
@@ -297,7 +296,9 @@ class MarklogicApiClient:
|
|
|
297
296
|
return os.path.join(ROOT_DIR, "xquery", xquery_file_name)
|
|
298
297
|
|
|
299
298
|
def _send_to_eval(
|
|
300
|
-
self,
|
|
299
|
+
self,
|
|
300
|
+
vars: query_dicts.MarkLogicAPIDict,
|
|
301
|
+
xquery_file_name: str,
|
|
301
302
|
) -> requests.Response:
|
|
302
303
|
return self.eval(
|
|
303
304
|
self._xquery_path(xquery_file_name),
|
|
@@ -306,13 +307,17 @@ class MarklogicApiClient:
|
|
|
306
307
|
)
|
|
307
308
|
|
|
308
309
|
def _eval_and_decode(
|
|
309
|
-
self,
|
|
310
|
+
self,
|
|
311
|
+
vars: query_dicts.MarkLogicAPIDict,
|
|
312
|
+
xquery_file_name: str,
|
|
310
313
|
) -> str:
|
|
311
314
|
response = self._send_to_eval(vars, xquery_file_name)
|
|
312
315
|
return get_single_string_from_marklogic_response(response)
|
|
313
316
|
|
|
314
317
|
def _eval_as_bytes(
|
|
315
|
-
self,
|
|
318
|
+
self,
|
|
319
|
+
vars: query_dicts.MarkLogicAPIDict,
|
|
320
|
+
xquery_file_name: str,
|
|
316
321
|
) -> bytes:
|
|
317
322
|
response = self._send_to_eval(vars, xquery_file_name)
|
|
318
323
|
return get_single_bytestring_from_marklogic_response(response)
|
|
@@ -355,7 +360,10 @@ class MarklogicApiClient:
|
|
|
355
360
|
return self.make_request("GET", path, headers, data) # type: ignore
|
|
356
361
|
|
|
357
362
|
def POST(
|
|
358
|
-
self,
|
|
363
|
+
self,
|
|
364
|
+
path: str,
|
|
365
|
+
headers: dict[str, Any],
|
|
366
|
+
**data: Any,
|
|
359
367
|
) -> requests.Response:
|
|
360
368
|
logging.warning("POST() is deprecated, use eval() or invoke()")
|
|
361
369
|
return self.make_request("POST", path, headers, data) # type: ignore
|
|
@@ -382,7 +390,7 @@ class MarklogicApiClient:
|
|
|
382
390
|
marklogic_document_uri = self._format_uri_for_marklogic(judgment_uri)
|
|
383
391
|
marklogic_document_version_uri = (
|
|
384
392
|
MarkLogicDocumentVersionURIString(
|
|
385
|
-
self._format_uri_for_marklogic(version_uri)
|
|
393
|
+
self._format_uri_for_marklogic(version_uri),
|
|
386
394
|
)
|
|
387
395
|
if version_uri
|
|
388
396
|
else None
|
|
@@ -398,7 +406,7 @@ class MarklogicApiClient:
|
|
|
398
406
|
response = self._eval_as_bytes(vars, "get_judgment.xqy")
|
|
399
407
|
if not response:
|
|
400
408
|
raise MarklogicNotPermittedError(
|
|
401
|
-
"The document is not published and show_unpublished was not set"
|
|
409
|
+
"The document is not published and show_unpublished was not set",
|
|
402
410
|
)
|
|
403
411
|
|
|
404
412
|
return response
|
|
@@ -410,18 +418,24 @@ class MarklogicApiClient:
|
|
|
410
418
|
show_unpublished: bool = False,
|
|
411
419
|
) -> str:
|
|
412
420
|
return self.get_judgment_xml_bytestring(
|
|
413
|
-
judgment_uri,
|
|
421
|
+
judgment_uri,
|
|
422
|
+
version_uri,
|
|
423
|
+
show_unpublished,
|
|
414
424
|
).decode(encoding="utf-8")
|
|
415
425
|
|
|
416
426
|
def set_document_name(
|
|
417
|
-
self,
|
|
427
|
+
self,
|
|
428
|
+
document_uri: DocumentURIString,
|
|
429
|
+
content: str,
|
|
418
430
|
) -> requests.Response:
|
|
419
431
|
uri = self._format_uri_for_marklogic(document_uri)
|
|
420
432
|
vars: query_dicts.SetMetadataNameDict = {"uri": uri, "content": content}
|
|
421
433
|
return self._send_to_eval(vars, "set_metadata_name.xqy")
|
|
422
434
|
|
|
423
435
|
def set_judgment_date(
|
|
424
|
-
self,
|
|
436
|
+
self,
|
|
437
|
+
judgment_uri: DocumentURIString,
|
|
438
|
+
content: str,
|
|
425
439
|
) -> requests.Response:
|
|
426
440
|
warnings.warn(
|
|
427
441
|
"set_judgment_date() is deprecated, use set_document_work_expression_date()",
|
|
@@ -431,7 +445,9 @@ class MarklogicApiClient:
|
|
|
431
445
|
return self.set_document_work_expression_date(judgment_uri, content)
|
|
432
446
|
|
|
433
447
|
def set_document_work_expression_date(
|
|
434
|
-
self,
|
|
448
|
+
self,
|
|
449
|
+
document_uri: DocumentURIString,
|
|
450
|
+
content: str,
|
|
435
451
|
) -> requests.Response:
|
|
436
452
|
uri = self._format_uri_for_marklogic(document_uri)
|
|
437
453
|
vars: query_dicts.SetMetadataWorkExpressionDateDict = {
|
|
@@ -442,7 +458,9 @@ class MarklogicApiClient:
|
|
|
442
458
|
return self._send_to_eval(vars, "set_metadata_work_expression_date.xqy")
|
|
443
459
|
|
|
444
460
|
def set_judgment_citation(
|
|
445
|
-
self,
|
|
461
|
+
self,
|
|
462
|
+
judgment_uri: DocumentURIString,
|
|
463
|
+
content: str,
|
|
446
464
|
) -> requests.Response:
|
|
447
465
|
uri = self._format_uri_for_marklogic(judgment_uri)
|
|
448
466
|
vars: query_dicts.SetMetadataCitationDict = {
|
|
@@ -453,7 +471,9 @@ class MarklogicApiClient:
|
|
|
453
471
|
return self._send_to_eval(vars, "set_metadata_citation.xqy")
|
|
454
472
|
|
|
455
473
|
def set_document_court(
|
|
456
|
-
self,
|
|
474
|
+
self,
|
|
475
|
+
document_uri: DocumentURIString,
|
|
476
|
+
content: str,
|
|
457
477
|
) -> requests.Response:
|
|
458
478
|
uri = self._format_uri_for_marklogic(document_uri)
|
|
459
479
|
vars: query_dicts.SetMetadataCourtDict = {"uri": uri, "content": content}
|
|
@@ -461,14 +481,18 @@ class MarklogicApiClient:
|
|
|
461
481
|
return self._send_to_eval(vars, "set_metadata_court.xqy")
|
|
462
482
|
|
|
463
483
|
def set_document_jurisdiction(
|
|
464
|
-
self,
|
|
484
|
+
self,
|
|
485
|
+
document_uri: DocumentURIString,
|
|
486
|
+
content: str,
|
|
465
487
|
) -> requests.Response:
|
|
466
488
|
uri = self._format_uri_for_marklogic(document_uri)
|
|
467
489
|
vars: query_dicts.SetMetadataJurisdictionDict = {"uri": uri, "content": content}
|
|
468
490
|
return self._send_to_eval(vars, "set_metadata_jurisdiction.xqy")
|
|
469
491
|
|
|
470
492
|
def set_document_court_and_jurisdiction(
|
|
471
|
-
self,
|
|
493
|
+
self,
|
|
494
|
+
document_uri: DocumentURIString,
|
|
495
|
+
content: str,
|
|
472
496
|
) -> requests.Response:
|
|
473
497
|
if "/" in content:
|
|
474
498
|
court, jurisdiction = re.split("\\s*/\\s*", content)
|
|
@@ -479,15 +503,12 @@ class MarklogicApiClient:
|
|
|
479
503
|
return self.set_document_jurisdiction(document_uri, "")
|
|
480
504
|
|
|
481
505
|
def set_judgment_this_uri(
|
|
482
|
-
self,
|
|
506
|
+
self,
|
|
507
|
+
judgment_uri: DocumentURIString,
|
|
483
508
|
) -> requests.Response:
|
|
484
509
|
uri = self._format_uri_for_marklogic(judgment_uri)
|
|
485
|
-
content_with_id = (
|
|
486
|
-
|
|
487
|
-
)
|
|
488
|
-
content_without_id = (
|
|
489
|
-
f"https://caselaw.nationalarchives.gov.uk/{judgment_uri.lstrip('/')}"
|
|
490
|
-
)
|
|
510
|
+
content_with_id = f"https://caselaw.nationalarchives.gov.uk/id/{judgment_uri.lstrip('/')}"
|
|
511
|
+
content_without_id = f"https://caselaw.nationalarchives.gov.uk/{judgment_uri.lstrip('/')}"
|
|
491
512
|
content_with_xml = f"https://caselaw.nationalarchives.gov.uk/{judgment_uri.lstrip('/')}/data.xml"
|
|
492
513
|
vars: query_dicts.SetMetadataThisUriDict = {
|
|
493
514
|
"uri": uri,
|
|
@@ -584,7 +605,8 @@ class MarklogicApiClient:
|
|
|
584
605
|
return self._send_to_eval(vars, "update_document.xqy")
|
|
585
606
|
|
|
586
607
|
def list_judgment_versions(
|
|
587
|
-
self,
|
|
608
|
+
self,
|
|
609
|
+
judgment_uri: DocumentURIString,
|
|
588
610
|
) -> requests.Response:
|
|
589
611
|
uri = self._format_uri_for_marklogic(judgment_uri)
|
|
590
612
|
vars: query_dicts.ListJudgmentVersionsDict = {"uri": uri}
|
|
@@ -617,7 +639,8 @@ class MarklogicApiClient:
|
|
|
617
639
|
return self._send_to_eval(vars, "checkin_judgment.xqy")
|
|
618
640
|
|
|
619
641
|
def get_judgment_checkout_status(
|
|
620
|
-
self,
|
|
642
|
+
self,
|
|
643
|
+
judgment_uri: DocumentURIString,
|
|
621
644
|
) -> requests.Response:
|
|
622
645
|
uri = self._format_uri_for_marklogic(judgment_uri)
|
|
623
646
|
vars: query_dicts.GetJudgmentCheckoutStatusDict = {"uri": uri}
|
|
@@ -625,7 +648,8 @@ class MarklogicApiClient:
|
|
|
625
648
|
return self._send_to_eval(vars, "get_judgment_checkout_status.xqy")
|
|
626
649
|
|
|
627
650
|
def get_judgment_checkout_status_message(
|
|
628
|
-
self,
|
|
651
|
+
self,
|
|
652
|
+
judgment_uri: DocumentURIString,
|
|
629
653
|
) -> Optional[str]:
|
|
630
654
|
"""Return the annotation of the lock or `None` if there is no lock."""
|
|
631
655
|
response = self.get_judgment_checkout_status(judgment_uri)
|
|
@@ -636,11 +660,14 @@ class MarklogicApiClient:
|
|
|
636
660
|
return None
|
|
637
661
|
response_xml = ElementTree.fromstring(content)
|
|
638
662
|
return response_xml.find(
|
|
639
|
-
"dls:annotation",
|
|
663
|
+
"dls:annotation",
|
|
664
|
+
namespaces={"dls": "http://marklogic.com/xdmp/dls"},
|
|
640
665
|
).text # type: ignore
|
|
641
666
|
|
|
642
667
|
def get_judgment_version(
|
|
643
|
-
self,
|
|
668
|
+
self,
|
|
669
|
+
judgment_uri: DocumentURIString,
|
|
670
|
+
version: int,
|
|
644
671
|
) -> requests.Response:
|
|
645
672
|
uri = self._format_uri_for_marklogic(judgment_uri)
|
|
646
673
|
vars: query_dicts.GetJudgmentVersionDict = {"uri": uri, "version": str(version)}
|
|
@@ -649,7 +676,7 @@ class MarklogicApiClient:
|
|
|
649
676
|
|
|
650
677
|
def validate_document(self, document_uri: DocumentURIString) -> bool:
|
|
651
678
|
vars: query_dicts.ValidateDocumentDict = {
|
|
652
|
-
"uri": self._format_uri_for_marklogic(document_uri)
|
|
679
|
+
"uri": self._format_uri_for_marklogic(document_uri),
|
|
653
680
|
}
|
|
654
681
|
response = self._send_to_eval(vars, "validate_document.xqy")
|
|
655
682
|
content = decoder.MultipartDecoder.from_response(response).parts[0].text
|
|
@@ -657,14 +684,18 @@ class MarklogicApiClient:
|
|
|
657
684
|
return (
|
|
658
685
|
len(
|
|
659
686
|
xml.findall(
|
|
660
|
-
".//error:error",
|
|
687
|
+
".//error:error",
|
|
688
|
+
{"error": "http://marklogic.com/xdmp/error"},
|
|
661
689
|
),
|
|
662
690
|
)
|
|
663
691
|
== 0
|
|
664
692
|
)
|
|
665
693
|
|
|
666
694
|
def eval(
|
|
667
|
-
self,
|
|
695
|
+
self,
|
|
696
|
+
xquery_path: str,
|
|
697
|
+
vars: str,
|
|
698
|
+
accept_header: str = "multipart/mixed",
|
|
668
699
|
) -> requests.Response:
|
|
669
700
|
headers = {
|
|
670
701
|
"Content-type": "application/x-www-form-urlencoded",
|
|
@@ -676,14 +707,20 @@ class MarklogicApiClient:
|
|
|
676
707
|
}
|
|
677
708
|
path = "LATEST/eval"
|
|
678
709
|
response = self.session.request(
|
|
679
|
-
"POST",
|
|
710
|
+
"POST",
|
|
711
|
+
url=self._path_to_request_url(path),
|
|
712
|
+
headers=headers,
|
|
713
|
+
data=data,
|
|
680
714
|
)
|
|
681
715
|
# Raise relevant exception for an erroneous response
|
|
682
716
|
self._raise_for_status(response)
|
|
683
717
|
return response
|
|
684
718
|
|
|
685
719
|
def invoke(
|
|
686
|
-
self,
|
|
720
|
+
self,
|
|
721
|
+
module: str,
|
|
722
|
+
vars: str,
|
|
723
|
+
accept_header: str = "multipart/mixed",
|
|
687
724
|
) -> requests.Response:
|
|
688
725
|
headers = {
|
|
689
726
|
"Content-type": "application/x-www-form-urlencoded",
|
|
@@ -695,7 +732,10 @@ class MarklogicApiClient:
|
|
|
695
732
|
}
|
|
696
733
|
path = "LATEST/invoke"
|
|
697
734
|
response = self.session.request(
|
|
698
|
-
"POST",
|
|
735
|
+
"POST",
|
|
736
|
+
url=self._path_to_request_url(path),
|
|
737
|
+
headers=headers,
|
|
738
|
+
data=data,
|
|
699
739
|
)
|
|
700
740
|
# Raise relevant exception for an erroneous response
|
|
701
741
|
self._raise_for_status(response)
|
|
@@ -723,7 +763,7 @@ class MarklogicApiClient:
|
|
|
723
763
|
"""
|
|
724
764
|
module = "/judgments/search/search-v2.xqy" # as stored on Marklogic
|
|
725
765
|
search_parameters.show_unpublished = self.verify_show_unpublished(
|
|
726
|
-
search_parameters.show_unpublished
|
|
766
|
+
search_parameters.show_unpublished,
|
|
727
767
|
)
|
|
728
768
|
vars = json.dumps(search_parameters.as_marklogic_payload())
|
|
729
769
|
return self.invoke(module, vars)
|
|
@@ -739,7 +779,7 @@ class MarklogicApiClient:
|
|
|
739
779
|
marklogic_document_uri = self._format_uri_for_marklogic(judgment_uri)
|
|
740
780
|
marklogic_document_version_uri = (
|
|
741
781
|
MarkLogicDocumentVersionURIString(
|
|
742
|
-
self._format_uri_for_marklogic(version_uri)
|
|
782
|
+
self._format_uri_for_marklogic(version_uri),
|
|
743
783
|
)
|
|
744
784
|
if version_uri
|
|
745
785
|
else None
|
|
@@ -815,7 +855,10 @@ class MarklogicApiClient:
|
|
|
815
855
|
)
|
|
816
856
|
|
|
817
857
|
def set_property(
|
|
818
|
-
self,
|
|
858
|
+
self,
|
|
859
|
+
judgment_uri: DocumentURIString,
|
|
860
|
+
name: str,
|
|
861
|
+
value: str,
|
|
819
862
|
) -> requests.Response:
|
|
820
863
|
uri = self._format_uri_for_marklogic(judgment_uri)
|
|
821
864
|
vars: query_dicts.SetPropertyDict = {
|
|
@@ -827,7 +870,10 @@ class MarklogicApiClient:
|
|
|
827
870
|
return self._send_to_eval(vars, "set_property.xqy")
|
|
828
871
|
|
|
829
872
|
def set_boolean_property(
|
|
830
|
-
self,
|
|
873
|
+
self,
|
|
874
|
+
judgment_uri: DocumentURIString,
|
|
875
|
+
name: str,
|
|
876
|
+
value: bool,
|
|
831
877
|
) -> requests.Response:
|
|
832
878
|
uri = self._format_uri_for_marklogic(judgment_uri)
|
|
833
879
|
string_value = "true" if value else "false"
|
|
@@ -843,7 +889,9 @@ class MarklogicApiClient:
|
|
|
843
889
|
return content == "true"
|
|
844
890
|
|
|
845
891
|
def set_published(
|
|
846
|
-
self,
|
|
892
|
+
self,
|
|
893
|
+
judgment_uri: DocumentURIString,
|
|
894
|
+
published: bool,
|
|
847
895
|
) -> requests.Response:
|
|
848
896
|
return self.set_boolean_property(judgment_uri, "published", published)
|
|
849
897
|
|
|
@@ -870,7 +918,9 @@ class MarklogicApiClient:
|
|
|
870
918
|
return self._send_to_eval(vars, "delete_judgment.xqy")
|
|
871
919
|
|
|
872
920
|
def copy_document(
|
|
873
|
-
self,
|
|
921
|
+
self,
|
|
922
|
+
old: DocumentURIString,
|
|
923
|
+
new: DocumentURIString,
|
|
874
924
|
) -> requests.Response:
|
|
875
925
|
old_uri = self._format_uri_for_marklogic(old)
|
|
876
926
|
new_uri = self._format_uri_for_marklogic(new)
|
|
@@ -908,13 +958,11 @@ class MarklogicApiClient:
|
|
|
908
958
|
check_privilege = self.user_has_privilege(
|
|
909
959
|
username,
|
|
910
960
|
MarkLogicPrivilegeURIString(
|
|
911
|
-
"https://caselaw.nationalarchives.gov.uk/custom/privileges/can-view-unpublished-documents"
|
|
961
|
+
"https://caselaw.nationalarchives.gov.uk/custom/privileges/can-view-unpublished-documents",
|
|
912
962
|
),
|
|
913
963
|
"execute",
|
|
914
964
|
)
|
|
915
|
-
return (
|
|
916
|
-
get_single_string_from_marklogic_response(check_privilege).lower() == "true"
|
|
917
|
-
)
|
|
965
|
+
return get_single_string_from_marklogic_response(check_privilege).lower() == "true"
|
|
918
966
|
|
|
919
967
|
def user_has_role(self, username: str, role: str) -> requests.Response:
|
|
920
968
|
vars: query_dicts.UserHasRoleDict = {
|
|
@@ -946,22 +994,20 @@ class MarklogicApiClient:
|
|
|
946
994
|
|
|
947
995
|
def verify_show_unpublished(self, show_unpublished: bool) -> bool:
|
|
948
996
|
if show_unpublished and not self.user_can_view_unpublished_judgments(
|
|
949
|
-
self.username
|
|
997
|
+
self.username,
|
|
950
998
|
):
|
|
951
999
|
# The user cannot view unpublished judgments but is requesting to see them
|
|
952
1000
|
logging.warning(
|
|
953
|
-
f"User {self.username} is attempting to view unpublished judgments but does not have that privilege."
|
|
1001
|
+
f"User {self.username} is attempting to view unpublished judgments but does not have that privilege.",
|
|
954
1002
|
)
|
|
955
1003
|
return False
|
|
956
1004
|
return show_unpublished
|
|
957
1005
|
|
|
958
1006
|
def get_properties_for_search_results(
|
|
959
|
-
self,
|
|
1007
|
+
self,
|
|
1008
|
+
judgment_uris: list[DocumentURIString],
|
|
960
1009
|
) -> str:
|
|
961
|
-
uris = [
|
|
962
|
-
self._format_uri_for_marklogic(judgment_uri)
|
|
963
|
-
for judgment_uri in judgment_uris
|
|
964
|
-
]
|
|
1010
|
+
uris = [self._format_uri_for_marklogic(judgment_uri) for judgment_uri in judgment_uris]
|
|
965
1011
|
vars: query_dicts.GetPropertiesForSearchResultsDict = {"uris": uris}
|
|
966
1012
|
response = self._send_to_eval(vars, "get_properties_for_search_results.xqy")
|
|
967
1013
|
return get_single_string_from_marklogic_response(response)
|
|
@@ -971,7 +1017,8 @@ class MarklogicApiClient:
|
|
|
971
1017
|
return get_single_string_from_marklogic_response(response)
|
|
972
1018
|
|
|
973
1019
|
def search_judgments_and_decode_response(
|
|
974
|
-
self,
|
|
1020
|
+
self,
|
|
1021
|
+
search_parameters: SearchParameters,
|
|
975
1022
|
) -> str:
|
|
976
1023
|
search_parameters.collections = [DOCUMENT_COLLECTION_URI_JUDGMENT]
|
|
977
1024
|
return self.search_and_decode_response(search_parameters)
|
|
@@ -994,8 +1041,8 @@ class MarklogicApiClient:
|
|
|
994
1041
|
row."""
|
|
995
1042
|
results: list[list[Any]] = json.loads(
|
|
996
1043
|
get_single_string_from_marklogic_response(
|
|
997
|
-
self._send_to_eval({}, "get_combined_stats_table.xqy")
|
|
998
|
-
)
|
|
1044
|
+
self._send_to_eval({}, "get_combined_stats_table.xqy"),
|
|
1045
|
+
),
|
|
999
1046
|
)
|
|
1000
1047
|
|
|
1001
1048
|
return results
|
|
@@ -1009,8 +1056,8 @@ class MarklogicApiClient:
|
|
|
1009
1056
|
self._send_to_eval(
|
|
1010
1057
|
{},
|
|
1011
1058
|
"get_highest_enrichment_version.xqy",
|
|
1012
|
-
)
|
|
1013
|
-
)
|
|
1059
|
+
),
|
|
1060
|
+
),
|
|
1014
1061
|
)
|
|
1015
1062
|
|
|
1016
1063
|
return (int(table[1][1]), int(table[1][2]))
|
|
@@ -1032,8 +1079,8 @@ class MarklogicApiClient:
|
|
|
1032
1079
|
self._send_to_eval(
|
|
1033
1080
|
vars,
|
|
1034
1081
|
"get_pending_enrichment_for_version.xqy",
|
|
1035
|
-
)
|
|
1036
|
-
)
|
|
1082
|
+
),
|
|
1083
|
+
),
|
|
1037
1084
|
)
|
|
1038
1085
|
|
|
1039
1086
|
return results
|
|
@@ -1045,14 +1092,15 @@ class MarklogicApiClient:
|
|
|
1045
1092
|
self._send_to_eval(
|
|
1046
1093
|
{},
|
|
1047
1094
|
"get_highest_parser_version.xqy",
|
|
1048
|
-
)
|
|
1049
|
-
)
|
|
1095
|
+
),
|
|
1096
|
+
),
|
|
1050
1097
|
)
|
|
1051
1098
|
|
|
1052
1099
|
return (int(table[1][1]), int(table[1][2]))
|
|
1053
1100
|
|
|
1054
1101
|
def get_pending_parse_for_version(
|
|
1055
|
-
self,
|
|
1102
|
+
self,
|
|
1103
|
+
target_version: tuple[int, int],
|
|
1056
1104
|
) -> list[list[Any]]:
|
|
1057
1105
|
"""Retrieve documents which are not yet parsed with a given version."""
|
|
1058
1106
|
vars: query_dicts.GetPendingParseForVersionDict = {
|
|
@@ -1064,8 +1112,8 @@ class MarklogicApiClient:
|
|
|
1064
1112
|
self._send_to_eval(
|
|
1065
1113
|
vars,
|
|
1066
1114
|
"get_pending_parse_for_version.xqy",
|
|
1067
|
-
)
|
|
1068
|
-
)
|
|
1115
|
+
),
|
|
1116
|
+
),
|
|
1069
1117
|
)
|
|
1070
1118
|
|
|
1071
1119
|
return results
|
|
@@ -79,12 +79,12 @@ class VersionAnnotation:
|
|
|
79
79
|
"""
|
|
80
80
|
if not self.calling_function:
|
|
81
81
|
raise AttributeError(
|
|
82
|
-
"The name of the calling function has not been set; use set_calling_function()"
|
|
82
|
+
"The name of the calling function has not been set; use set_calling_function()",
|
|
83
83
|
)
|
|
84
84
|
|
|
85
85
|
if not self.calling_agent:
|
|
86
86
|
raise AttributeError(
|
|
87
|
-
"The name of the calling agent has not been set; use set_calling_agent()"
|
|
87
|
+
"The name of the calling agent has not been set; use set_calling_agent()",
|
|
88
88
|
)
|
|
89
89
|
|
|
90
90
|
annotation_data: AnnotationDataDict = {
|
|
@@ -6,7 +6,8 @@ from caselawclient.search_parameters import SearchParameters
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def search_judgments_and_parse_response(
|
|
9
|
-
api_client: MarklogicApiClient,
|
|
9
|
+
api_client: MarklogicApiClient,
|
|
10
|
+
search_parameters: SearchParameters,
|
|
10
11
|
) -> SearchResponse:
|
|
11
12
|
"""
|
|
12
13
|
Search for judgments using the given search parameters and parse the response into a SearchResponse object.
|
|
@@ -18,14 +19,15 @@ def search_judgments_and_parse_response(
|
|
|
18
19
|
"""
|
|
19
20
|
return SearchResponse(
|
|
20
21
|
etree.fromstring(
|
|
21
|
-
api_client.search_judgments_and_decode_response(search_parameters)
|
|
22
|
+
api_client.search_judgments_and_decode_response(search_parameters),
|
|
22
23
|
),
|
|
23
24
|
api_client,
|
|
24
25
|
)
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
def search_and_parse_response(
|
|
28
|
-
api_client: MarklogicApiClient,
|
|
29
|
+
api_client: MarklogicApiClient,
|
|
30
|
+
search_parameters: SearchParameters,
|
|
29
31
|
) -> SearchResponse:
|
|
30
32
|
"""
|
|
31
33
|
Search using the given search parameters and parse the response into a SearchResponse object.
|
caselawclient/content_hash.py
CHANGED
|
@@ -23,9 +23,7 @@ def get_hashable_text(doc: bytes) -> bytes:
|
|
|
23
23
|
"//akn:meta",
|
|
24
24
|
namespaces={"akn": "http://docs.oasis-open.org/legaldocml/ns/akn/3.0"},
|
|
25
25
|
)
|
|
26
|
-
for
|
|
27
|
-
metadata
|
|
28
|
-
) in metadatas: # there should be no more than one, but handle zero case gracefully
|
|
26
|
+
for metadata in metadatas: # there should be no more than one, but handle zero case gracefully
|
|
29
27
|
metadata.getparent().remove(metadata)
|
|
30
28
|
text = "".join(root.itertext())
|
|
31
29
|
spaceless = re.sub(r"\s", "", text)
|
|
@@ -57,6 +55,6 @@ def validate_content_hash(doc: bytes) -> str:
|
|
|
57
55
|
hash_from_tag = get_hash_from_tag(doc)
|
|
58
56
|
if hash_from_document != hash_from_tag:
|
|
59
57
|
raise InvalidContentHashError(
|
|
60
|
-
f'Hash of existing tag is "{hash_from_tag}" but the hash of the document is "{hash_from_document}"'
|
|
58
|
+
f'Hash of existing tag is "{hash_from_tag}" but the hash of the document is "{hash_from_document}"',
|
|
61
59
|
)
|
|
62
60
|
return hash_from_document
|
caselawclient/errors.py
CHANGED
|
@@ -60,13 +60,12 @@ class MarklogicValidationFailedError(MarklogicAPIError):
|
|
|
60
60
|
|
|
61
61
|
class MarklogicCommunicationError(MarklogicAPIError):
|
|
62
62
|
status_code = 500
|
|
63
|
-
default_message =
|
|
64
|
-
"Something unexpected happened when communicating with the Marklogic server."
|
|
65
|
-
)
|
|
63
|
+
default_message = "Something unexpected happened when communicating with the Marklogic server."
|
|
66
64
|
|
|
67
65
|
|
|
68
66
|
class GatewayTimeoutError(MarklogicAPIError):
|
|
69
67
|
"This will not contain XML, because it is a failure to connect to the Marklogic server."
|
|
68
|
+
|
|
70
69
|
status_code = 504
|
|
71
70
|
default_message = "The gateway to MarkLogic timed out."
|
|
72
71
|
|
|
@@ -74,9 +73,7 @@ class GatewayTimeoutError(MarklogicAPIError):
|
|
|
74
73
|
class InvalidContentHashError(MarklogicAPIError):
|
|
75
74
|
# This error does not come from Marklogic, but is an error raised by this API...
|
|
76
75
|
status_code = 422
|
|
77
|
-
default_message =
|
|
78
|
-
"The content hash in the document did not match the hash of the content"
|
|
79
|
-
)
|
|
76
|
+
default_message = "The content hash in the document did not match the hash of the content"
|
|
80
77
|
|
|
81
78
|
|
|
82
79
|
class DocumentNotFoundError(MarklogicAPIError):
|