ds-caselaw-marklogic-api-client 37.3.1__py3-none-any.whl → 37.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,8 @@
1
1
  import datetime
2
2
  import json
3
- from typing import Any, Optional
3
+ from typing import Any, Generic, Optional, Type, TypeAlias, TypeVar, cast
4
4
  from unittest.mock import Mock
5
5
 
6
- from typing_extensions import TypeAlias
7
-
8
6
  from caselawclient.Client import MarklogicApiClient
9
7
  from caselawclient.identifier_resolution import IdentifierResolution, IdentifierResolutions
10
8
  from caselawclient.models.documents import Document
@@ -17,6 +15,8 @@ from caselawclient.models.press_summaries import PressSummary
17
15
  from caselawclient.responses.search_result import SearchResult, SearchResultMetadata
18
16
  from caselawclient.types import DocumentURIString
19
17
 
18
+ T = TypeVar("T")
19
+
20
20
  DEFAULT_DOCUMENT_BODY_XML = """<akomaNtoso xmlns="http://docs.oasis-open.org/legaldocml/ns/akn/3.0" xmlns:uk="https://caselaw.nationalarchives.gov.uk/akn">
21
21
  <judgment name="decision">
22
22
  <meta/><header/>
@@ -114,13 +114,13 @@ class PressSummaryFactory(DocumentFactory):
114
114
  }
115
115
 
116
116
 
117
- class SimpleFactory:
118
- target_class: TypeAlias = object
117
+ class SimpleFactory(Generic[T]):
118
+ target_class: Type[T]
119
119
  # "name_of_attribute": "default value"
120
120
  PARAMS_MAP: dict[str, Any]
121
121
 
122
122
  @classmethod
123
- def build(cls, **kwargs: Any) -> target_class:
123
+ def build(cls, **kwargs: Any) -> T:
124
124
  mock_object = Mock(spec=cls.target_class, autospec=True)
125
125
 
126
126
  for param, default in cls.PARAMS_MAP.items():
@@ -129,10 +129,10 @@ class SimpleFactory:
129
129
  else:
130
130
  setattr(mock_object.return_value, param, default)
131
131
 
132
- return mock_object()
132
+ return cast(T, mock_object())
133
133
 
134
134
 
135
- class SearchResultMetadataFactory(SimpleFactory):
135
+ class SearchResultMetadataFactory(SimpleFactory[SearchResultMetadata]):
136
136
  target_class = SearchResultMetadata
137
137
  # "name_of_attribute": "default value"
138
138
  PARAMS_MAP = {
@@ -174,9 +174,8 @@ class IdentifierResolutionsFactory:
174
174
  return IdentifierResolutions(resolutions)
175
175
 
176
176
 
177
- class SearchResultFactory(SimpleFactory):
177
+ class SearchResultFactory(SimpleFactory[SearchResult]):
178
178
  target_class = SearchResult
179
-
180
179
  PARAMS_MAP = {
181
180
  "uri": "d-a1b2c3",
182
181
  "name": "Judgment v Judgement",
@@ -51,6 +51,14 @@ class DocumentBody:
51
51
  def jurisdiction(self) -> str:
52
52
  return self.get_xpath_match_string("/akn:akomaNtoso/akn:*/akn:meta/akn:proprietary/uk:jurisdiction/text()")
53
53
 
54
+ @cached_property
55
+ def category(self) -> Optional[str]:
56
+ return self.get_xpath_match_string("/akn:akomaNtoso/akn:*/akn:meta/akn:proprietary/uk:category/text()")
57
+
58
+ @cached_property
59
+ def case_number(self) -> Optional[str]:
60
+ return self.get_xpath_match_string("/akn:akomaNtoso/akn:*/akn:meta/akn:proprietary/uk:caseNumber/text()")
61
+
54
62
  @property
55
63
  def court_and_jurisdiction_identifier_string(self) -> CourtCode:
56
64
  if self.jurisdiction != "":
@@ -11,13 +11,17 @@ from .exceptions import IdentifierValidationException, UUIDMismatchError
11
11
  IDENTIFIER_PACKABLE_ATTRIBUTES: list[str] = [
12
12
  "uuid",
13
13
  "value",
14
+ "deprecated",
14
15
  "url_slug",
15
16
  ]
17
+ """A list of attributes of an Identifier to pack into an XML representation."""
16
18
 
17
19
  IDENTIFIER_UNPACKABLE_ATTRIBUTES: list[str] = [
18
20
  "uuid",
19
21
  "value",
22
+ "deprecated",
20
23
  ]
24
+ """A list of attributes to unpack from an XML representation."""
21
25
 
22
26
 
23
27
  class IdentifierSchema(ABC):
@@ -69,6 +73,9 @@ class Identifier(ABC):
69
73
  uuid: str
70
74
  value: DocumentIdentifierValue
71
75
 
76
+ deprecated: bool
77
+ """Should this identifier be considered deprecated, ie although we know it refers to a particular document its usage should be discouraged?"""
78
+
72
79
  def __init_subclass__(cls: type["Identifier"], **kwargs: Any) -> None:
73
80
  """Ensure that subclasses have the required attributes set."""
74
81
  for required in ("schema",):
@@ -77,12 +84,16 @@ class Identifier(ABC):
77
84
  super().__init_subclass__(**kwargs)
78
85
 
79
86
  def __repr__(self) -> str:
80
- return f"<{self.schema.name} {self.value}: {self.uuid}>"
87
+ representation = f"{self.schema.name} {self.value}: {self.uuid}"
88
+
89
+ if self.deprecated:
90
+ return f"<{representation} (deprecated)> "
91
+ return f"<{representation}>"
81
92
 
82
93
  def __str__(self) -> str:
83
94
  return self.value
84
95
 
85
- def __init__(self, value: str, uuid: Optional[str] = None) -> None:
96
+ def __init__(self, value: str, uuid: Optional[str] = None, deprecated: bool = False) -> None:
86
97
  if not self.schema.validate_identifier(value=value):
87
98
  raise IdentifierValidationException(
88
99
  f'Identifier value "{value}" is not valid according to the {self.schema.name} schema.'
@@ -94,6 +105,8 @@ class Identifier(ABC):
94
105
  else:
95
106
  self.uuid = "id-" + str(uuid4())
96
107
 
108
+ self.deprecated = deprecated
109
+
97
110
  @property
98
111
  def as_xml_tree(self) -> etree._Element:
99
112
  """Convert this Identifier into a packed XML representation for storage."""
@@ -102,9 +115,13 @@ class Identifier(ABC):
102
115
  namespace_attribute = etree.SubElement(identifier_root, "namespace")
103
116
  namespace_attribute.text = self.schema.namespace
104
117
 
105
- for attribute in IDENTIFIER_PACKABLE_ATTRIBUTES:
106
- packed_attribute = etree.SubElement(identifier_root, attribute)
107
- packed_attribute.text = getattr(self, attribute)
118
+ for attribute_name in IDENTIFIER_PACKABLE_ATTRIBUTES:
119
+ packed_attribute = etree.SubElement(identifier_root, attribute_name)
120
+ attribute_value = getattr(self, attribute_name)
121
+ if type(attribute_value) is bool:
122
+ packed_attribute.text = str(attribute_value).lower()
123
+ else:
124
+ packed_attribute.text = getattr(self, attribute_name)
108
125
 
109
126
  return identifier_root
110
127
 
@@ -43,14 +43,23 @@ def unpack_an_identifier_from_etree(identifier_xml: etree._Element) -> Optional[
43
43
  warn(f"Identifier type {namespace_element.text} is not known.")
44
44
  return None
45
45
 
46
- kwargs: dict[str, str] = {}
46
+ str_kwargs: dict[str, str] = {}
47
+ deprecated = False
47
48
 
48
49
  for attribute in IDENTIFIER_UNPACKABLE_ATTRIBUTES:
49
50
  element = identifier_xml.find(attribute)
50
- if element is None or not element.text:
51
- raise InvalidIdentifierXMLRepresentationException(
52
- f"Identifer XML representation is not valid: {element} not present or empty"
53
- )
54
- kwargs[attribute] = element.text
55
51
 
56
- return IDENTIFIER_NAMESPACE_MAP[namespace_element.text](**kwargs)
52
+ # Special case for unpacking deprecation state into a boolean
53
+ if attribute == "deprecated":
54
+ if element is not None and element.text is not None and element.text.lower() == "true":
55
+ deprecated = True
56
+
57
+ else:
58
+ # Case for unpacking all other element types
59
+ if element is None or not element.text:
60
+ raise InvalidIdentifierXMLRepresentationException(
61
+ f"Identifer XML representation is not valid: {element} not present or empty"
62
+ )
63
+ str_kwargs[attribute] = element.text
64
+
65
+ return IDENTIFIER_NAMESPACE_MAP[namespace_element.text](deprecated=deprecated, **str_kwargs)
@@ -1,14 +1,15 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: ds-caselaw-marklogic-api-client
3
- Version: 37.3.1
3
+ Version: 37.4.0
4
4
  Summary: An API client for interacting with the underlying data in Find Caselaw.
5
- Home-page: https://github.com/nationalarchives/ds-caselaw-custom-api-client
6
5
  Keywords: national archives,caselaw
7
6
  Author: The National Archives
8
7
  Requires-Python: >=3.10.0,<4.0.0
9
8
  Classifier: Programming Language :: Python :: 3
10
9
  Classifier: Programming Language :: Python :: 3.10
11
10
  Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
12
13
  Requires-Dist: boto3 (>=1.26.112,<2.0.0)
13
14
  Requires-Dist: certifi (>=2025.4.26,<2025.5.0)
14
15
  Requires-Dist: charset-normalizer (>=3.0.0,<4.0.0)
@@ -26,6 +27,7 @@ Requires-Dist: requests-toolbelt (>=0.10.1,<1.1.0)
26
27
  Requires-Dist: saxonche (>=12.5.0,<13.0.0)
27
28
  Requires-Dist: sqids (>=0.5.0,<0.6.0)
28
29
  Requires-Dist: typing-extensions (>=4.7.1,<5.0.0)
30
+ Project-URL: Homepage, https://github.com/nationalarchives/ds-caselaw-custom-api-client
29
31
  Description-Content-Type: text/markdown
30
32
 
31
33
  # The National Archives: Find Case Law
@@ -4,21 +4,21 @@ caselawclient/client_helpers/__init__.py,sha256=eucyUXwUqI72TPw-C5zLcHlMu4GtFY50
4
4
  caselawclient/client_helpers/search_helpers.py,sha256=R99HyRLeYHgsw2L3DOidEqlKLLvs6Tga5rKTuWQViig,1525
5
5
  caselawclient/content_hash.py,sha256=0cPC4OoABq0SC2wYFX9-24DodNigeOqksDxgxQH_hUA,2221
6
6
  caselawclient/errors.py,sha256=JC16fEGq_MRJX-_KFzfINCV2Cqx8o6OWOt3C16rQd84,3142
7
- caselawclient/factories.py,sha256=XgrnG61hAJ-ty61DLv2qNEAo9ITuDZowZ4MRmPrf2Bg,7109
7
+ caselawclient/factories.py,sha256=6tjIJBg0vQivYVwdKBVES8lhavLK4exqi7-CGk7w2HE,7161
8
8
  caselawclient/identifier_resolution.py,sha256=B5I1sD7o7YjzsXMECjbKjgiGLDda5bGhejsJ-lYpTIg,2429
9
9
  caselawclient/models/__init__.py,sha256=kd23EUpvaC7aLHdgk8farqKAQEx3lf7RvNT2jEatvlg,68
10
10
  caselawclient/models/documents/__init__.py,sha256=zDrR6XniqB6S2BkNJH8KfvPz-RCBjPVG_N6eJkJiIlA,19467
11
- caselawclient/models/documents/body.py,sha256=IVcuSbgA7SvCvii_VE8MZy_54enDZY8VPoESkUDgfKU,6114
11
+ caselawclient/models/documents/body.py,sha256=Hy76P8XM0K7EQVy1rz9PQe8TSgepvjLRtbYQmXX9J1g,6469
12
12
  caselawclient/models/documents/exceptions.py,sha256=Mz1P8uNqf5w6uLnRwJt6xK7efsVqtd5VA-WXUUH7QLk,285
13
13
  caselawclient/models/documents/statuses.py,sha256=Cp4dTQmJOtsU41EJcxy5dV1841pGD2PNWH0VrkDEv4Q,579
14
14
  caselawclient/models/documents/transforms/html.xsl,sha256=XyUQLFcJ7_GwthWQ6ShU0bmzrgpl7xDFU-U8VLgOvEs,38258
15
15
  caselawclient/models/documents/xml.py,sha256=HlmPb63lLMnySSOLP4iexcAyQiLByKBZtTd25f8sY8M,1268
16
- caselawclient/models/identifiers/__init__.py,sha256=_iAsx_e-Rxq3ED3TQQ5Vg1ZNnQn6AZQK8QCvHSFhdGg,6848
16
+ caselawclient/models/identifiers/__init__.py,sha256=nIlf3q-8yW6S00JU7GbxZqIMqNACwlEafRIuleS-5bM,7603
17
17
  caselawclient/models/identifiers/exceptions.py,sha256=ckVsjPzLuTXkbd7KZRJXoxcltQCXPGL2rMyYwE5orgg,177
18
18
  caselawclient/models/identifiers/fclid.py,sha256=Gq0G0eLdUH3j7VybluqJGVcHV3Y-hpjty1OdR91dI5Q,1453
19
19
  caselawclient/models/identifiers/neutral_citation.py,sha256=mFc-nYDIkLf5fM2eTSBnBigVgxuDcUF2HuMwQYEYeXY,2871
20
20
  caselawclient/models/identifiers/press_summary_ncn.py,sha256=CKhNTnO6pfriS4Sg-gt0Pf0fRhH53Uf0flULPncJWM4,762
21
- caselawclient/models/identifiers/unpacker.py,sha256=fKfiuTKaN-71e40PV8BC9PueKjwgfX9Xw3IVdy8mkqg,2299
21
+ caselawclient/models/identifiers/unpacker.py,sha256=y9WnDdy5qSXolsjLO_D0rjqJEAcVtKpfDz3-t2_keG0,2692
22
22
  caselawclient/models/judgments.py,sha256=r40irgdEID-NeSNLm3OUdUBznMpRSwjD2SJrGlBgP8o,2208
23
23
  caselawclient/models/neutral_citation_mixin.py,sha256=jAac3PPuWyPdj9N-n-U_JfwkbgbSIXaqFVQahfu95do,2086
24
24
  caselawclient/models/parser_logs.py,sha256=30kF4w0GcowiMIFtymUkl7ZARanNh_PjDpJZezn-cA8,315
@@ -83,7 +83,7 @@ caselawclient/xquery/validate_document.xqy,sha256=PgaDcnqCRJPIVqfmWsNlXmCLNKd21q
83
83
  caselawclient/xquery/xslt.xqy,sha256=w57wNijH3dkwHkpKeAxqjlghVflQwo8cq6jS_sm-erM,199
84
84
  caselawclient/xquery/xslt_transform.xqy,sha256=cccaFiGkCcvSfDv007UriZ3I4ak2nTLP1trRZdbOoS8,2462
85
85
  caselawclient/xquery_type_dicts.py,sha256=zuyDGTkcN6voOXCm3APXItZ-Ey6tZ2hdZummZWzjl50,6489
86
- ds_caselaw_marklogic_api_client-37.3.1.dist-info/LICENSE.md,sha256=fGMzyyLuQW-IAXUeDSCrRdsYW536aEWThdbpCjo6ZKg,1108
87
- ds_caselaw_marklogic_api_client-37.3.1.dist-info/METADATA,sha256=RzqWJC6SHrgrCLLOl4aRL8Th3lhaycwYMR8uATPDZeg,4206
88
- ds_caselaw_marklogic_api_client-37.3.1.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
89
- ds_caselaw_marklogic_api_client-37.3.1.dist-info/RECORD,,
86
+ ds_caselaw_marklogic_api_client-37.4.0.dist-info/LICENSE.md,sha256=fGMzyyLuQW-IAXUeDSCrRdsYW536aEWThdbpCjo6ZKg,1108
87
+ ds_caselaw_marklogic_api_client-37.4.0.dist-info/METADATA,sha256=LLPRbVfKttq9sIz2z7AA8mXzLtDtc8Agd99y_w7Gt7M,4320
88
+ ds_caselaw_marklogic_api_client-37.4.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
89
+ ds_caselaw_marklogic_api_client-37.4.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.5.2
2
+ Generator: poetry-core 2.1.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any