ds-caselaw-marklogic-api-client 27.0.0__tar.gz → 27.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.
Files changed (72) hide show
  1. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/PKG-INFO +2 -1
  2. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/pyproject.toml +3 -1
  3. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/Client.py +3 -1
  4. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/factories.py +14 -46
  5. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/models/documents/__init__.py +7 -0
  6. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/models/documents/body.py +20 -1
  7. ds_caselaw_marklogic_api_client-27.1.0/src/caselawclient/models/documents/transforms/html.xsl +1062 -0
  8. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/LICENSE.md +0 -0
  9. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/README.md +0 -0
  10. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/__init__.py +0 -0
  11. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/client_helpers/__init__.py +0 -0
  12. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/client_helpers/search_helpers.py +0 -0
  13. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/content_hash.py +0 -0
  14. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/errors.py +0 -0
  15. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/models/__init__.py +0 -0
  16. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/models/documents/exceptions.py +0 -0
  17. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/models/documents/statuses.py +0 -0
  18. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/models/documents/xml.py +0 -0
  19. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/models/judgments.py +0 -0
  20. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/models/neutral_citation_mixin.py +0 -0
  21. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/models/press_summaries.py +0 -0
  22. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/models/utilities/__init__.py +0 -0
  23. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/models/utilities/aws.py +0 -0
  24. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/models/utilities/dates.py +0 -0
  25. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/models/utilities/move.py +0 -0
  26. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/py.typed +0 -0
  27. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/responses/__init__.py +0 -0
  28. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/responses/search_response.py +0 -0
  29. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/responses/search_result.py +0 -0
  30. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/responses/xsl/search_match.xsl +0 -0
  31. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/search_parameters.py +0 -0
  32. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xml_helpers.py +0 -0
  33. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/break_judgment_checkout.xqy +0 -0
  34. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/checkin_judgment.xqy +0 -0
  35. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/checkout_judgment.xqy +0 -0
  36. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/copy_document.xqy +0 -0
  37. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/delete_judgment.xqy +0 -0
  38. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/document_collections.xqy +0 -0
  39. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/document_exists.xqy +0 -0
  40. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/get_combined_stats_table.xqy +0 -0
  41. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/get_components_for_document.xqy +0 -0
  42. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/get_highest_enrichment_version.xqy +0 -0
  43. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/get_highest_parser_version.xqy +0 -0
  44. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/get_judgment.xqy +0 -0
  45. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/get_judgment_checkout_status.xqy +0 -0
  46. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/get_judgment_version.xqy +0 -0
  47. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/get_last_modified.xqy +0 -0
  48. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/get_pending_enrichment_for_version.xqy +0 -0
  49. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/get_pending_parse_for_version.xqy +0 -0
  50. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/get_properties_for_search_results.xqy +0 -0
  51. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/get_property.xqy +0 -0
  52. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/get_version_annotation.xqy +0 -0
  53. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/get_version_created.xqy +0 -0
  54. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/insert_document.xqy +0 -0
  55. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/list_judgment_versions.xqy +0 -0
  56. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/set_boolean_property.xqy +0 -0
  57. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/set_metadata_citation.xqy +0 -0
  58. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/set_metadata_court.xqy +0 -0
  59. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/set_metadata_jurisdiction.xqy +0 -0
  60. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/set_metadata_name.xqy +0 -0
  61. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/set_metadata_this_uri.xqy +0 -0
  62. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/set_metadata_work_expression_date.xqy +0 -0
  63. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/set_property.xqy +0 -0
  64. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/update_document.xqy +0 -0
  65. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/update_locked_judgment.xqy +0 -0
  66. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/user_has_privilege.xqy +0 -0
  67. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/user_has_role.xqy +0 -0
  68. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/validate_all_documents.xqy +0 -0
  69. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/validate_document.xqy +0 -0
  70. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/xslt.xqy +0 -0
  71. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery/xslt_transform.xqy +0 -0
  72. {ds_caselaw_marklogic_api_client-27.0.0 → ds_caselaw_marklogic_api_client-27.1.0}/src/caselawclient/xquery_type_dicts.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ds-caselaw-marklogic-api-client
