ds-caselaw-marklogic-api-client 29.1.0__tar.gz → 29.2.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 (84) hide show
  1. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/PKG-INFO +2 -2
  2. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/pyproject.toml +4 -2
  3. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/errors.py +1 -3
  4. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/models/documents/__init__.py +4 -5
  5. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/models/documents/body.py +1 -2
  6. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/models/neutral_citation_mixin.py +3 -6
  7. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/models/utilities/aws.py +33 -23
  8. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/get_judgment.xqy +5 -2
  9. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/LICENSE.md +0 -0
  10. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/README.md +0 -0
  11. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/Client.py +0 -0
  12. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/__init__.py +0 -0
  13. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/client_helpers/__init__.py +0 -0
  14. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/client_helpers/search_helpers.py +0 -0
  15. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/content_hash.py +0 -0
  16. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/factories.py +0 -0
  17. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/identifier_resolution.py +0 -0
  18. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/models/__init__.py +0 -0
  19. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/models/documents/exceptions.py +0 -0
  20. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/models/documents/statuses.py +0 -0
  21. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/models/documents/transforms/html.xsl +0 -0
  22. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/models/documents/xml.py +0 -0
  23. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/models/identifiers/__init__.py +0 -0
  24. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/models/identifiers/fclid.py +0 -0
  25. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/models/identifiers/neutral_citation.py +0 -0
  26. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/models/identifiers/press_summary_ncn.py +0 -0
  27. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/models/identifiers/unpacker.py +0 -0
  28. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/models/judgments.py +0 -0
  29. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/models/press_summaries.py +0 -0
  30. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/models/utilities/__init__.py +0 -0
  31. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/models/utilities/dates.py +0 -0
  32. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/models/utilities/move.py +0 -0
  33. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/py.typed +0 -0
  34. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/responses/__init__.py +0 -0
  35. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/responses/search_response.py +0 -0
  36. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/responses/search_result.py +0 -0
  37. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/responses/xsl/search_match.xsl +0 -0
  38. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/search_parameters.py +0 -0
  39. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xml_helpers.py +0 -0
  40. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/break_judgment_checkout.xqy +0 -0
  41. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/checkin_judgment.xqy +0 -0
  42. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/checkout_judgment.xqy +0 -0
  43. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/copy_document.xqy +0 -0
  44. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/delete_judgment.xqy +0 -0
  45. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/document_collections.xqy +0 -0
  46. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/document_exists.xqy +0 -0
  47. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/get_combined_stats_table.xqy +0 -0
  48. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/get_components_for_document.xqy +0 -0
  49. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/get_highest_enrichment_version.xqy +0 -0
  50. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/get_highest_parser_version.xqy +0 -0
  51. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/get_judgment_checkout_status.xqy +0 -0
  52. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/get_judgment_version.xqy +0 -0
  53. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/get_last_modified.xqy +0 -0
  54. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/get_next_document_sequence_number.xqy +0 -0
  55. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/get_pending_enrichment_for_version.xqy +0 -0
  56. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/get_pending_parse_for_version.xqy +0 -0
  57. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/get_properties_for_search_results.xqy +0 -0
  58. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/get_property.xqy +0 -0
  59. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/get_property_as_node.xqy +0 -0
  60. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/get_recently_enriched.xqy +0 -0
  61. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/get_recently_parsed.xqy +0 -0
  62. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/get_version_annotation.xqy +0 -0
  63. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/get_version_created.xqy +0 -0
  64. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/insert_document.xqy +0 -0
  65. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/list_judgment_versions.xqy +0 -0
  66. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/resolve_from_identifier.xqy +0 -0
  67. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/set_boolean_property.xqy +0 -0
  68. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/set_metadata_citation.xqy +0 -0
  69. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/set_metadata_court.xqy +0 -0
  70. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/set_metadata_jurisdiction.xqy +0 -0
  71. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/set_metadata_name.xqy +0 -0
  72. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/set_metadata_this_uri.xqy +0 -0
  73. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/set_metadata_work_expression_date.xqy +0 -0
  74. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/set_property.xqy +0 -0
  75. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/set_property_as_node.xqy +0 -0
  76. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/update_document.xqy +0 -0
  77. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/update_locked_judgment.xqy +0 -0
  78. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/user_has_privilege.xqy +0 -0
  79. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/user_has_role.xqy +0 -0
  80. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/validate_all_documents.xqy +0 -0
  81. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/validate_document.xqy +0 -0
  82. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/xslt.xqy +0 -0
  83. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.0}/src/caselawclient/xquery/xslt_transform.xqy +0 -0
  84. {ds_caselaw_marklogic_api_client-29.1.0 → ds_caselaw_marklogic_api_client-29.2.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: 29.1.0
3
+ Version: 29.2.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
@@ -13,7 +13,7 @@ Classifier: Programming Language :: Python :: 3.11
13
13
  Requires-Dist: boto3 (>=1.26.112,<2.0.0)
14
14
  Requires-Dist: certifi (>=2024.12.14,<2024.13.0)
15
15
  Requires-Dist: charset-normalizer (>=3.0.0,<4.0.0)
16
- Requires-Dist: django-environ (>=0.11.0,<0.12.0)
16
+ Requires-Dist: django-environ (>=0.12.0)
17
17
  Requires-Dist: ds-caselaw-utils (>=2.0.0,<3.0.0)
18
18
  Requires-Dist: idna (>=3.4,<4.0)
19
19
  Requires-Dist: lxml (>=5.0.0,<6.0.0)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "ds-caselaw-marklogic-api-client"
3
- version = "29.1.0"
3
+ version = "29.2.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"
@@ -14,7 +14,7 @@ packages = [
14
14
  python = "^3.9"
15
15
  certifi = ">=2024.12.14,<2024.13.0"
16
16
  charset-normalizer = "^3.0.0"
17
- django-environ = "^0.11.0"
17
+ django-environ = ">=0.12.0"
18
18
  idna = "^3.4"
19
19
  requests = "^2.28.2"
20
20
  requests-toolbelt = ">=0.10.1,<1.1.0"
@@ -52,6 +52,8 @@ tag_format = "v$version"
52
52
  version_scheme = "semver2"
53
53
  version_provider = "poetry"
54
54
  update_changelog_on_bump = true
55
+ changelog_incremental = true
56
+
55
57
  [build-system]
56
58
  requires = ["poetry-core"]
57
59
  build-backend = "poetry.core.masonry.api"
@@ -37,9 +37,7 @@ class MarklogicResourceUnmanagedError(MarklogicAPIError):
37
37
 
38
38
  status_code = 404
39
39
  default_message = (
40
- "The resource isn't managed. "
41
- "It probably doesn't exist, and if it does, that's a problem. "
42
- "Please report it."
40
+ "The resource isn't managed. It probably doesn't exist, and if it does, that's a problem. Please report it."
43
41
  )
44
42
 
45
43
 
@@ -29,7 +29,6 @@ from caselawclient.models.utilities.aws import (
29
29
  publish_documents,
30
30
  request_parse,
31
31
  unpublish_documents,
32
- uri_for_s3,
33
32
  )
34
33
 
35
34
  from .body import DocumentBody
@@ -216,11 +215,11 @@ class Document:
216
215
 
217
216
  @property
218
217
  def docx_url(self) -> str:
219
- return generate_docx_url(uri_for_s3(self.uri))
218
+ return generate_docx_url(self.uri)
220
219
 
221
220
  @property
222
221
  def pdf_url(self) -> str:
223
- return generate_pdf_url(uri_for_s3(self.uri))
222
+ return generate_pdf_url(self.uri)
224
223
 
225
224
  @cached_property
226
225
  def assigned_to(self) -> str:
@@ -438,7 +437,7 @@ class Document:
438
437
  self.identifiers.add(document_fclid)
439
438
  self.save_identifiers()
440
439
 
441
- publish_documents(uri_for_s3(self.uri))
440
+ publish_documents(self.uri)
442
441
  self.api_client.set_published(self.uri, True)
443
442
  announce_document_event(
444
443
  uri=self.uri,
@@ -448,7 +447,7 @@ class Document:
448
447
 
449
448
  def unpublish(self) -> None:
450
449
  self.api_client.break_checkout(self.uri)
451
- unpublish_documents(uri_for_s3(self.uri))
450
+ unpublish_documents(self.uri)
452
451
  self.api_client.set_published(self.uri, False)
453
452
  announce_document_event(
454
453
  uri=self.uri,
@@ -91,8 +91,7 @@ class DocumentBody:
91
91
  ) -> list[datetime.datetime]:
92
92
  name_filter = f"[@name='{name}']" if name else ""
93
93
  iso_datetimes = self._xml.get_xpath_match_strings(
94
- "/akn:akomaNtoso/akn:*/akn:meta/akn:identification/akn:FRBRManifestation"
95
- f"/akn:FRBRdate{name_filter}/@date",
94
+ f"/akn:akomaNtoso/akn:*/akn:meta/akn:identification/akn:FRBRManifestation/akn:FRBRdate{name_filter}/@date",
96
95
  {"akn": "http://docs.oasis-open.org/legaldocml/ns/akn/3.0"},
97
96
  )
98
97
 
@@ -23,11 +23,6 @@ class NeutralCitationMixin(ABC):
23
23
 
24
24
  def __init__(self, document_noun: str, *args: Any, **kwargs: Any) -> None:
25
25
  self.attributes_to_validate: list[tuple[str, bool, str]] = self.attributes_to_validate + [
26
- (
27
- "has_ncn",
28
- True,
29
- f"This {document_noun} has no neutral citation number",
30
- ),
31
26
  (
32
27
  "has_valid_ncn",
33
28
  True,
@@ -50,4 +45,6 @@ class NeutralCitationMixin(ABC):
50
45
  @cached_property
51
46
  @deprecated("Legacy usage of NCNs is deprecated; you should be moving to the Identifiers framework")
52
47
  def has_valid_ncn(self) -> bool:
53
- return self.neutral_citation is not None and neutral_url(self.neutral_citation) is not None
48
+ if self.neutral_citation is None:
49
+ return True
50
+ return neutral_url(self.neutral_citation) is not None
@@ -2,7 +2,7 @@ import datetime
2
2
  import json
3
3
  import logging
4
4
  import uuid
5
- from typing import Any, Literal, Optional, TypedDict, overload
5
+ from typing import TYPE_CHECKING, Any, Literal, Optional, TypedDict, overload
6
6
 
7
7
  import boto3
8
8
  import botocore.client
@@ -13,9 +13,21 @@ 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
20
+
16
21
  env = environ.Env()
17
22
 
18
23
 
24
+ class S3PrefixString(str):
25
+ def __new__(cls, content: str) -> "S3PrefixString":
26
+ if content[-1] != "/":
27
+ raise RuntimeError("S3 Prefixes must end in / so they behave like directories")
28
+ return str.__new__(cls, content)
29
+
30
+
19
31
  class ParserInstructionsMetadataDict(TypedDict):
20
32
  name: Optional[str]
21
33
  cite: Optional[str]
@@ -58,8 +70,9 @@ def create_sns_client() -> SNSClient:
58
70
  return create_aws_client("sns")
59
71
 
60
72
 
61
- def uri_for_s3(uri: str) -> str:
62
- return uri.lstrip("/")
73
+ def uri_for_s3(uri: DocumentURIString) -> S3PrefixString:
74
+ """An S3 Prefix must end with / to avoid uksc/2004/1 matching uksc/2004/1000"""
75
+ return S3PrefixString(uri + "/")
63
76
 
64
77
 
65
78
  def generate_signed_asset_url(key: str) -> str:
@@ -79,7 +92,7 @@ def generate_signed_asset_url(key: str) -> str:
79
92
  )
80
93
 
81
94
 
82
- def check_docx_exists(uri: str) -> bool:
95
+ def check_docx_exists(uri: DocumentURIString) -> bool:
83
96
  """Does the docx for a document URI actually exist?"""
84
97
  bucket = env("PRIVATE_ASSET_BUCKET", None)
85
98
  s3_key = generate_docx_key(uri)
@@ -93,25 +106,25 @@ def check_docx_exists(uri: str) -> bool:
93
106
  raise
94
107
 
95
108
 
96
- def generate_docx_key(uri: str) -> str:
109
+ def generate_docx_key(uri: DocumentURIString) -> str:
97
110
  """from a canonical caselaw URI (eat/2022/1) return the S3 key of the associated docx"""
98
- return f'{uri}/{uri.replace("/", "_")}.docx'
111
+ return f"{uri}/{uri.replace('/', '_')}.docx"
99
112
 
100
113
 
101
- def generate_docx_url(uri: str) -> str:
114
+ def generate_docx_url(uri: DocumentURIString) -> str:
102
115
  """from a canonical caselaw URI (eat/2022/1) return a signed S3 link for the front end"""
103
116
  return generate_signed_asset_url(generate_docx_key(uri))
104
117
 
105
118
 
106
- def generate_pdf_url(uri: str) -> str:
107
- key = f'{uri}/{uri.replace("/", "_")}.pdf'
119
+ def generate_pdf_url(uri: DocumentURIString) -> str:
120
+ key = f"{uri}/{uri.replace('/', '_')}.pdf"
108
121
 
109
122
  return generate_signed_asset_url(key)
110
123
 
111
124
 
112
- def delete_from_bucket(uri: str, bucket: str) -> None:
125
+ def delete_from_bucket(uri: DocumentURIString, bucket: str) -> None:
113
126
  client = create_s3_client()
114
- response = client.list_objects(Bucket=bucket, Prefix=uri)
127
+ response = client.list_objects(Bucket=bucket, Prefix=uri_for_s3(uri))
115
128
 
116
129
  if response.get("Contents"):
117
130
  objects_to_delete: list[ObjectIdentifierTypeDef] = [{"Key": obj["Key"]} for obj in response.get("Contents", [])]
@@ -123,7 +136,7 @@ def delete_from_bucket(uri: str, bucket: str) -> None:
123
136
  )
124
137
 
125
138
 
126
- def publish_documents(uri: str) -> None:
139
+ def publish_documents(uri: DocumentURIString) -> None:
127
140
  """
128
141
  Copy assets from the unpublished bucket to the published one.
129
142
  Don't copy parser logs and package tar gz.
@@ -134,7 +147,7 @@ def publish_documents(uri: str) -> None:
134
147
  public_bucket = env("PUBLIC_ASSET_BUCKET")
135
148
  private_bucket = env("PRIVATE_ASSET_BUCKET")
136
149
 
137
- response = client.list_objects(Bucket=private_bucket, Prefix=uri)
150
+ response = client.list_objects(Bucket=private_bucket, Prefix=uri_for_s3(uri))
138
151
 
139
152
  for result in response.get("Contents", []):
140
153
  print(f"Contemplating copying {result!r}")
@@ -152,15 +165,15 @@ def publish_documents(uri: str) -> None:
152
165
  )
153
166
 
154
167
 
155
- def unpublish_documents(uri: str) -> None:
168
+ def unpublish_documents(uri: DocumentURIString) -> None:
156
169
  delete_from_bucket(uri, env("PUBLIC_ASSET_BUCKET"))
157
170
 
158
171
 
159
- def delete_documents_from_private_bucket(uri: str) -> None:
172
+ def delete_documents_from_private_bucket(uri: DocumentURIString) -> None:
160
173
  delete_from_bucket(uri, env("PRIVATE_ASSET_BUCKET"))
161
174
 
162
175
 
163
- def announce_document_event(uri: str, status: str, enrich: bool = False) -> None:
176
+ def announce_document_event(uri: DocumentURIString, status: str, enrich: bool = False) -> None:
164
177
  client = create_sns_client()
165
178
 
166
179
  message_attributes: dict[str, MessageAttributeValueTypeDef] = {}
@@ -186,17 +199,14 @@ def announce_document_event(uri: str, status: str, enrich: bool = False) -> None
186
199
  )
187
200
 
188
201
 
189
- def copy_assets(old_uri: str, new_uri: str) -> None:
202
+ def copy_assets(old_uri: DocumentURIString, new_uri: DocumentURIString) -> None:
190
203
  """
191
204
  Copy *unpublished* assets from one path to another,
192
205
  renaming DOCX and PDF files as appropriate.
193
206
  """
194
207
  client = create_s3_client()
195
208
  bucket = env("PRIVATE_ASSET_BUCKET")
196
- old_uri = uri_for_s3(old_uri)
197
- new_uri = uri_for_s3(new_uri)
198
-
199
- response = client.list_objects(Bucket=bucket, Prefix=old_uri)
209
+ response = client.list_objects(Bucket=bucket, Prefix=uri_for_s3(old_uri))
200
210
 
201
211
  for result in response.get("Contents", []):
202
212
  old_key = str(result["Key"])
@@ -212,7 +222,7 @@ def copy_assets(old_uri: str, new_uri: str) -> None:
212
222
  )
213
223
 
214
224
 
215
- def build_new_key(old_key: str, new_uri: str) -> str:
225
+ def build_new_key(old_key: str, new_uri: DocumentURIString) -> str:
216
226
  """Ensure that DOCX and PDF filenames are modified to reflect their new home
217
227
  as we get the name of the new S3 path"""
218
228
  old_filename = old_key.rsplit("/", 1)[-1]
@@ -224,7 +234,7 @@ def build_new_key(old_key: str, new_uri: str) -> str:
224
234
 
225
235
 
226
236
  def request_parse(
227
- uri: str,
237
+ uri: DocumentURIString,
228
238
  reference: Optional[str],
229
239
  parser_instructions: Optional[ParserInstructionsDict] = None,
230
240
  ) -> None:
@@ -14,6 +14,7 @@ declare variable $search_query as xs:string? external;
14
14
  let $number_marks_xslt := (
15
15
  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
16
16
  xmlns:uk="https://caselaw.nationalarchives.gov.uk/akn"
17
+ xmlns:akn="http://docs.oasis-open.org/legaldocml/ns/akn/3.0"
17
18
  version="2.0">
18
19
  <xsl:output method="xml" />
19
20
  <xsl:template match="@*|node()">
@@ -21,12 +22,15 @@ let $number_marks_xslt := (
21
22
  <xsl:apply-templates select="@*|node()"/>
22
23
  </xsl:copy>
23
24
  </xsl:template>
25
+ <xsl:template match="//akn:meta//uk:mark">
26
+ <xsl:apply-templates />
27
+ </xsl:template>
24
28
  <xsl:template match="uk:mark">
25
29
  <xsl:copy>
26
30
  <xsl:copy-of select="@*" />
27
31
  <xsl:attribute name="id">
28
32
  <xsl:text>mark_</xsl:text>
29
- <xsl:value-of select="count(preceding::uk:mark)"/>
33
+ <xsl:number count="//uk:mark" level="any" from="//*[ancestor::akn:meta]" />
30
34
  </xsl:attribute>
31
35
  <xsl:apply-templates />
32
36
  </xsl:copy>
@@ -62,5 +66,4 @@ let $transformed := if($search_query) then
62
66
  else
63
67
  $raw_xml
64
68
 
65
-
66
69
  return $transformed