ds-caselaw-marklogic-api-client 29.2.0__tar.gz → 30.0.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.

Potentially problematic release.


This version of ds-caselaw-marklogic-api-client might be problematic. Click here for more details.

Files changed (86) hide show
  1. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/PKG-INFO +1 -1
  2. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/pyproject.toml +1 -1
  3. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/Client.py +27 -4
  4. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/factories.py +2 -1
  5. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/identifier_resolution.py +11 -2
  6. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/models/documents/__init__.py +2 -23
  7. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/models/documents/body.py +31 -23
  8. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/models/documents/exceptions.py +0 -4
  9. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/models/judgments.py +3 -1
  10. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/models/press_summaries.py +2 -1
  11. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/models/utilities/aws.py +2 -5
  12. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/models/utilities/move.py +1 -1
  13. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/responses/search_result.py +1 -1
  14. ds_caselaw_marklogic_api_client-30.0.0/src/caselawclient/types.py +24 -0
  15. ds_caselaw_marklogic_api_client-30.0.0/src/caselawclient/xquery/resolve_from_identifier_value.xqy +17 -0
  16. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery_type_dicts.py +9 -3
  17. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/LICENSE.md +0 -0
  18. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/README.md +0 -0
  19. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/__init__.py +0 -0
  20. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/client_helpers/__init__.py +0 -0
  21. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/client_helpers/search_helpers.py +0 -0
  22. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/content_hash.py +0 -0
  23. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/errors.py +0 -0
  24. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/models/__init__.py +0 -0
  25. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/models/documents/statuses.py +0 -0
  26. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/models/documents/transforms/html.xsl +0 -0
  27. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/models/documents/xml.py +0 -0
  28. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/models/identifiers/__init__.py +0 -0
  29. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/models/identifiers/fclid.py +0 -0
  30. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/models/identifiers/neutral_citation.py +0 -0
  31. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/models/identifiers/press_summary_ncn.py +0 -0
  32. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/models/identifiers/unpacker.py +0 -0
  33. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/models/neutral_citation_mixin.py +0 -0
  34. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/models/utilities/__init__.py +0 -0
  35. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/models/utilities/dates.py +0 -0
  36. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/py.typed +0 -0
  37. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/responses/__init__.py +0 -0
  38. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/responses/search_response.py +0 -0
  39. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/responses/xsl/search_match.xsl +0 -0
  40. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/search_parameters.py +0 -0
  41. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xml_helpers.py +0 -0
  42. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/break_judgment_checkout.xqy +0 -0
  43. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/checkin_judgment.xqy +0 -0
  44. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/checkout_judgment.xqy +0 -0
  45. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/copy_document.xqy +0 -0
  46. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/delete_judgment.xqy +0 -0
  47. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/document_collections.xqy +0 -0
  48. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/document_exists.xqy +0 -0
  49. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/get_combined_stats_table.xqy +0 -0
  50. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/get_components_for_document.xqy +0 -0
  51. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/get_highest_enrichment_version.xqy +0 -0
  52. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/get_highest_parser_version.xqy +0 -0
  53. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/get_judgment.xqy +0 -0
  54. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/get_judgment_checkout_status.xqy +0 -0
  55. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/get_judgment_version.xqy +0 -0
  56. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/get_last_modified.xqy +0 -0
  57. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/get_next_document_sequence_number.xqy +0 -0
  58. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/get_pending_enrichment_for_version.xqy +0 -0
  59. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/get_pending_parse_for_version.xqy +0 -0
  60. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/get_properties_for_search_results.xqy +0 -0
  61. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/get_property.xqy +0 -0
  62. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/get_property_as_node.xqy +0 -0
  63. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/get_recently_enriched.xqy +0 -0
  64. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/get_recently_parsed.xqy +0 -0
  65. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/get_version_annotation.xqy +0 -0
  66. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/get_version_created.xqy +0 -0
  67. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/insert_document.xqy +0 -0
  68. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/list_judgment_versions.xqy +0 -0
  69. /ds_caselaw_marklogic_api_client-29.2.0/src/caselawclient/xquery/resolve_from_identifier.xqy → /ds_caselaw_marklogic_api_client-30.0.0/src/caselawclient/xquery/resolve_from_identifier_slug.xqy +0 -0
  70. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/set_boolean_property.xqy +0 -0
  71. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/set_metadata_citation.xqy +0 -0
  72. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/set_metadata_court.xqy +0 -0
  73. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/set_metadata_jurisdiction.xqy +0 -0
  74. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/set_metadata_name.xqy +0 -0
  75. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/set_metadata_this_uri.xqy +0 -0
  76. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/set_metadata_work_expression_date.xqy +0 -0
  77. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/set_property.xqy +0 -0
  78. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/set_property_as_node.xqy +0 -0
  79. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/update_document.xqy +0 -0
  80. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/update_locked_judgment.xqy +0 -0
  81. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/user_has_privilege.xqy +0 -0
  82. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/user_has_role.xqy +0 -0
  83. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/validate_all_documents.xqy +0 -0
  84. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/validate_document.xqy +0 -0
  85. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/xslt.xqy +0 -0
  86. {ds_caselaw_marklogic_api_client-29.2.0 → ds_caselaw_marklogic_api_client-30.0.0}/src/caselawclient/xquery/xslt_transform.xqy +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ds-caselaw-marklogic-api-client