3
- Version: 27.0.0
3
+ Version: 27.1.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
@@ -24,6 +24,7 @@ Requires-Dist: python-dateutil (>=2.9.0-post.0,<3.0.0)
24
24
  Requires-Dist: pytz (>=2024.1,<2025.0)
25
25
  Requires-Dist: requests (>=2.28.2,<3.0.0)
26
26
  Requires-Dist: requests-toolbelt (>=0.10.1,<1.1.0)
27
+ Requires-Dist: saxonche (>=12.5.0,<13.0.0)
27
28
  Requires-Dist: typing-extensions (>=4.7.1,<5.0.0)
28
29
  Description-Content-Type: text/markdown
29
30
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "ds-caselaw-marklogic-api-client"
3
- version = "27.0.0"
3
+ version = "27.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"
@@ -27,10 +27,12 @@ mypy-boto3-s3 = "^1.26.104"
27
27
  mypy-boto3-sns = "^1.26.69"
28
28
  pytz = "^2024.1"
29
29
  python-dateutil = "^2.9.0-post.0"
30
+ saxonche = "^12.5.0"
30
31
 
31
32
  [tool.poetry.group.dev.dependencies]
32
33
  coverage = "^7.2.3"
33
34
  pytest = "^8.0.0"
35
+ beautifulsoup4 = "^4.12.3"
34
36
  responses = "^0.25.0"
35
37
  python-dotenv = "^1.0.0"
36
38
  time-machine = "^2.13.0"
@@ -634,12 +634,14 @@ class MarklogicApiClient:
634
634
  judgment_uri: DocumentURIString,
635
635
  annotation: str = "",
636
636
  expires_at_midnight: bool = False,
637
+ timeout_seconds: int = -1,
637
638
  ) -> requests.Response:
639
+ """If timeout_seconds is -1, the lock never times out"""
638
640
  uri = self._format_uri_for_marklogic(judgment_uri)
639
641
  vars: query_dicts.CheckoutJudgmentDict = {
640
642
  "uri": uri,
641
643
  "annotation": annotation,
642
- "timeout": -1,
644
+ "timeout": timeout_seconds,
643
645
  }
644
646
 
645
647
  if expires_at_midnight:
@@ -1,6 +1,6 @@
1
1
  import datetime
2
- from typing import Any, Optional, cast
3
- from unittest.mock import Mock, patch
2
+ from typing import Any, Optional
3
+ from unittest.mock import Mock
4
4
 
5
5
  from typing_extensions import TypeAlias
6
6
 
@@ -63,10 +63,8 @@ class DocumentFactory:
63
63
  api_client = Mock(spec=MarklogicApiClient)
64
64
  api_client.get_judgment_xml_bytestring.return_value = DEFAULT_DOCUMENT_BODY_XML.encode(encoding="utf-8")
65
65
 
66
- with patch.object(cls.target_class, "content_as_html") as mock_content_as_html:
67
- mock_content_as_html.return_value = html
68
- document = cls.target_class(uri, api_client=api_client)
69
-
66
+ document = cls.target_class(uri, api_client=api_client)
67
+ document.content_as_html = Mock(return_value=html) # type: ignore[method-assign]
70
68
  document.body = kwargs.pop("body") if "body" in kwargs else DocumentBodyFactory.build()
71
69
 
72
70
  for param_name, default_value in cls.PARAMS_MAP.items():
@@ -77,55 +75,24 @@ class DocumentFactory:
77
75
 
78
76
 
79
77
  class JudgmentFactory(DocumentFactory):
80
- target_class = Judgment
81
-
82
- def __init__(self) -> None:
83
- self.PARAMS_MAP = self.PARAMS_MAP | {
84
- "neutral_citation": "[2023] Test 123",
85
- "best_human_identifier": "[2023] Test 123",
86
- }
87
-
88
- super().__init__()
89
-
90
- @classmethod
91
- def build(
92
- cls,
93
- uri: str = "test/2023/123",
94
- html: str = "<p>This is a judgment.</p>",
95
- api_client: Optional[MarklogicApiClient] = None,
96
- **kwargs: Any,
97
- ) -> Judgment:
98
- return cast(Judgment, super().build(uri, html, api_client, **kwargs))
78
+ target_class: TypeAlias = Judgment
79
+ PARAMS_MAP = DocumentFactory.PARAMS_MAP | {
80
+ "neutral_citation": "[2023] Test 123",
81
+ }
99
82
 
