ds-caselaw-marklogic-api-client 41.1.0__tar.gz → 43.1.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.
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/PKG-INFO +3 -2
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/pyproject.toml +9 -8
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/Client.py +3 -1
- ds_caselaw_marklogic_api_client-43.1.0/src/caselawclient/client_helpers/__init__.py +35 -0
- ds_caselaw_marklogic_api_client-43.1.0/src/caselawclient/managers/merge/__init__.py +51 -0
- ds_caselaw_marklogic_api_client-43.1.0/src/caselawclient/managers/merge/checks.py +79 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/documents/__init__.py +8 -0
- ds_caselaw_marklogic_api_client-41.1.0/src/caselawclient/client_helpers/__init__.py → ds_caselaw_marklogic_api_client-43.1.0/src/caselawclient/models/documents/versions.py +0 -35
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/utilities/aws.py +20 -0
- ds_caselaw_marklogic_api_client-43.1.0/src/caselawclient/py.typed +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/search_parameters.py +4 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/types.py +36 -6
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/check_content_hash_unique_by_uri.xqy +7 -1
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/LICENSE.md +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/README.md +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/__init__.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/client_helpers/search_helpers.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/content_hash.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/errors.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/factories.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/identifier_resolution.py +0 -0
- /ds_caselaw_marklogic_api_client-41.1.0/src/caselawclient/py.typed → /ds_caselaw_marklogic_api_client-43.1.0/src/caselawclient/managers/__init__.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/__init__.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/documents/body.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/documents/comparison.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/documents/exceptions.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/documents/statuses.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/documents/transforms/html.xsl +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/documents/xml.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/identifiers/__init__.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/identifiers/collection.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/identifiers/exceptions.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/identifiers/fclid.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/identifiers/neutral_citation.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/identifiers/press_summary_ncn.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/identifiers/unpacker.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/judgments.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/neutral_citation_mixin.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/parser_logs.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/press_summaries.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/utilities/__init__.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/utilities/dates.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/models/utilities/move.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/responses/__init__.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/responses/search_response.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/responses/search_result.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/responses/xsl/search_match.xsl +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xml_helpers.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/break_judgment_checkout.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/checkin_judgment.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/checkout_judgment.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/copy_document.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/delete_judgment.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/document_collections.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/document_exists.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/get_combined_stats_table.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/get_components_for_document.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/get_highest_enrichment_version.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/get_highest_parser_version.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/get_judgment.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/get_judgment_checkout_status.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/get_judgment_version.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/get_last_modified.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/get_missing_fclid.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/get_next_document_sequence_number.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/get_pending_enrichment_for_version.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/get_pending_parse_for_version.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/get_properties_for_search_results.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/get_property.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/get_property_as_node.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/get_recently_enriched.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/get_recently_parsed.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/get_version_annotation.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/get_version_created.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/insert_document.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/list_judgment_versions.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/resolve_from_identifier_slug.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/resolve_from_identifier_value.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/set_boolean_property.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/set_datetime_property.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/set_metadata_citation.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/set_metadata_court.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/set_metadata_jurisdiction.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/set_metadata_name.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/set_metadata_this_uri.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/set_metadata_work_expression_date.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/set_property.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/set_property_as_node.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/update_document.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/update_locked_judgment.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/user_has_privilege.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/user_has_role.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/validate_all_documents.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/validate_document.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/xslt.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery/xslt_transform.xqy +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xquery_type_dicts.py +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xslt/modify_xml_live.xsl +0 -0
- {ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/src/caselawclient/xslt/sample.xsl +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: ds-caselaw-marklogic-api-client
|
|
3
|
-
Version:
|
|
3
|
+
Version: 43.1.0
|
|
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
|
|
@@ -9,7 +9,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
9
9
|
Classifier: Programming Language :: Python :: 3.12
|
|
10
10
|
Classifier: Programming Language :: Python :: 3.13
|
|
11
11
|
Requires-Dist: boto3 (>=1.26.112,<2.0.0)
|
|
12
|
-
Requires-Dist: certifi (>=2025.
|
|
12
|
+
Requires-Dist: certifi (>=2025.10.5,<2025.11.0)
|
|
13
13
|
Requires-Dist: charset-normalizer (>=3.0.0,<4.0.0)
|
|
14
14
|
Requires-Dist: defusedxml (>=0.7.1,<0.8.0)
|
|
15
15
|
Requires-Dist: django-environ (>=0.12.0)
|
|
@@ -19,6 +19,7 @@ Requires-Dist: lxml (>=6.0.0,<7.0.0)
|
|
|
19
19
|
Requires-Dist: memoization (>=0.4.0,<0.5.0)
|
|
20
20
|
Requires-Dist: mypy-boto3-s3 (>=1.26.104,<2.0.0)
|
|
21
21
|
Requires-Dist: mypy-boto3-sns (>=1.26.69,<2.0.0)
|
|
22
|
+
Requires-Dist: pydantic (>=2.12.3,<3.0.0)
|
|
22
23
|
Requires-Dist: python-dateutil (>=2.9.0-post.0,<3.0.0)
|
|
23
24
|
Requires-Dist: pytz (>2024)
|
|
24
25
|
Requires-Dist: requests (>=2.28.2,<3.0.0)
|
{ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/pyproject.toml
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "ds-caselaw-marklogic-api-client"
|
|
3
|
-
version = "
|
|
3
|
+
version = "43.1.0"
|
|
4
4
|
description = "An API client for interacting with the underlying data in Find Caselaw."
|
|
5
5
|
authors = ["The National Archives"]
|
|
6
6
|
homepage = "https://github.com/nationalarchives/ds-caselaw-custom-api-client"
|
|
@@ -12,7 +12,7 @@ packages = [
|
|
|
12
12
|
|
|
13
13
|
[tool.poetry.dependencies]
|
|
14
14
|
python = "^3.12.0"
|
|
15
|
-
certifi = ">=2025.
|
|
15
|
+
certifi = ">=2025.10.5,<2025.11.0"
|
|
16
16
|
charset-normalizer = "^3.0.0"
|
|
17
17
|
django-environ = ">=0.12.0"
|
|
18
18
|
idna = "^3.4"
|
|
@@ -30,22 +30,23 @@ python-dateutil = "^2.9.0-post.0"
|
|
|
30
30
|
saxonche = "^12.5.0"
|
|
31
31
|
sqids = "^0.5.0"
|
|
32
32
|
defusedxml = "^0.7.1"
|
|
33
|
+
pydantic = "^2.12.3"
|
|
33
34
|
|
|
34
35
|
[tool.poetry.group.dev.dependencies]
|
|
35
|
-
coverage = "7.
|
|
36
|
+
coverage = "7.11.0"
|
|
36
37
|
pytest = "8.4.2"
|
|
37
|
-
pytest-cov = "
|
|
38
|
-
beautifulsoup4 = "4.
|
|
38
|
+
pytest-cov = "7.0.0"
|
|
39
|
+
beautifulsoup4 = "4.14.2"
|
|
39
40
|
responses = "0.25.8"
|
|
40
|
-
python-dotenv = "1.
|
|
41
|
+
python-dotenv = "1.2.1"
|
|
41
42
|
time-machine = "2.19.0"
|
|
42
|
-
moto = {version = "5.1.
|
|
43
|
+
moto = {version = "5.1.16", extras = ["all"]}
|
|
43
44
|
|
|
44
45
|
[tool.poetry.group.docs]
|
|
45
46
|
optional = true
|
|
46
47
|
|
|
47
48
|
[tool.poetry.group.docs.dependencies]
|
|
48
|
-
pdoc = "^
|
|
49
|
+
pdoc = "^16.0.0"
|
|
49
50
|
|
|
50
51
|
|
|
51
52
|
[tool.commitizen]
|
|
@@ -21,13 +21,13 @@ from requests.structures import CaseInsensitiveDict
|
|
|
21
21
|
from requests_toolbelt.multipart import decoder
|
|
22
22
|
|
|
23
23
|
from caselawclient import xquery_type_dicts as query_dicts
|
|
24
|
-
from caselawclient.client_helpers import VersionAnnotation
|
|
25
24
|
from caselawclient.identifier_resolution import IdentifierResolutions
|
|
26
25
|
from caselawclient.models.documents import (
|
|
27
26
|
DOCUMENT_COLLECTION_URI_JUDGMENT,
|
|
28
27
|
DOCUMENT_COLLECTION_URI_PRESS_SUMMARY,
|
|
29
28
|
Document,
|
|
30
29
|
)
|
|
30
|
+
from caselawclient.models.documents.versions import VersionAnnotation
|
|
31
31
|
from caselawclient.models.judgments import Judgment
|
|
32
32
|
from caselawclient.models.press_summaries import PressSummary
|
|
33
33
|
from caselawclient.models.utilities import move
|
|
@@ -802,6 +802,8 @@ class MarklogicApiClient:
|
|
|
802
802
|
:param judge:
|
|
803
803
|
:param party:
|
|
804
804
|
:param neutral_citation:
|
|
805
|
+
:param document_name:
|
|
806
|
+
:param consignment_number:
|
|
805
807
|
:param specific_keyword:
|
|
806
808
|
:param order:
|
|
807
809
|
:param date_from:
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from lxml import etree
|
|
2
|
+
|
|
3
|
+
from caselawclient.xml_helpers import DEFAULT_NAMESPACES
|
|
4
|
+
|
|
5
|
+
from ..models.documents import Document
|
|
6
|
+
from ..models.judgments import Judgment
|
|
7
|
+
from ..models.parser_logs import ParserLog
|
|
8
|
+
from ..models.press_summaries import PressSummary
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CannotDetermineDocumentType(Exception):
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def get_document_type_class(xml: bytes) -> type[Document]:
|
|
16
|
+
"""Attempt to get the type of the document based on the top-level structure of the XML document."""
|
|
17
|
+
|
|
18
|
+
node = etree.fromstring(xml)
|
|
19
|
+
|
|
20
|
+
# If the main node is `<judgment>`, it's a judgment
|
|
21
|
+
if node.xpath("/akn:akomaNtoso/akn:judgment", namespaces=DEFAULT_NAMESPACES):
|
|
22
|
+
return Judgment
|
|
23
|
+
|
|
24
|
+
# If the main node is `<doc name='pressSummary'>`, it's a press summary
|
|
25
|
+
if node.xpath("/akn:akomaNtoso/akn:doc[@name='pressSummary']", namespaces=DEFAULT_NAMESPACES):
|
|
26
|
+
return PressSummary
|
|
27
|
+
|
|
28
|
+
# If the document is a parser error with a root element of `error`, it's not of a special type.
|
|
29
|
+
if node.xpath("/error", namespaces=DEFAULT_NAMESPACES):
|
|
30
|
+
return ParserLog
|
|
31
|
+
|
|
32
|
+
# Otherwise, we don't know for sure. Fail out.
|
|
33
|
+
raise CannotDetermineDocumentType(
|
|
34
|
+
"Unable to determine the Document type by its XML",
|
|
35
|
+
)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import caselawclient.managers.merge.checks as checks
|
|
2
|
+
from caselawclient.models.documents import Document
|
|
3
|
+
from caselawclient.types import SuccessFailureMessageTuple
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def _combine_list_of_successfailure_results(
|
|
7
|
+
validations: list[SuccessFailureMessageTuple],
|
|
8
|
+
) -> SuccessFailureMessageTuple:
|
|
9
|
+
"""Given a list of SuccessFailureMessageTuples, combine the success/failure states and any messages into a single new object representing the overall success/failure state."""
|
|
10
|
+
success = True
|
|
11
|
+
messages: list[str] = []
|
|
12
|
+
|
|
13
|
+
for validation in validations:
|
|
14
|
+
if validation.success is False:
|
|
15
|
+
success = False
|
|
16
|
+
|
|
17
|
+
messages += validation.messages
|
|
18
|
+
|
|
19
|
+
return SuccessFailureMessageTuple(success, messages)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class MergeManager:
|
|
23
|
+
@classmethod
|
|
24
|
+
def check_document_is_safe_as_merge_source(cls, source_document: Document) -> SuccessFailureMessageTuple:
|
|
25
|
+
"""
|
|
26
|
+
Is the given document safe to be considered as a merge source?
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
return _combine_list_of_successfailure_results(
|
|
30
|
+
[
|
|
31
|
+
checks.check_document_is_not_version(source_document),
|
|
32
|
+
checks.check_document_has_only_one_version(source_document),
|
|
33
|
+
checks.check_document_has_never_been_published(source_document),
|
|
34
|
+
checks.check_document_is_safe_to_delete(source_document),
|
|
35
|
+
]
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
@classmethod
|
|
39
|
+
def check_source_document_is_safe_to_merge_into_target(
|
|
40
|
+
cls, source_document: Document, target_document: Document
|
|
41
|
+
) -> SuccessFailureMessageTuple:
|
|
42
|
+
"""Is the given source document safe to merge into a given target?"""
|
|
43
|
+
|
|
44
|
+
return _combine_list_of_successfailure_results(
|
|
45
|
+
[
|
|
46
|
+
checks.check_documents_are_not_same_document(source_document, target_document),
|
|
47
|
+
checks.check_document_is_not_version(target_document),
|
|
48
|
+
checks.check_documents_are_same_type(source_document, target_document),
|
|
49
|
+
checks.check_source_document_is_newer_than_target(source_document, target_document),
|
|
50
|
+
]
|
|
51
|
+
)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from caselawclient.models.documents import Document
|
|
2
|
+
from caselawclient.types import SuccessFailureMessageTuple
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def check_document_is_not_version(document: Document) -> SuccessFailureMessageTuple:
|
|
6
|
+
"""Check that the document URI isn't a specific version"""
|
|
7
|
+
if document.is_version:
|
|
8
|
+
return SuccessFailureMessageTuple(
|
|
9
|
+
False,
|
|
10
|
+
["This document is a specific version, and cannot be used as a merge source"],
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
return SuccessFailureMessageTuple(True, [])
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def check_document_has_only_one_version(document: Document) -> SuccessFailureMessageTuple:
|
|
17
|
+
"""Make sure the document has exactly one version."""
|
|
18
|
+
if len(document.versions) > 1:
|
|
19
|
+
return SuccessFailureMessageTuple(
|
|
20
|
+
False,
|
|
21
|
+
["This document has more than one version"],
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
return SuccessFailureMessageTuple(True, [])
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def check_document_has_never_been_published(document: Document) -> SuccessFailureMessageTuple:
|
|
28
|
+
"""Make sure the document has never been published."""
|
|
29
|
+
if document.has_ever_been_published:
|
|
30
|
+
return SuccessFailureMessageTuple(
|
|
31
|
+
False,
|
|
32
|
+
["This document has previously been published"],
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
return SuccessFailureMessageTuple(True, [])
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def check_document_is_safe_to_delete(document: Document) -> SuccessFailureMessageTuple:
|
|
39
|
+
"""Make sure the document is safe to delete."""
|
|
40
|
+
if not document.safe_to_delete:
|
|
41
|
+
return SuccessFailureMessageTuple(
|
|
42
|
+
False,
|
|
43
|
+
["This document cannot be deleted because it is published"],
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
return SuccessFailureMessageTuple(True, [])
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def check_documents_are_not_same_document(document_one: Document, document_two: Document) -> SuccessFailureMessageTuple:
|
|
50
|
+
"""Check that two documents aren't actually the same"""
|
|
51
|
+
if document_one.uri == document_two.uri:
|
|
52
|
+
return SuccessFailureMessageTuple(
|
|
53
|
+
False,
|
|
54
|
+
["You cannot merge a document with itself"],
|
|
55
|
+
)
|
|
56
|
+
return SuccessFailureMessageTuple(True, [])
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def check_documents_are_same_type(document_one: Document, document_two: Document) -> SuccessFailureMessageTuple:
|
|
60
|
+
"""Check to see if this document is the same type as a target document."""
|
|
61
|
+
if type(document_one) is not type(document_two):
|
|
62
|
+
return SuccessFailureMessageTuple(
|
|
63
|
+
False,
|
|
64
|
+
[
|
|
65
|
+
f"The type of {document_one.uri} ({type(document_one).document_noun}) does not match the type of {document_two.uri} ({type(document_two).document_noun})"
|
|
66
|
+
],
|
|
67
|
+
)
|
|
68
|
+
return SuccessFailureMessageTuple(True, [])
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def check_source_document_is_newer_than_target(
|
|
72
|
+
source_document: Document, target_document: Document
|
|
73
|
+
) -> SuccessFailureMessageTuple:
|
|
74
|
+
"""Check to see if the created datetime of the latest version of this document is newer than the created datetime of the latest version of a target document."""
|
|
75
|
+
if source_document.version_created_datetime < target_document.version_created_datetime:
|
|
76
|
+
return SuccessFailureMessageTuple(
|
|
77
|
+
False, [f"The document at {source_document.uri} is older than the latest version of {target_document.uri}"]
|
|
78
|
+
)
|
|
79
|
+
return SuccessFailureMessageTuple(True, [])
|
|
@@ -7,6 +7,7 @@ from typing import TYPE_CHECKING, Any, Optional
|
|
|
7
7
|
from ds_caselaw_utils import courts
|
|
8
8
|
from ds_caselaw_utils.courts import CourtNotFoundException
|
|
9
9
|
from ds_caselaw_utils.types import NeutralCitationString
|
|
10
|
+
from pydantic import TypeAdapter
|
|
10
11
|
from requests_toolbelt.multipart import decoder
|
|
11
12
|
|
|
12
13
|
import caselawclient.models.documents.comparison as comparison
|
|
@@ -16,6 +17,7 @@ from caselawclient.errors import (
|
|
|
16
17
|
OnlySupportedOnVersion,
|
|
17
18
|
)
|
|
18
19
|
from caselawclient.identifier_resolution import IdentifierResolutions
|
|
20
|
+
from caselawclient.models.documents.versions import AnnotationDataDict
|
|
19
21
|
from caselawclient.models.identifiers import Identifier
|
|
20
22
|
from caselawclient.models.identifiers.exceptions import IdentifierValidationException
|
|
21
23
|
from caselawclient.models.identifiers.fclid import FindCaseLawIdentifier, FindCaseLawIdentifierSchema
|
|
@@ -357,6 +359,12 @@ class Document:
|
|
|
357
359
|
def annotation(self) -> str:
|
|
358
360
|
return self.api_client.get_version_annotation(self.uri)
|
|
359
361
|
|
|
362
|
+
@cached_property
|
|
363
|
+
def structured_annotation(self) -> AnnotationDataDict:
|
|
364
|
+
annotation_data_dict_loader = TypeAdapter(AnnotationDataDict)
|
|
365
|
+
|
|
366
|
+
return annotation_data_dict_loader.validate_json(self.annotation)
|
|
367
|
+
|
|
360
368
|
@cached_property
|
|
361
369
|
def has_unique_content_hash(self) -> bool:
|
|
362
370
|
"""Check if the content hash of this document is unique compared to all other documents in MarkLogic."""
|
|
@@ -2,20 +2,8 @@ import json
|
|
|
2
2
|
from enum import Enum
|
|
3
3
|
from typing import Any, Optional, TypedDict
|
|
4
4
|
|
|
5
|
-
from lxml import etree
|
|
6
5
|
from typing_extensions import NotRequired
|
|
7
6
|
|
|
8
|
-
from caselawclient.xml_helpers import DEFAULT_NAMESPACES
|
|
9
|
-
|
|
10
|
-
from ..models.documents import Document
|
|
11
|
-
from ..models.judgments import Judgment
|
|
12
|
-
from ..models.parser_logs import ParserLog
|
|
13
|
-
from ..models.press_summaries import PressSummary
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class CannotDetermineDocumentType(Exception):
|
|
17
|
-
pass
|
|
18
|
-
|
|
19
7
|
|
|
20
8
|
class AnnotationDataDict(TypedDict):
|
|
21
9
|
type: str
|
|
@@ -124,26 +112,3 @@ class VersionAnnotation:
|
|
|
124
112
|
|
|
125
113
|
def __str__(self) -> str:
|
|
126
114
|
return self.as_json
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
def get_document_type_class(xml: bytes) -> type[Document]:
|
|
130
|
-
"""Attempt to get the type of the document based on the top-level structure of the XML document."""
|
|
131
|
-
|
|
132
|
-
node = etree.fromstring(xml)
|
|
133
|
-
|
|
134
|
-
# If the main node is `<judgment>`, it's a judgment
|
|
135
|
-
if node.xpath("/akn:akomaNtoso/akn:judgment", namespaces=DEFAULT_NAMESPACES):
|
|
136
|
-
return Judgment
|
|
137
|
-
|
|
138
|
-
# If the main node is `<doc name='pressSummary'>`, it's a press summary
|
|
139
|
-
if node.xpath("/akn:akomaNtoso/akn:doc[@name='pressSummary']", namespaces=DEFAULT_NAMESPACES):
|
|
140
|
-
return PressSummary
|
|
141
|
-
|
|
142
|
-
# If the document is a parser error with a root element of `error`, it's not of a special type.
|
|
143
|
-
if node.xpath("/error", namespaces=DEFAULT_NAMESPACES):
|
|
144
|
-
return ParserLog
|
|
145
|
-
|
|
146
|
-
# Otherwise, we don't know for sure. Fail out.
|
|
147
|
-
raise CannotDetermineDocumentType(
|
|
148
|
-
"Unable to determine the Document type by its XML",
|
|
149
|
-
)
|
|
@@ -231,6 +231,26 @@ def copy_assets(old_uri: DocumentURIString, new_uri: DocumentURIString) -> None:
|
|
|
231
231
|
)
|
|
232
232
|
|
|
233
233
|
|
|
234
|
+
def are_unpublished_assets_clean(uri: DocumentURIString) -> bool:
|
|
235
|
+
"""Returns true if all non-tar.gz assets in the relevant S3 bucket have been cleaned
|
|
236
|
+
(they have a DOCUMENT_PROCESSOR_VERSION tag)
|
|
237
|
+
Note: if there are no assets, then this returns true."""
|
|
238
|
+
client = create_s3_client()
|
|
239
|
+
bucket = env("PRIVATE_ASSET_BUCKET")
|
|
240
|
+
response = client.list_objects(Bucket=bucket, Prefix=uri_for_s3(uri))
|
|
241
|
+
for result in response.get("Contents", []):
|
|
242
|
+
file_key = str(result["Key"])
|
|
243
|
+
# ignore original tar.gz files
|
|
244
|
+
if file_key.endswith(".tar.gz"):
|
|
245
|
+
continue
|
|
246
|
+
|
|
247
|
+
# check if assets are tagged as being processed by S3
|
|
248
|
+
tag_response = client.get_object_tagging(Bucket=bucket, Key=file_key)
|
|
249
|
+
if not (any(tag["Key"] == "DOCUMENT_PROCESSOR_VERSION" for tag in tag_response["TagSet"])):
|
|
250
|
+
return False
|
|
251
|
+
return True
|
|
252
|
+
|
|
253
|
+
|
|
234
254
|
def build_new_key(old_key: str, new_uri: DocumentURIString) -> str:
|
|
235
255
|
"""Ensure that DOCX and PDF filenames are modified to reflect their new home
|
|
236
256
|
as we get the name of the new S3 path"""
|
|
File without changes
|
|
@@ -15,6 +15,8 @@ class SearchParameters:
|
|
|
15
15
|
judge: Optional[str] = None
|
|
16
16
|
party: Optional[str] = None
|
|
17
17
|
neutral_citation: Optional[str] = None
|
|
18
|
+
document_name: Optional[str] = None
|
|
19
|
+
consignment_number: Optional[str] = None
|
|
18
20
|
specific_keyword: Optional[str] = None
|
|
19
21
|
order: Optional[str] = None
|
|
20
22
|
date_from: Optional[str] = None
|
|
@@ -39,6 +41,8 @@ class SearchParameters:
|
|
|
39
41
|
"q": str(self.query or ""),
|
|
40
42
|
"party": str(self.party or ""),
|
|
41
43
|
"neutral_citation": str(self.neutral_citation or ""),
|
|
44
|
+
"document_name": str(self.document_name or ""),
|
|
45
|
+
"consignment_number": str(self.consignment_number or ""),
|
|
42
46
|
"specific_keyword": str(self.specific_keyword or ""),
|
|
43
47
|
"order": str(self.order or ""),
|
|
44
48
|
"from": str(self.date_from or ""),
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from dataclasses import dataclass, field
|
|
2
|
-
from typing import NamedTuple
|
|
3
2
|
|
|
4
3
|
|
|
5
4
|
@dataclass
|
|
@@ -70,9 +69,40 @@ class DocumentIdentifierValue(str):
|
|
|
70
69
|
pass
|
|
71
70
|
|
|
72
71
|
|
|
73
|
-
SuccessFailureMessageTuple
|
|
74
|
-
"""
|
|
75
|
-
|
|
72
|
+
class SuccessFailureMessageTuple(tuple[bool, list[str]]):
|
|
73
|
+
"""
|
|
74
|
+
Return whether an operation has succeeded or failed
|
|
75
|
+
(and optionally a list of messages associated with that operation).
|
|
76
|
+
Typically the messages will be exposed to the end-user.
|
|
77
|
+
Use only where a failure is a routine event (such as during validation).
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
def __new__(cls, success: bool, messages: list[str]) -> "SuccessFailureMessageTuple":
|
|
81
|
+
return super().__new__(cls, [success, messages])
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def success(self) -> bool:
|
|
85
|
+
return self[0]
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def messages(self) -> list[str]:
|
|
89
|
+
return self[1]
|
|
90
|
+
|
|
91
|
+
def __repr__(self) -> str:
|
|
92
|
+
return f"SuccessFailureMessageTuple({self.success!r}, {self.messages!r})"
|
|
93
|
+
|
|
94
|
+
def __bool__(self) -> bool:
|
|
95
|
+
return self.success
|
|
96
|
+
|
|
97
|
+
def __or__(self, other: "SuccessFailureMessageTuple") -> "SuccessFailureMessageTuple":
|
|
98
|
+
"""Allows us to write combined_tuple = first_tuple | second_tuple"""
|
|
99
|
+
return SuccessFailureMessageTuple(self.success and other.success, self.messages + other.messages)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def SuccessTuple() -> SuccessFailureMessageTuple:
|
|
103
|
+
return SuccessFailureMessageTuple(True, [])
|
|
104
|
+
|
|
76
105
|
|
|
77
|
-
|
|
78
|
-
|
|
106
|
+
def FailureTuple(message: str | list[str]) -> SuccessFailureMessageTuple:
|
|
107
|
+
messages = message if isinstance(message, list) else [message]
|
|
108
|
+
return SuccessFailureMessageTuple(success=False, messages=messages)
|
|
@@ -5,5 +5,11 @@ declare variable $uri as xs:string external;
|
|
|
5
5
|
|
|
6
6
|
let $doc := doc($uri)
|
|
7
7
|
let $hash := $doc//uk:hash/text()
|
|
8
|
-
let $count := count(cts:
|
|
8
|
+
let $count := count(cts:uris(
|
|
9
|
+
(), (),
|
|
10
|
+
cts:and-query((
|
|
11
|
+
cts:element-value-query(xs:QName("uk:hash"), $hash),
|
|
12
|
+
cts:collection-query("http://marklogic.com/collections/dls/latest-version")
|
|
13
|
+
))
|
|
14
|
+
))
|
|
9
15
|
return $count = 1
|
{ds_caselaw_marklogic_api_client-41.1.0 → ds_caselaw_marklogic_api_client-43.1.0}/LICENSE.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|