3
- Version: 29.2.0
3
+ Version: 30.0.0
4
4
  Summary: An API client for interacting with the underlying data in Find Caselaw.
5
5
  Home-page: https://github.com/nationalarchives/ds-caselaw-custom-api-client
6
6
  Keywords: national archives,caselaw
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "ds-caselaw-marklogic-api-client"
3
- version = "29.2.0"
3
+ version = "30.0.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"
@@ -25,12 +25,12 @@ from caselawclient.models.documents import (
25
25
  DOCUMENT_COLLECTION_URI_JUDGMENT,
26
26
  DOCUMENT_COLLECTION_URI_PRESS_SUMMARY,
27
27
  Document,
28
- DocumentURIString,
29
28
  )
30
29
  from caselawclient.models.judgments import Judgment
31
30
  from caselawclient.models.press_summaries import PressSummary
32
31
  from caselawclient.models.utilities import move
33
32
  from caselawclient.search_parameters import SearchParameters
33
+ from caselawclient.types import DocumentURIString
34
34
  from caselawclient.xquery_type_dicts import (
35
35
  MarkLogicDocumentURIString,
36
36
  MarkLogicDocumentVersionURIString,
@@ -1203,17 +1203,40 @@ class MarklogicApiClient:
1203
1203
 
1204
1204
  return results
1205
1205
 
1206
- def resolve_from_identifier(self, identifier_uri: str, published_only: bool = True) -> IdentifierResolutions:
1206
+ def resolve_from_identifier_slug(self, identifier_uri: str, published_only: bool = True) -> IdentifierResolutions:
1207
1207
  """Given a PUI/EUI url, look up the precomputed slug and return the
1208
1208
  MarkLogic document URIs which match that slug. Multiple returns should be anticipated"""
1209
- vars: query_dicts.ResolveFromIdentifierDict = {
1209
+ vars: query_dicts.ResolveFromIdentifierSlugDict = {
1210
1210
  "identifier_uri": DocumentURIString(identifier_uri),
1211
1211
  "published_only": int(published_only),
1212
1212
  }
1213
1213
  raw_results: list[str] = get_multipart_strings_from_marklogic_response(
1214
1214
  self._send_to_eval(
1215
1215
  vars,
1216
- "resolve_from_identifier.xqy",
1216
+ "resolve_from_identifier_slug.xqy",
1217
+ ),
1218
+ )
1219
+ return IdentifierResolutions.from_marklogic_output(raw_results)
1220
+
1221
+ def resolve_from_identifier(self, identifier_uri: str, published_only: bool = True) -> IdentifierResolutions:
1222
+ warnings.warn(
1223
+ "resolve_from_identifier deprecated, use resolve_from_identifier_slug instead", DeprecationWarning
1224
+ )
1225
+ return self.resolve_from_identifier(identifier_uri, published_only)
1226
+
1227
+ def resolve_from_identifier_value(
1228
+ self, identifier_value: str, published_only: bool = True
1229
+ ) -> IdentifierResolutions:
1230
+ """Given a PUI/EUI url, look up the precomputed slug and return the
1231
+ MarkLogic document URIs which match that slug. Multiple returns should be anticipated"""
1232
+ vars: query_dicts.ResolveFromIdentifierValueDict = {
1233
+ "identifier_value": identifier_value,
1234
+ "published_only": int(published_only),
1235
+ }
1236
+ raw_results: list[str] = get_multipart_strings_from_marklogic_response(
1237
+ self._send_to_eval(
1238
+ vars,
1239
+ "resolve_from_identifier_value.xqy",
1217
1240
  ),
1218
1241
  )
1219
1242
  return IdentifierResolutions.from_marklogic_output(raw_results)
@@ -5,11 +5,12 @@ from unittest.mock import Mock
5
5
  from typing_extensions import TypeAlias
6
6
 
7
7
  from caselawclient.Client import MarklogicApiClient
8
- from caselawclient.models.documents import Document, DocumentURIString
8
+ from caselawclient.models.documents import Document
9
9
  from caselawclient.models.documents.body import DocumentBody
10
10
  from caselawclient.models.judgments import Judgment
11
11
  from caselawclient.models.press_summaries import PressSummary
12
12
  from caselawclient.responses.search_result import SearchResult, SearchResultMetadata
13
+ from caselawclient.types import DocumentURIString
13
14
 
14
15
  DEFAULT_DOCUMENT_BODY_XML = "<akomantoso>This is some XML of a judgment.</akomantoso>"
15
16
 
@@ -1,7 +1,9 @@
1
1
  import json
2
2
  from typing import NamedTuple
3
3
 
4
- from caselawclient.models.documents import DocumentURIString
4
+ from caselawclient.models.identifiers import Identifier
5
+ from caselawclient.models.identifiers.unpacker import IDENTIFIER_NAMESPACE_MAP
6
+ from caselawclient.types import DocumentURIString
5
7
  from caselawclient.xquery_type_dicts import MarkLogicDocumentURIString
6
8
 
7
9
 
@@ -12,7 +14,7 @@ class IdentifierResolutions(list["IdentifierResolution"]):
12
14
  MarkLogic returns a list of dictionaries; IdentifierResolution handles a single dictionary
13
15
  which corresponds to a single identifier to MarkLogic document mapping.
14
16
 
15
- see `xquery/resolve_from_identifier.xqy` and `resolve_from_identifier` in `Client.py`
17
+ see `xquery/resolve_from_identifier_slug.xqy` and `resolve_from_identifier` in `Client.py`
16
18
  """
17
19
 
18
20
  @staticmethod
@@ -31,13 +33,20 @@ class IdentifierResolution(NamedTuple):
31
33
  document_uri: MarkLogicDocumentURIString
32
34
  identifier_slug: DocumentURIString
33
35
  document_published: bool
36
+ identifier_value: str
37
+ identifier_namespace: str
38
+ identifier_type: type[Identifier]
34
39
 
35
40
  @staticmethod
36
41
  def from_marklogic_output(raw_row: str) -> "IdentifierResolution":
37
42
  row = json.loads(raw_row)
43
+ identifier_namespace = row["documents.compiled_url_slugs.identifier_namespace"]
38
44
  return IdentifierResolution(
39
45
  identifier_uuid=row["documents.compiled_url_slugs.identifier_uuid"],
40
46
  document_uri=MarkLogicDocumentURIString(row["documents.compiled_url_slugs.document_uri"]),
41
47
  identifier_slug=DocumentURIString(row["documents.compiled_url_slugs.identifier_slug"]),
42
48
  document_published=row["documents.compiled_url_slugs.document_published"] == "true",
49
+ identifier_value=row["documents.compiled_url_slugs.identifier_value"],
50
+ identifier_namespace=identifier_namespace,
51
+ identifier_type=IDENTIFIER_NAMESPACE_MAP[identifier_namespace],
43
52
  )
@@ -30,9 +30,10 @@ from caselawclient.models.utilities.aws import (
30
30
  request_parse,
31
31
  unpublish_documents,
32
32
  )
33
+ from caselawclient.types import DocumentURIString
33
34
 
34
35
  from .body import DocumentBody
35
- from .exceptions import CannotPublishUnpublishableDocument, DocumentNotSafeForDeletion, InvalidDocumentURIException
36
+ from .exceptions import CannotPublishUnpublishableDocument, DocumentNotSafeForDeletion
36
37
  from .statuses import DOCUMENT_STATUS_HOLD, DOCUMENT_STATUS_IN_PROGRESS, DOCUMENT_STATUS_NEW, DOCUMENT_STATUS_PUBLISHED
37
38
 
38
39
  MINIMUM_ENRICHMENT_TIME = datetime.timedelta(minutes=20)
@@ -49,28 +50,6 @@ if TYPE_CHECKING:
49
50
  from caselawclient.Client import MarklogicApiClient
50
51
 
51
52
 
52
- class DocumentURIString(str):
53
- """
54
- This class checks that the string is actually a valid Document URI on creation. It does _not_ manipulate the string.
55
- """
56
-
57
- def __new__(cls, content: str) -> "DocumentURIString":
58
- # Check that the URI doesn't begin or end with a slash
59
- if content[0] == "/" or content[-1] == "/":
60
- raise InvalidDocumentURIException(
61
- f'"{content}" is not a valid document URI; URIs cannot begin or end with slashes.'
62
- )
63
-
64
- # Check that the URI doesn't contain a full stop
65
- if "." in content:
66
- raise InvalidDocumentURIException(
67
- f'"{content}" is not a valid document URI; URIs cannot contain full stops.'
68
- )
69
-
70
- # If everything is good, return as usual
71
- return str.__new__(cls, content)
72
-
73
-
74
53
  class Document:
75
54
  """
76
55
  A base class from which all other document types are extensions. This class includes the essential methods for
@@ -3,6 +3,7 @@ import os
3
3
  import warnings
4
4
  from functools import cache, cached_property
5
5
  from typing import Optional
6
+ from xml.etree.ElementTree import Element
6
7
 
7
8
  import pytz
8
9
  from ds_caselaw_utils.types import CourtCode
@@ -12,6 +13,11 @@ from caselawclient.models.utilities.dates import parse_string_date_as_utc
12
13
 
13
14
  from .xml import XML
14
15
 
16
+ DEFAULT_NAMESPACES = {
17
+ "uk": "https://caselaw.nationalarchives.gov.uk/akn",
18
+ "akn": "http://docs.oasis-open.org/legaldocml/ns/akn/3.0",
19
+ }
20
+
15
21
 
16
22
  class UnparsableDate(Warning):
17
23
  pass
@@ -26,35 +32,25 @@ class DocumentBody:
26
32
  self._xml = XML(xml_bytestring=xml_bytestring)
27
33
  """ This is an instance of the `Document.XML` class for manipulation of the XML document itself. """
28
34
 
29
- def get_xpath_match_string(self, xpath: str, namespaces: dict[str, str]) -> str:
35
+ def get_xpath_match_string(self, xpath: str, namespaces: dict[str, str] = DEFAULT_NAMESPACES) -> str:
30
36
  return self._xml.get_xpath_match_string(xpath, namespaces)
31
37
 
38
+ def get_xpath_match_strings(self, xpath: str, namespaces: dict[str, str] = DEFAULT_NAMESPACES) -> list[str]:
39
+ return self._xml.get_xpath_match_strings(xpath, namespaces)
40
+
32
41
  @cached_property
33
42
  def name(self) -> str:
34
- return self._xml.get_xpath_match_string(
35
- "/akn:akomaNtoso/akn:*/akn:meta/akn:identification/akn:FRBRWork/akn:FRBRname/@value",
36
- {"akn": "http://docs.oasis-open.org/legaldocml/ns/akn/3.0"},
43
+ return self.get_xpath_match_string(
44
+ "/akn:akomaNtoso/akn:*/akn:meta/akn:identification/akn:FRBRWork/akn:FRBRname/@value"
37
45
  )
38
46
 
39
47
  @cached_property
40
48
  def court(self) -> str:
41
- return self._xml.get_xpath_match_string(
42
- "/akn:akomaNtoso/akn:*/akn:meta/akn:proprietary/uk:court/text()",
43
- {
44
- "uk": "https://caselaw.nationalarchives.gov.uk/akn",
45
- "akn": "http://docs.oasis-open.org/legaldocml/ns/akn/3.0",
46
- },
47
- )
49
+ return self.get_xpath_match_string("/akn:akomaNtoso/akn:*/akn:meta/akn:proprietary/uk:court/text()")
48
50
 
49
51
  @cached_property
50
52
  def jurisdiction(self) -> str:
51
- return self._xml.get_xpath_match_string(
52
- "/akn:akomaNtoso/akn:*/akn:meta/akn:proprietary/uk:jurisdiction/text()",
53
- {
54
- "uk": "https://caselaw.nationalarchives.gov.uk/akn",
55
- "akn": "http://docs.oasis-open.org/legaldocml/ns/akn/3.0",
56
- },
57
- )
53
+ return self.get_xpath_match_string("/akn:akomaNtoso/akn:*/akn:meta/akn:proprietary/uk:jurisdiction/text()")
58
54
 
59
55
  @property
60
56
  def court_and_jurisdiction_identifier_string(self) -> CourtCode:
@@ -64,9 +60,8 @@ class DocumentBody:
64
60
 
65
61
  @cached_property
66
62
  def document_date_as_string(self) -> str:
67
- return self._xml.get_xpath_match_string(
63
+ return self.get_xpath_match_string(
68
64
  "/akn:akomaNtoso/akn:*/akn:meta/akn:identification/akn:FRBRWork/akn:FRBRdate/@date",
69
- {"akn": "http://docs.oasis-open.org/legaldocml/ns/akn/3.0"},
70
65
  )
71
66
 
72
67
  @cached_property
@@ -90,9 +85,8 @@ class DocumentBody:
90
85
  name: Optional[str] = None,
91
86
  ) -> list[datetime.datetime]:
92
87
  name_filter = f"[@name='{name}']" if name else ""
93
- iso_datetimes = self._xml.get_xpath_match_strings(
88
+ iso_datetimes = self.get_xpath_match_strings(
94
89
  f"/akn:akomaNtoso/akn:*/akn:meta/akn:identification/akn:FRBRManifestation/akn:FRBRdate{name_filter}/@date",
95
- {"akn": "http://docs.oasis-open.org/legaldocml/ns/akn/3.0"},
96
90
  )
97
91
 
98
92
  return [parse_string_date_as_utc(event, pytz.UTC) for event in iso_datetimes]
@@ -130,9 +124,23 @@ class DocumentBody:
130
124
  def content_as_xml(self) -> str:
131
125
  return self._xml.xml_as_string
132
126
 
127
+ @cached_property
128
+ def has_content(self) -> bool:
129
+ """If we do not have a word document, the XML will not contain
130
+ the contents of the judgment, but will contain a preamble."""
131
+
132
+ def stripped_tag_text(tag: Element) -> str:
133
+ return "".join(tag.itertext()).strip()
134
+
135
+ header = self._xml.xml_as_tree.xpath("//akn:header", namespaces=DEFAULT_NAMESPACES)[0]
136
+ content = self._xml.xml_as_tree.xpath("//akn:judgmentBody", namespaces=DEFAULT_NAMESPACES)[0]
137
+ return not (stripped_tag_text(header) == "" and stripped_tag_text(content) == "")
138
+
133
139
  @cache
134
- def content_as_html(self, image_base_url: Optional[str] = None) -> str:
140
+ def content_as_html(self, image_base_url: Optional[str] = None) -> Optional[str]:
135
141
  """Convert the XML representation of the Document into HTML for rendering."""
142
+ if not self.has_content:
143
+ return None
136
144
 
137
145
  html_xslt_location = os.path.join(os.path.dirname(os.path.realpath(__file__)), "transforms", "html.xsl")
138
146
 
@@ -4,7 +4,3 @@ class CannotPublishUnpublishableDocument(Exception):
4
4
 
5
5
  class DocumentNotSafeForDeletion(Exception):
6
6
  """A document which is not safe for deletion cannot be deleted."""
7
-
8
-
9
- class InvalidDocumentURIException(Exception):
10
- """The document URI is not valid."""
@@ -10,7 +10,9 @@ from caselawclient.models.neutral_citation_mixin import NeutralCitationMixin
10
10
  if TYPE_CHECKING:
11
11
  from caselawclient.models.press_summaries import PressSummary
12
12
 
13
- from .documents import Document, DocumentURIString
13
+ from caselawclient.types import DocumentURIString
14
+
15
+ from .documents import Document
14
16
 
15
17
 
16
18
  class Judgment(NeutralCitationMixin, Document):
@@ -8,8 +8,9 @@ from ds_caselaw_utils.types import NeutralCitationString
8
8
 
9
9
  from caselawclient.errors import DocumentNotFoundError
10
10
  from caselawclient.models.neutral_citation_mixin import NeutralCitationMixin
11
+ from caselawclient.types import DocumentURIString
11
12
 
12
- from .documents import Document, DocumentURIString
13
+ from .documents import Document
13
14
 
14
15
  if TYPE_CHECKING:
15
16
  from caselawclient.models.judgments import Judgment
@@ -2,7 +2,7 @@ import datetime
2
2
  import json
3
3
  import logging
4
4
  import uuid
5
- from typing import TYPE_CHECKING, Any, Literal, Optional, TypedDict, overload
5
+ from typing import Any, Literal, Optional, TypedDict, overload
6
6
 
7
7
  import boto3
8
8
  import botocore.client
@@ -13,10 +13,7 @@ from mypy_boto3_sns.client import SNSClient
13
13
  from mypy_boto3_sns.type_defs import MessageAttributeValueTypeDef
14
14
  from typing_extensions import NotRequired
15
15
 
16
- if TYPE_CHECKING:
17
- from caselawclient.models.documents import DocumentURIString
18
- else:
19
- DocumentURIString = None
16
+ from caselawclient.types import DocumentURIString
20
17
 
21
18
  env = environ.Env()
22
19
 
@@ -4,8 +4,8 @@ import ds_caselaw_utils as caselawutils
4
4
  from ds_caselaw_utils.types import NeutralCitationString
5
5
 
6
6
  from caselawclient.errors import MarklogicAPIError
7
- from caselawclient.models.documents import DocumentURIString
8
7
  from caselawclient.models.utilities.aws import copy_assets
8
+ from caselawclient.types import DocumentURIString
9
9
 
10
10
  if TYPE_CHECKING:
11
11
  from caselawclient.Client import MarklogicApiClient
@@ -12,7 +12,7 @@ from ds_caselaw_utils.types import CourtCode, JurisdictionCode
12
12
  from lxml import etree
13
13
 
14
14
  from caselawclient.Client import MarklogicApiClient
15
- from caselawclient.models.documents import DocumentURIString
15
+ from caselawclient.types import DocumentURIString
16
16
  from caselawclient.xml_helpers import get_xpath_match_string
17
17
 
18
18
 
@@ -0,0 +1,24 @@
1
+ class InvalidDocumentURIException(Exception):
2
+ """The document URI is not valid."""
3
+
4
+
5
+ class DocumentURIString(str):
6
+ """
7
+ This class checks that the string is actually a valid Document URI on creation. It does _not_ manipulate the string.
8
+ """
9
+
10
+ def __new__(cls, content: str) -> "DocumentURIString":
11
+ # Check that the URI doesn't begin or end with a slash
12
+ if content[0] == "/" or content[-1] == "/":
13
+ raise InvalidDocumentURIException(
14
+ f'"{content}" is not a valid document URI; URIs cannot begin or end with slashes.'
15
+ )
16
+
17
+ # Check that the URI doesn't contain a full stop
18
+ if "." in content:
19
+ raise InvalidDocumentURIException(
20
+ f'"{content}" is not a valid document URI; URIs cannot contain full stops.'
21
+ )
22
+
23
+ # If everything is good, return as usual
24
+ return str.__new__(cls, content)
@@ -0,0 +1,17 @@
1
+ xquery version "1.0-ml";
2
+
3
+ declare namespace xdmp="http://marklogic.com/xdmp";
4
+ declare variable $identifier_value as xs:string external;
5
+ declare variable $published_only as xs:int? external := 1;
6
+
7
+ let $published_query := if ($published_only) then " AND document_published = 'true'" else ""
8
+ let $query := "SELECT * from compiled_url_slugs WHERE (identifier_value = @value)" || $published_query
9
+
10
+ return xdmp:sql(
11
+ $query,
12
+ "map",
13
+ map:new((
14
+ map:entry("value", $identifier_value)
15
+ ))
16
+ )
17
+
@@ -7,7 +7,7 @@ checks. They are used to enforce appropriately typed variables being passed in t
7
7
  """
8
8
 
9
9
  from typing import Any, NewType, Optional, TypedDict
10
- from caselawclient.models.documents import DocumentURIString
10
+ from caselawclient.types import DocumentURIString
11
11
 
12
12
  MarkLogicDocumentURIString = NewType("MarkLogicDocumentURIString", str)
13
13
  MarkLogicDocumentVersionURIString = NewType("MarkLogicDocumentVersionURIString", MarkLogicDocumentURIString)
@@ -141,12 +141,18 @@ class ListJudgmentVersionsDict(MarkLogicAPIDict):
141
141
  uri: MarkLogicDocumentURIString
142
142
 
143
143
 
144
- # resolve_from_identifier.xqy
145
- class ResolveFromIdentifierDict(MarkLogicAPIDict):
144
+ # resolve_from_identifier_slug.xqy
145
+ class ResolveFromIdentifierSlugDict(MarkLogicAPIDict):
146
146
  identifier_uri: DocumentURIString
147
147
  published_only: Optional[int]
148
148
 
149
149
 
150
+ # resolve_from_identifier_value.xqy
151
+ class ResolveFromIdentifierValueDict(MarkLogicAPIDict):
152
+ identifier_value: str
153
+ published_only: Optional[int]
154
+
155
+
150
156
  # set_boolean_property.xqy
151
157
  class SetBooleanPropertyDict(MarkLogicAPIDict):
152
158
  name: str