100
83
 
101
84
  class PressSummaryFactory(DocumentFactory):
102
- target_class = PressSummary
103
-
104
- def __init__(self) -> None:
105
- self.PARAMS_MAP = self.PARAMS_MAP | {
106
- "neutral_citation": "[2023] Test 123",
107
- "best_human_identifier": "[2023] Test 123",
108
- }
109
-
110
- super().__init__()
111
-
112
- @classmethod
113
- def build(
114
- cls,
115
- uri: str = "test/2023/123/press-summary/1",
116
- html: str = "<p>This is a judgment.</p>",
117
- api_client: Optional[MarklogicApiClient] = None,
118
- **kwargs: Any,
119
- ) -> PressSummary:
120
- return cast(PressSummary, super().build(uri, html, api_client, **kwargs))
85
+ target_class: TypeAlias = PressSummary
86
+ PARAMS_MAP = DocumentFactory.PARAMS_MAP | {
87
+ "neutral_citation": "[2023] Test 123",
88
+ }
121
89
 
122
90
 
123
91
  class SimpleFactory:
92
+ target_class: TypeAlias = object
124
93
  # "name_of_attribute": "default value"
125
94
  PARAMS_MAP: dict[str, Any]
126
95
 
127
- target_class: TypeAlias = object
128
-
129
96
  @classmethod
130
97
  def build(cls, **kwargs: Any) -> target_class:
131
98
  mock_object = Mock(spec=cls.target_class, autospec=True)
@@ -147,6 +114,7 @@ class SearchResultMetadataFactory(SimpleFactory):
147
114
  "author_email": "fake.email@gov.invalid",
148
115
  "consignment_reference": "TDR-2023-ABC",
149
116
  "submission_datetime": datetime.datetime(2023, 2, 3, 9, 12, 34),
117
+ "editor_status": "New",
150
118
  }
151
119
 
152
120
 
@@ -495,3 +495,10 @@ class Document:
495
495
  Is it sensible to reparse this document?
496
496
  """
497
497
  return self.docx_exists()
498
+
499
+ def __getattr__(self, name: str) -> Any:
500
+ warnings.warn(f"{name} no longer exists on Document, using Document.body instead", DeprecationWarning)
501
+ try:
502
+ return getattr(self.body, name)
503
+ except Exception:
504
+ raise AttributeError(f"Neither 'Document' nor 'DocumentBody' objects have an attribute '{name}'")
@@ -1,10 +1,12 @@
1
1
  import datetime
2
+ import os
2
3
  import warnings
3
- from functools import cached_property
4
+ from functools import cache, cached_property
4
5
  from typing import Optional
5
6
 
6
7
  import pytz
7
8
  from ds_caselaw_utils.types import CourtCode
9
+ from saxonche import PySaxonProcessor
8
10
 
9
11
  from caselawclient.models.utilities.dates import parse_string_date_as_utc
10
12
 
@@ -129,6 +131,23 @@ class DocumentBody:
129
131
  def content_as_xml(self) -> str:
130
132
  return self._xml.xml_as_string
131
133
 
134
+ @cache
135
+ def content_as_html(self, image_base_url: Optional[str] = None) -> str:
136
+ """Convert the XML representation of the Document into HTML for rendering."""
137
+
138
+ html_xslt_location = os.path.join(os.path.dirname(os.path.realpath(__file__)), "transforms", "html.xsl")
139
+
140
+ with PySaxonProcessor() as proc:
141
+ xslt_processor = proc.new_xslt30_processor()
142
+ document = proc.parse_xml(xml_text=self._xml.xml_as_string)
143
+
144
+ executable = xslt_processor.compile_stylesheet(stylesheet_file=html_xslt_location)
145
+
146
+ if image_base_url:
147
+ executable.set_parameter("image-base", proc.make_string_value(image_base_url))
148
+
149
+ return str(executable.transform_to_string(xdm_node=document))
150
+
132
151
  @cached_property
133
152
  def failed_to_parse(self) -> bool:
134
153
  """