ds-caselaw-marklogic-api-client 39.1.0__py3-none-any.whl → 39.2.1__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.
- caselawclient/Client.py +10 -4
- caselawclient/__init__.py +25 -2
- caselawclient/models/documents/__init__.py +5 -1
- caselawclient/models/documents/comparison.py +42 -0
- caselawclient/models/identifiers/__init__.py +4 -2
- caselawclient/models/utilities/aws.py +2 -0
- {ds_caselaw_marklogic_api_client-39.1.0.dist-info → ds_caselaw_marklogic_api_client-39.2.1.dist-info}/METADATA +6 -4
- {ds_caselaw_marklogic_api_client-39.1.0.dist-info → ds_caselaw_marklogic_api_client-39.2.1.dist-info}/RECORD +10 -9
- {ds_caselaw_marklogic_api_client-39.1.0.dist-info → ds_caselaw_marklogic_api_client-39.2.1.dist-info}/LICENSE.md +0 -0
- {ds_caselaw_marklogic_api_client-39.1.0.dist-info → ds_caselaw_marklogic_api_client-39.2.1.dist-info}/WHEEL +0 -0
caselawclient/Client.py
CHANGED
|
@@ -56,6 +56,11 @@ from .errors import (
|
|
|
56
56
|
)
|
|
57
57
|
|
|
58
58
|
env = environ.Env()
|
|
59
|
+
|
|
60
|
+
# Requests timeouts: https://requests.readthedocs.io/en/latest/user/advanced/
|
|
61
|
+
CONNECT_TIMEOUT = float(os.environ.get("CONNECT_TIMEOUT", "3.05"))
|
|
62
|
+
READ_TIMEOUT = float(os.environ.get("READ_TIMEOUT", "10.0"))
|
|
63
|
+
|
|
59
64
|
ROOT_DIR = os.path.dirname(os.path.realpath(__file__))
|
|
60
65
|
DEFAULT_XSL_TRANSFORM = "accessible-html.xsl"
|
|
61
66
|
|
|
@@ -170,6 +175,7 @@ class MarklogicApiClient:
|
|
|
170
175
|
error_code_classes: dict[str, Type[MarklogicAPIError]] = {
|
|
171
176
|
"XDMP-DOCNOTFOUND": MarklogicResourceNotFoundError,
|
|
172
177
|
"XDMP-LOCKCONFLICT": MarklogicResourceLockedError,
|
|
178
|
+
"XDMP-LOCKED": MarklogicResourceLockedError,
|
|
173
179
|
"DLS-UNMANAGED": MarklogicResourceUnmanagedError,
|
|
174
180
|
"DLS-NOTCHECKEDOUT": MarklogicResourceNotCheckedOutError,
|
|
175
181
|
"DLS-CHECKOUTCONFLICT": MarklogicCheckoutConflictError,
|
|
@@ -317,11 +323,13 @@ class MarklogicApiClient:
|
|
|
317
323
|
self,
|
|
318
324
|
vars: query_dicts.MarkLogicAPIDict,
|
|
319
325
|
xquery_file_name: str,
|
|
326
|
+
timeout: tuple[float, float] = (CONNECT_TIMEOUT, READ_TIMEOUT),
|
|
320
327
|
) -> requests.Response:
|
|
321
328
|
return self.eval(
|
|
322
329
|
self._xquery_path(xquery_file_name),
|
|
323
330
|
vars=json.dumps(vars),
|
|
324
331
|
accept_header="application/xml",
|
|
332
|
+
timeout=timeout,
|
|
325
333
|
)
|
|
326
334
|
|
|
327
335
|
def _eval_and_decode(
|
|
@@ -724,6 +732,7 @@ class MarklogicApiClient:
|
|
|
724
732
|
xquery_path: str,
|
|
725
733
|
vars: str,
|
|
726
734
|
accept_header: str = "multipart/mixed",
|
|
735
|
+
timeout: tuple[float, float] = (CONNECT_TIMEOUT, READ_TIMEOUT),
|
|
727
736
|
) -> requests.Response:
|
|
728
737
|
headers = {
|
|
729
738
|
"Content-type": "application/x-www-form-urlencoded",
|
|
@@ -743,6 +752,7 @@ class MarklogicApiClient:
|
|
|
743
752
|
url=self._path_to_request_url(path),
|
|
744
753
|
headers=headers,
|
|
745
754
|
data=data,
|
|
755
|
+
timeout=timeout,
|
|
746
756
|
)
|
|
747
757
|
# Raise relevant exception for an erroneous response
|
|
748
758
|
self._raise_for_status(response)
|
|
@@ -1052,10 +1062,6 @@ class MarklogicApiClient:
|
|
|
1052
1062
|
if show_unpublished and not self.user_can_view_unpublished_judgments(
|
|
1053
1063
|
self.username,
|
|
1054
1064
|
):
|
|
1055
|
-
# The user cannot view unpublished judgments but is requesting to see them
|
|
1056
|
-
logging.warning(
|
|
1057
|
-
f"User {self.username} is attempting to view unpublished judgments but does not have that privilege.",
|
|
1058
|
-
)
|
|
1059
1065
|
return False
|
|
1060
1066
|
return show_unpublished
|
|
1061
1067
|
|
caselawclient/__init__.py
CHANGED
|
@@ -1,4 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
if os.getenv("PDOC_DYNAMIC_VERSION") == "1":
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import tomllib
|
|
7
|
+
|
|
8
|
+
pyproject_path = Path(__file__).parent.parent.parent / "pyproject.toml"
|
|
9
|
+
with pyproject_path.open("rb") as f:
|
|
10
|
+
__version__ = tomllib.load(f)["tool"]["poetry"]["version"]
|
|
11
|
+
__pip_version_string__ = f"~={__version__}"
|
|
12
|
+
__poetry_version_string__ = f' = "^{__version__}"'
|
|
13
|
+
|
|
14
|
+
else:
|
|
15
|
+
__pip_version_string__ = ""
|
|
16
|
+
__poetry_version_string__ = ""
|
|
17
|
+
|
|
18
|
+
__doc__ = f"""
|
|
2
19
|
|
|
3
20
|
# Installation
|
|
4
21
|
|
|
@@ -15,7 +32,13 @@ poetry add ds-caselaw-marklogic-api-client
|
|
|
15
32
|
or in your projects `requirements.txt` with:
|
|
16
33
|
|
|
17
34
|
```text
|
|
18
|
-
ds-caselaw-marklogic-api-client
|
|
35
|
+
ds-caselaw-marklogic-api-client{__pip_version_string__}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
or `pyproject.toml` for Poetry with:
|
|
39
|
+
|
|
40
|
+
```text
|
|
41
|
+
ds-caselaw-marklogic-api-client{__poetry_version_string__}
|
|
19
42
|
```
|
|
20
43
|
|
|
21
44
|
# Usage
|
|
@@ -9,6 +9,7 @@ from ds_caselaw_utils.courts import CourtNotFoundException
|
|
|
9
9
|
from ds_caselaw_utils.types import NeutralCitationString
|
|
10
10
|
from requests_toolbelt.multipart import decoder
|
|
11
11
|
|
|
12
|
+
import caselawclient.models.documents.comparison as comparison
|
|
12
13
|
from caselawclient.errors import (
|
|
13
14
|
DocumentNotFoundError,
|
|
14
15
|
NotSupportedOnVersion,
|
|
@@ -421,7 +422,7 @@ class Document:
|
|
|
421
422
|
uri=self.uri,
|
|
422
423
|
status="publish",
|
|
423
424
|
)
|
|
424
|
-
self.enrich()
|
|
425
|
+
self.enrich(accept_failures=True)
|
|
425
426
|
|
|
426
427
|
def unpublish(self) -> None:
|
|
427
428
|
self.api_client.break_checkout(self.uri)
|
|
@@ -583,3 +584,6 @@ class Document:
|
|
|
583
584
|
return self.body.apply_xslt(
|
|
584
585
|
"modify_xml_live.xsl", work_uri=work_uri, expression_uri=expression_uri, manifestation_uri=manifestation_uri
|
|
585
586
|
)
|
|
587
|
+
|
|
588
|
+
def compare_to(self, that_doc: "Document") -> comparison.Comparison:
|
|
589
|
+
return comparison.Comparison(self, that_doc)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from typing import TypedDict
|
|
2
|
+
|
|
3
|
+
import caselawclient.models.documents
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AttributeComparison(TypedDict):
|
|
7
|
+
"""Results from a comparison of one attribute across two documents"""
|
|
8
|
+
|
|
9
|
+
label: str
|
|
10
|
+
this_value: str
|
|
11
|
+
that_value: str
|
|
12
|
+
match: bool
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Comparison(dict[str, AttributeComparison]):
|
|
16
|
+
def __init__(
|
|
17
|
+
self, this_doc: "caselawclient.models.documents.Document", that_doc: "caselawclient.models.documents.Document"
|
|
18
|
+
):
|
|
19
|
+
# court, date, title
|
|
20
|
+
self["court"] = AttributeComparison(
|
|
21
|
+
label="court",
|
|
22
|
+
this_value=this_doc.court,
|
|
23
|
+
that_value=that_doc.court,
|
|
24
|
+
match=this_doc.court == that_doc.court,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
self["date"] = AttributeComparison(
|
|
28
|
+
label="date",
|
|
29
|
+
this_value=this_doc.body.document_date_as_string,
|
|
30
|
+
that_value=that_doc.body.document_date_as_string,
|
|
31
|
+
match=this_doc.body.document_date_as_string == that_doc.body.document_date_as_string,
|
|
32
|
+
)
|
|
33
|
+
self["name"] = AttributeComparison(
|
|
34
|
+
label="name",
|
|
35
|
+
this_value=this_doc.name,
|
|
36
|
+
that_value=that_doc.name,
|
|
37
|
+
match=this_doc.name == that_doc.name,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
def match(self) -> bool:
|
|
41
|
+
"""Is this comparison an exact match across all attributes?"""
|
|
42
|
+
return all(x["match"] for x in self.values())
|
|
@@ -166,8 +166,10 @@ class Identifier(ABC):
|
|
|
166
166
|
"""
|
|
167
167
|
resolutions = [
|
|
168
168
|
resolution
|
|
169
|
-
for resolution in api_client.resolve_from_identifier_value(
|
|
170
|
-
|
|
169
|
+
for resolution in api_client.resolve_from_identifier_value(
|
|
170
|
+
identifier_value=self.value, published_only=False
|
|
171
|
+
)
|
|
172
|
+
if resolution.identifier_namespace == self.schema.namespace and resolution.identifier_uuid != self.uuid
|
|
171
173
|
]
|
|
172
174
|
if len(resolutions) > 0:
|
|
173
175
|
return SuccessFailureMessageTuple(
|
|
@@ -96,6 +96,8 @@ def check_docx_exists(uri: DocumentURIString) -> bool:
|
|
|
96
96
|
except botocore.exceptions.ClientError as e:
|
|
97
97
|
if e.response["Error"]["Code"] == "404":
|
|
98
98
|
return False
|
|
99
|
+
if e.response["Error"]["Code"] == "403":
|
|
100
|
+
e.add_note("403 on reading {s3_key}")
|
|
99
101
|
raise
|
|
100
102
|
|
|
101
103
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: ds-caselaw-marklogic-api-client
|
|
3
|
-
Version: 39.1
|
|
3
|
+
Version: 39.2.1
|
|
4
4
|
Summary: An API client for interacting with the underlying data in Find Caselaw.
|
|
5
5
|
Keywords: national archives,caselaw
|
|
6
6
|
Author: The National Archives
|
|
@@ -11,13 +11,13 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.12
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.13
|
|
13
13
|
Requires-Dist: boto3 (>=1.26.112,<2.0.0)
|
|
14
|
-
Requires-Dist: certifi (>=2025.
|
|
14
|
+
Requires-Dist: certifi (>=2025.8.3,<2025.9.0)
|
|
15
15
|
Requires-Dist: charset-normalizer (>=3.0.0,<4.0.0)
|
|
16
16
|
Requires-Dist: defusedxml (>=0.7.1,<0.8.0)
|
|
17
17
|
Requires-Dist: django-environ (>=0.12.0)
|
|
18
18
|
Requires-Dist: ds-caselaw-utils (>=2.0.0,<3.0.0)
|
|
19
19
|
Requires-Dist: idna (>=3.4,<4.0)
|
|
20
|
-
Requires-Dist: lxml (>=
|
|
20
|
+
Requires-Dist: lxml (>=6.0.0,<7.0.0)
|
|
21
21
|
Requires-Dist: memoization (>=0.4.0,<0.5.0)
|
|
22
22
|
Requires-Dist: mypy-boto3-s3 (>=1.26.104,<2.0.0)
|
|
23
23
|
Requires-Dist: mypy-boto3-sns (>=1.26.69,<2.0.0)
|
|
@@ -37,7 +37,9 @@ This repository is part of the [Find Case Law](https://caselaw.nationalarchives.
|
|
|
37
37
|
|
|
38
38
|
# MarkLogic API Client
|
|
39
39
|
|
|
40
|
-
[](https://pypi.org/project/ds-caselaw-marklogic-api-client/)
|
|
40
|
+
[](https://pypi.org/project/ds-caselaw-marklogic-api-client/)
|
|
41
|
+

|
|
42
|
+

|
|
41
43
|
|
|
42
44
|
This is an API Client for connecting to Marklogic for The National Archive's Caselaw site.
|
|
43
45
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
caselawclient/Client.py,sha256=
|
|
2
|
-
caselawclient/__init__.py,sha256=
|
|
1
|
+
caselawclient/Client.py,sha256=rcdgfEJ5N_Ajryf8CFHBlEWqvRB7J5IxqE1tCcudTqU,45496
|
|
2
|
+
caselawclient/__init__.py,sha256=QZtsOB_GR5XfFnWMJ6E9_fBany-JXFIrQmzs1mD_KVg,1225
|
|
3
3
|
caselawclient/client_helpers/__init__.py,sha256=eucyUXwUqI72TPw-C5zLcHlMu4GtFY507a6lQc03lQY,5053
|
|
4
4
|
caselawclient/client_helpers/search_helpers.py,sha256=R99HyRLeYHgsw2L3DOidEqlKLLvs6Tga5rKTuWQViig,1525
|
|
5
5
|
caselawclient/content_hash.py,sha256=0cPC4OoABq0SC2wYFX9-24DodNigeOqksDxgxQH_hUA,2221
|
|
@@ -7,13 +7,14 @@ caselawclient/errors.py,sha256=JC16fEGq_MRJX-_KFzfINCV2Cqx8o6OWOt3C16rQd84,3142
|
|
|
7
7
|
caselawclient/factories.py,sha256=eGj9TiZpmF3todW-08Ps7bHNMvByHqwEbgujRhvU_Yc,7382
|
|
8
8
|
caselawclient/identifier_resolution.py,sha256=B5I1sD7o7YjzsXMECjbKjgiGLDda5bGhejsJ-lYpTIg,2429
|
|
9
9
|
caselawclient/models/__init__.py,sha256=kd23EUpvaC7aLHdgk8farqKAQEx3lf7RvNT2jEatvlg,68
|
|
10
|
-
caselawclient/models/documents/__init__.py,sha256=
|
|
10
|
+
caselawclient/models/documents/__init__.py,sha256=5hnKWzuj6fXCHf7jGKg_uolI_iKt6yLb9FMl_yWQ84o,21681
|
|
11
11
|
caselawclient/models/documents/body.py,sha256=O1ZTV3KHo-YNi7Syd4oCV1CVSuRF7mcLXojwshyY4jg,6601
|
|
12
|
+
caselawclient/models/documents/comparison.py,sha256=KwFZQByOcYcZKe8csjAntttACKq4BZb28n2VeV5rK54,1355
|
|
12
13
|
caselawclient/models/documents/exceptions.py,sha256=te7PPQTDHjZ9EYVg5pVaiZfF00lMBFy333PHj8_mkC4,443
|
|
13
14
|
caselawclient/models/documents/statuses.py,sha256=Cp4dTQmJOtsU41EJcxy5dV1841pGD2PNWH0VrkDEv4Q,579
|
|
14
15
|
caselawclient/models/documents/transforms/html.xsl,sha256=XyUQLFcJ7_GwthWQ6ShU0bmzrgpl7xDFU-U8VLgOvEs,38258
|
|
15
16
|
caselawclient/models/documents/xml.py,sha256=BVra2VL_0JyImM8GC3wdouu1tApy79C-e2dHvQyrXPE,2195
|
|
16
|
-
caselawclient/models/identifiers/__init__.py,sha256=
|
|
17
|
+
caselawclient/models/identifiers/__init__.py,sha256=bcXiree1FKIlJklWggvS_IKMHMppAjDbadOpxCJx3yw,7727
|
|
17
18
|
caselawclient/models/identifiers/collection.py,sha256=kGlziJiLAqoyd6LaaZ5tsgUf2fD6Y-7fv1It9S4-Otw,7448
|
|
18
19
|
caselawclient/models/identifiers/exceptions.py,sha256=6LVjvx-UOwqkrpxU19ydmrphKNw0rcG5GXwjTFyf8Dk,130
|
|
19
20
|
caselawclient/models/identifiers/fclid.py,sha256=hj8z-VhXFrUHKOY6k_ItPvOakIvbhJ5xEbZ04E2j7t8,1521
|
|
@@ -25,7 +26,7 @@ caselawclient/models/neutral_citation_mixin.py,sha256=jAac3PPuWyPdj9N-n-U_Jfwkbg
|
|
|
25
26
|
caselawclient/models/parser_logs.py,sha256=iOhKTAAi87XQvxz1DHjF2lrqScD19g_c8EjSf0vPdfs,364
|
|
26
27
|
caselawclient/models/press_summaries.py,sha256=rtrYs_3BazUXxdA2oYmIJ6YIAiVlKeyc1aSF9uvkJJU,2196
|
|
27
28
|
caselawclient/models/utilities/__init__.py,sha256=LPhyrQwLKc5tIJUO8Bysn9wCiR6Z6jMMTksjOV4JH9U,1041
|
|
28
|
-
caselawclient/models/utilities/aws.py,sha256=
|
|
29
|
+
caselawclient/models/utilities/aws.py,sha256=_JUoJatfC1m_etT5MDwbCrOHpdqqTRqGCyzzNiW1WRA,8660
|
|
29
30
|
caselawclient/models/utilities/dates.py,sha256=WwORxVjUHM1ZFcBF6Qtwo3Cj0sATsnSECkUZ6ls1N1Q,492
|
|
30
31
|
caselawclient/models/utilities/move.py,sha256=MXdUqkSiyqRb8YKs_66B6ICWn8EWM6DiJV95fuJO1Us,3610
|
|
31
32
|
caselawclient/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -86,7 +87,7 @@ caselawclient/xquery/xslt_transform.xqy,sha256=cccaFiGkCcvSfDv007UriZ3I4ak2nTLP1
|
|
|
86
87
|
caselawclient/xquery_type_dicts.py,sha256=zuyDGTkcN6voOXCm3APXItZ-Ey6tZ2hdZummZWzjl50,6489
|
|
87
88
|
caselawclient/xslt/modify_xml_live.xsl,sha256=gNjwBun2-UzOeeuf0wNjFtN3jXm1yrwqv_KT8r1slXw,2370
|
|
88
89
|
caselawclient/xslt/sample.xsl,sha256=IG-v77stjwqiw25pguh391K-5DTKiX651WqILDZixm0,825
|
|
89
|
-
ds_caselaw_marklogic_api_client-39.1.
|
|
90
|
-
ds_caselaw_marklogic_api_client-39.1.
|
|
91
|
-
ds_caselaw_marklogic_api_client-39.1.
|
|
92
|
-
ds_caselaw_marklogic_api_client-39.1.
|
|
90
|
+
ds_caselaw_marklogic_api_client-39.2.1.dist-info/LICENSE.md,sha256=fGMzyyLuQW-IAXUeDSCrRdsYW536aEWThdbpCjo6ZKg,1108
|
|
91
|
+
ds_caselaw_marklogic_api_client-39.2.1.dist-info/METADATA,sha256=EiKB1ULoiBebeYY-lr9xAJ8UQUpH9K0DdvL1zZK0w0E,4466
|
|
92
|
+
ds_caselaw_marklogic_api_client-39.2.1.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
|
93
|
+
ds_caselaw_marklogic_api_client-39.2.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|