ds-caselaw-marklogic-api-client 17.2.0__tar.gz → 17.3.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 (59) hide show
  1. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/PKG-INFO +2 -2
  2. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/pyproject.toml +4 -2
  3. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/models/documents.py +45 -9
  4. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/models/utilities/aws.py +61 -7
  5. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/search_parameters.py +2 -0
  6. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/LICENSE.md +0 -0
  7. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/README.md +0 -0
  8. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/Client.py +0 -0
  9. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/__init__.py +0 -0
  10. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/client_helpers/__init__.py +0 -0
  11. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/client_helpers/search_helpers.py +0 -0
  12. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/content_hash.py +0 -0
  13. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/errors.py +0 -0
  14. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/models/__init__.py +0 -0
  15. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/models/judgments.py +0 -0
  16. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/models/neutral_citation_mixin.py +0 -0
  17. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/models/press_summaries.py +0 -0
  18. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/models/utilities/__init__.py +0 -0
  19. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/models/utilities/move.py +0 -0
  20. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/py.typed +0 -0
  21. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/responses/__init__.py +0 -0
  22. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/responses/search_response.py +0 -0
  23. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/responses/search_result.py +0 -0
  24. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/responses/xsl/search_match.xsl +0 -0
  25. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xml_helpers.py +0 -0
  26. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xml_tools.py +0 -0
  27. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/break_judgment_checkout.xqy +0 -0
  28. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/checkin_judgment.xqy +0 -0
  29. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/checkout_judgment.xqy +0 -0
  30. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/copy_document.xqy +0 -0
  31. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/delete_judgment.xqy +0 -0
  32. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/document_collections.xqy +0 -0
  33. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/document_exists.xqy +0 -0
  34. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/get_combined_stats_table.xqy +0 -0
  35. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/get_judgment.xqy +0 -0
  36. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/get_judgment_checkout_status.xqy +0 -0
  37. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/get_judgment_version.xqy +0 -0
  38. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/get_last_modified.xqy +0 -0
  39. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/get_properties_for_search_results.xqy +0 -0
  40. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/get_property.xqy +0 -0
  41. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/get_version_annotation.xqy +0 -0
  42. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/get_version_created.xqy +0 -0
  43. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/insert_document.xqy +0 -0
  44. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/list_judgment_versions.xqy +0 -0
  45. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/set_boolean_property.xqy +0 -0
  46. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/set_metadata_citation.xqy +0 -0
  47. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/set_metadata_court.xqy +0 -0
  48. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/set_metadata_name.xqy +0 -0
  49. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/set_metadata_this_uri.xqy +0 -0
  50. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/set_metadata_work_expression_date.xqy +0 -0
  51. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/set_property.xqy +0 -0
  52. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/update_document.xqy +0 -0
  53. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/update_locked_judgment.xqy +0 -0
  54. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/user_has_privilege.xqy +0 -0
  55. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/user_has_role.xqy +0 -0
  56. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/validate_all_documents.xqy +0 -0
  57. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/xslt.xqy +0 -0
  58. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.0}/src/caselawclient/xquery/xslt_transform.xqy +0 -0
  59. {ds_caselaw_marklogic_api_client-17.2.0 → ds_caselaw_marklogic_api_client-17.3.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: 17.2.0
3
+ Version: 17.3.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
@@ -14,7 +14,7 @@ Requires-Dist: boto3 (>=1.26.112,<2.0.0)
14
14
  Requires-Dist: certifi (>=2022.12.7,<2024.0.0)
15
15
  Requires-Dist: charset-normalizer (>=3.0.0,<4.0.0)
16
16
  Requires-Dist: django-environ (>=0.11.0,<0.12.0)
17
- Requires-Dist: ds-caselaw-utils (>=1.0.0,<2.0.0)
17
+ Requires-Dist: ds-caselaw-utils (>=1.3.0,<2.0.0)
18
18
  Requires-Dist: idna (>=3.4,<4.0)
19
19
  Requires-Dist: lxml (>=4.9.2,<5.0.0)
20
20
  Requires-Dist: memoization (>=0.4.0,<0.5.0)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "ds-caselaw-marklogic-api-client"
3
- version = "17.2.0"
3
+ version = "17.3.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"
@@ -21,7 +21,7 @@ requests-toolbelt = ">=0.10.1,<1.1.0"
21
21
  urllib3 = "^1.26.15"
22
22
  memoization = "^0.4.0"
23
23
  lxml = "^4.9.2"
24
- ds-caselaw-utils = "^1.0.0"
24
+ ds-caselaw-utils = "^1.3.0"
25
25
  boto3 = "^1.26.112"
26
26
  typing-extensions = "^4.7.1"
27
27
  mypy-boto3-s3 = "^1.26.104"
@@ -47,3 +47,5 @@ build-backend = "poetry.core.masonry.api"
47
47
  markers = [
48
48
  "write: the test deliberately changes the Marklogic DB')",
49
49
  ]
50
+
51
+ filterwarnings = ["ignore::DeprecationWarning"]
@@ -20,11 +20,13 @@ from ..errors import (
20
20
  from ..xml_helpers import get_xpath_match_string, get_xpath_match_strings
21
21
  from .utilities import VersionsDict, get_judgment_root, render_versions
22
22
  from .utilities.aws import (
23
+ ParserInstructionsDict,
24
+ announce_document_event,
23
25
  delete_documents_from_private_bucket,
24
26
  generate_docx_url,
25
27
  generate_pdf_url,
26
- notify_changed,
27
28
  publish_documents,
29
+ request_parse,
28
30
  unpublish_documents,
29
31
  uri_for_s3,
30
32
  )
@@ -448,9 +450,12 @@ class Document:
448
450
  return DOCUMENT_STATUS_NEW
449
451
 
450
452
  def enrich(self) -> None:
451
- notify_changed(
453
+ """
454
+ Announces to the ANNOUNCE SNS that the document is waiting to be enriched.
455
+ """
456
+ announce_document_event(
452
457
  uri=self.uri,
453
- status="published",
458
+ status="enrich",
454
459
  enrich=True,
455
460
  )
456
461
 
@@ -464,20 +469,19 @@ class Document:
464
469
 
465
470
  publish_documents(uri_for_s3(self.uri))
466
471
  self.api_client.set_published(self.uri, True)
467
- notify_changed(
472
+ announce_document_event(
468
473
  uri=self.uri,
469
- status="published",
470
- enrich=True,
474
+ status="publish",
471
475
  )
476
+ self.enrich()
472
477
 
473
478
  def unpublish(self) -> None:
474
479
  self.api_client.break_checkout(self.uri)
475
480
  unpublish_documents(uri_for_s3(self.uri))
476
481
  self.api_client.set_published(self.uri, False)
477
- notify_changed(
482
+ announce_document_event(
478
483
  uri=self.uri,
479
- status="not published",
480
- enrich=False,
484
+ status="unpublish",
481
485
  )
482
486
 
483
487
  def hold(self) -> None:
@@ -520,3 +524,35 @@ class Document:
520
524
 
521
525
  def move(self, new_citation: str) -> None:
522
526
  self.api_client.update_document_uri(self.uri, new_citation)
527
+
528
+ def reparse(self) -> None:
529
+ "Send an SNS notification that triggers reparsing, also sending all editor-modifiable metadata and URI"
530
+
531
+ parser_type_noun = {"judgment": "judgment", "press summary": "pressSummary"}[
532
+ self.document_noun
533
+ ]
534
+ checked_date = (
535
+ self.document_date_as_string
536
+ if self.document_date_as_string > "1001"
537
+ else None
538
+ )
539
+
540
+ # the keys of parser_instructions should exactly match the parser output
541
+ # in the *-metadata.json files by the parser. Whilst typically empty
542
+ # values are "" from the API, we should pass None instead in this case.
543
+
544
+ parser_instructions: ParserInstructionsDict = {
545
+ "name": self.name or None,
546
+ "cite": self.best_human_identifier or None,
547
+ "court": self.court or None,
548
+ "date": checked_date,
549
+ "uri": self.uri,
550
+ "documentType": parser_type_noun,
551
+ "published": self.is_published,
552
+ }
553
+
554
+ request_parse(
555
+ uri=self.uri,
556
+ reference=self.consignment_reference,
557
+ parser_instructions=parser_instructions,
558
+ )
@@ -1,6 +1,8 @@
1
+ import datetime
1
2
  import json
2
3
  import logging
3
- from typing import Any, Literal, Union, overload
4
+ import uuid
5
+ from typing import Any, Literal, Optional, TypedDict, Union, overload
4
6
 
5
7
  import boto3
6
8
  import botocore.client
@@ -9,10 +11,21 @@ from mypy_boto3_s3.client import S3Client
9
11
  from mypy_boto3_s3.type_defs import CopySourceTypeDef, ObjectIdentifierTypeDef
10
12
  from mypy_boto3_sns.client import SNSClient
11
13
  from mypy_boto3_sns.type_defs import MessageAttributeValueTypeDef
14
+ from typing_extensions import NotRequired
12
15
 
13
16
  env = environ.Env()
14
17
 
15
18
 
19
+ class ParserInstructionsDict(TypedDict):
20
+ name: NotRequired[Optional[str]]
21
+ cite: NotRequired[Optional[str]]
22
+ court: NotRequired[Optional[str]]
23
+ date: NotRequired[Optional[str]]
24
+ uri: NotRequired[Optional[str]]
25
+ documentType: NotRequired[Optional[str]]
26
+ published: NotRequired[bool]
27
+
28
+
16
29
  @overload
17
30
  def create_aws_client(service: Literal["s3"]) -> S3Client:
18
31
  ...
@@ -64,10 +77,14 @@ def generate_signed_asset_url(key: str) -> str:
64
77
  )
65
78
 
66
79
 
67
- def generate_docx_url(uri: str) -> str:
68
- key = f'{uri}/{uri.replace("/", "_")}.docx'
80
+ def generate_docx_key(uri: str) -> str:
81
+ """from a canonical caselaw URI (eat/2022/1) return the S3 key of the associated docx"""
82
+ return f'{uri}/{uri.replace("/", "_")}.docx'
69
83
 
70
- return generate_signed_asset_url(key)
84
+
85
+ def generate_docx_url(uri: str) -> str:
86
+ """from a canonical caselaw URI (eat/2022/1) return a signed S3 link for the front end"""
87
+ return generate_signed_asset_url(generate_docx_key(uri))
71
88
 
72
89
 
73
90
  def generate_pdf_url(uri: str) -> str:
@@ -110,7 +127,7 @@ def publish_documents(uri: str) -> None:
110
127
 
111
128
  if not key.endswith("parser.log") and not key.endswith(".tar.gz"):
112
129
  source: CopySourceTypeDef = {"Bucket": private_bucket, "Key": key}
113
- extra_args = {"ACL": "public-read"}
130
+ extra_args: dict[str, str] = {}
114
131
  try:
115
132
  client.copy(source, public_bucket, key, extra_args)
116
133
  except botocore.client.ClientError as e:
@@ -127,7 +144,7 @@ def delete_documents_from_private_bucket(uri: str) -> None:
127
144
  delete_from_bucket(uri, env("PRIVATE_ASSET_BUCKET"))
128
145
 
129
146
 
130
- def notify_changed(uri: str, status: str, enrich: bool = False) -> None:
147
+ def announce_document_event(uri: str, status: str, enrich: bool = False) -> None:
131
148
  client = create_sns_client()
132
149
 
133
150
  message_attributes: dict[str, MessageAttributeValueTypeDef] = {}
@@ -146,7 +163,7 @@ def notify_changed(uri: str, status: str, enrich: bool = False) -> None:
146
163
  }
147
164
 
148
165
  client.publish(
149
- TopicArn=env("SNS_TOPIC"),
166
+ TopicArn=env("SNS_TOPIC"), # this is the ANNOUNCE SNS topic
150
167
  Message=json.dumps({"uri_reference": uri, "status": status}),
151
168
  Subject=f"Updated: {uri} {status}",
152
169
  MessageAttributes=message_attributes,
@@ -189,3 +206,40 @@ def build_new_key(old_key: str, new_uri: str) -> str:
189
206
  return f"{new_uri}/{new_filename}.{old_filename.split('.')[-1]}"
190
207
  else:
191
208
  return f"{new_uri}/{old_filename}"
209
+
210
+
211
+ def request_parse(
212
+ uri: str,
213
+ reference: Optional[str],
214
+ parser_instructions: Optional[ParserInstructionsDict] = None,
215
+ ) -> None:
216
+ client = create_sns_client()
217
+
218
+ if parser_instructions is None:
219
+ parser_instructions = ParserInstructionsDict({})
220
+
221
+ message_to_send = {
222
+ "properties": {
223
+ "messageType": "uk.gov.nationalarchives.da.messages.request.courtdocument.parse.RequestCourtDocumentParse",
224
+ "timestamp": datetime.datetime.now(datetime.timezone.utc)
225
+ .isoformat()
226
+ .replace("+00:00", "Z"),
227
+ "function": "fcl-judgment-parse-request",
228
+ "producer": "FCL",
229
+ "executionId": f"fcl_ex_id_{uuid.uuid4()}",
230
+ "parentExecutionId": None,
231
+ },
232
+ "parameters": {
233
+ "s3Bucket": env("PRIVATE_ASSET_BUCKET"),
234
+ "s3Key": generate_docx_key(uri),
235
+ "reference": reference or f"FCL-{uuid.uuid4()}",
236
+ "originator": "FCL",
237
+ "parserInstructions": parser_instructions,
238
+ },
239
+ }
240
+
241
+ client.publish(
242
+ TopicArn=env("REPARSE_SNS_TOPIC"),
243
+ Message=json.dumps(message_to_send),
244
+ Subject=f"Reparse request: {uri}",
245
+ )
@@ -73,6 +73,8 @@ class SearchParameters:
73
73
  "ewhc/kb": "ewhc/qb",
74
74
  "ewhc/scco": "ewhc/costs",
75
75
  "ewhc/costs": "ewhc/scco",
76
+ "ukait": "ukut/iac",
77
+ "ukut/iac": "ukait",
76
78
  }
77
79
  alternative_court_names = set()
78
80
  for primary_name, secondary_name in ALTERNATIVE_COURT_NAMES_MAP.items():