ds-caselaw-marklogic-api-client 35.1.1__tar.gz → 36.0.1__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 (88) hide show
  1. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/PKG-INFO +2 -2
  2. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/pyproject.toml +4 -4
  3. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/factories.py +9 -6
  4. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/identifier_resolution.py +1 -1
  5. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/models/identifiers/__init__.py +7 -8
  6. ds_caselaw_marklogic_api_client-36.0.1/src/caselawclient/models/identifiers/exceptions.py +10 -0
  7. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/models/identifiers/neutral_citation.py +24 -2
  8. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/models/identifiers/unpacker.py +2 -1
  9. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/LICENSE.md +0 -0
  10. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/README.md +0 -0
  11. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/Client.py +0 -0
  12. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/__init__.py +0 -0
  13. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/client_helpers/__init__.py +0 -0
  14. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/client_helpers/search_helpers.py +0 -0
  15. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/content_hash.py +0 -0
  16. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/errors.py +0 -0
  17. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/models/__init__.py +0 -0
  18. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/models/documents/__init__.py +0 -0
  19. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/models/documents/body.py +0 -0
  20. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/models/documents/exceptions.py +0 -0
  21. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/models/documents/statuses.py +0 -0
  22. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/models/documents/transforms/html.xsl +0 -0
  23. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/models/documents/xml.py +0 -0
  24. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/models/identifiers/fclid.py +0 -0
  25. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/models/identifiers/press_summary_ncn.py +0 -0
  26. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/models/judgments.py +0 -0
  27. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/models/neutral_citation_mixin.py +0 -0
  28. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/models/parser_logs.py +0 -0
  29. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/models/press_summaries.py +0 -0
  30. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/models/utilities/__init__.py +0 -0
  31. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/models/utilities/aws.py +0 -0
  32. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/models/utilities/dates.py +0 -0
  33. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/models/utilities/move.py +0 -0
  34. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/py.typed +0 -0
  35. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/responses/__init__.py +0 -0
  36. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/responses/search_response.py +0 -0
  37. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/responses/search_result.py +0 -0
  38. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/responses/xsl/search_match.xsl +0 -0
  39. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/search_parameters.py +0 -0
  40. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/types.py +0 -0
  41. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xml_helpers.py +0 -0
  42. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/break_judgment_checkout.xqy +0 -0
  43. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/checkin_judgment.xqy +0 -0
  44. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/checkout_judgment.xqy +0 -0
  45. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/copy_document.xqy +0 -0
  46. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/delete_judgment.xqy +0 -0
  47. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/document_collections.xqy +0 -0
  48. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/document_exists.xqy +0 -0
  49. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/get_combined_stats_table.xqy +0 -0
  50. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/get_components_for_document.xqy +0 -0
  51. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/get_highest_enrichment_version.xqy +0 -0
  52. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/get_highest_parser_version.xqy +0 -0
  53. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/get_judgment.xqy +0 -0
  54. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/get_judgment_checkout_status.xqy +0 -0
  55. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/get_judgment_version.xqy +0 -0
  56. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/get_last_modified.xqy +0 -0
  57. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/get_next_document_sequence_number.xqy +0 -0
  58. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/get_pending_enrichment_for_version.xqy +0 -0
  59. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/get_pending_parse_for_version.xqy +0 -0
  60. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/get_properties_for_search_results.xqy +0 -0
  61. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/get_property.xqy +0 -0
  62. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/get_property_as_node.xqy +0 -0
  63. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/get_recently_enriched.xqy +0 -0
  64. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/get_recently_parsed.xqy +0 -0
  65. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/get_version_annotation.xqy +0 -0
  66. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/get_version_created.xqy +0 -0
  67. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/insert_document.xqy +0 -0
  68. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/list_judgment_versions.xqy +0 -0
  69. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/resolve_from_identifier_slug.xqy +0 -0
  70. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/resolve_from_identifier_value.xqy +0 -0
  71. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/set_boolean_property.xqy +0 -0
  72. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/set_metadata_citation.xqy +0 -0
  73. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/set_metadata_court.xqy +0 -0
  74. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/set_metadata_jurisdiction.xqy +0 -0
  75. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/set_metadata_name.xqy +0 -0
  76. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/set_metadata_this_uri.xqy +0 -0
  77. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/set_metadata_work_expression_date.xqy +0 -0
  78. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/set_property.xqy +0 -0
  79. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/set_property_as_node.xqy +0 -0
  80. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/update_document.xqy +0 -0
  81. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/update_locked_judgment.xqy +0 -0
  82. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/user_has_privilege.xqy +0 -0
  83. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/user_has_role.xqy +0 -0
  84. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/validate_all_documents.xqy +0 -0
  85. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/validate_document.xqy +0 -0
  86. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/xslt.xqy +0 -0
  87. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/src/caselawclient/xquery/xslt_transform.xqy +0 -0
  88. {ds_caselaw_marklogic_api_client-35.1.1 → ds_caselaw_marklogic_api_client-36.0.1}/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: 35.1.1
3
+ Version: 36.0.1
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
@@ -10,7 +10,7 @@ Classifier: Programming Language :: Python :: 3
10
10
  Classifier: Programming Language :: Python :: 3.10
11
11
  Classifier: Programming Language :: Python :: 3.11
12
12
  Requires-Dist: boto3 (>=1.26.112,<2.0.0)
13
- Requires-Dist: certifi (>=2025.1.31,<2025.2.0)
13
+ Requires-Dist: certifi (>=2025.4.26,<2025.5.0)
14
14
  Requires-Dist: charset-normalizer (>=3.0.0,<4.0.0)
15
15
  Requires-Dist: django-environ (>=0.12.0)
16
16
  Requires-Dist: ds-caselaw-utils (>=2.0.0,<3.0.0)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "ds-caselaw-marklogic-api-client"
3
- version = "35.1.1"
3
+ version = "36.0.1"
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"
@@ -12,7 +12,7 @@ packages = [
12
12
 
13
13
  [tool.poetry.dependencies]
14
14
  python = "^3.10.0"
15
- certifi = ">=2025.1.31,<2025.2.0"
15
+ certifi = ">=2025.4.26,<2025.5.0"
16
16
  charset-normalizer = "^3.0.0"
17
17
  django-environ = ">=0.12.0"
18
18
  idna = "^3.4"
@@ -33,11 +33,11 @@ sqids = "^0.5.0"
33
33
  [tool.poetry.group.dev.dependencies]
34
34
  coverage = "7.8.0"
35
35
  pytest = "8.3.5"
36
- beautifulsoup4 = "4.13.3"
36
+ beautifulsoup4 = "4.13.4"
37
37
  responses = "0.25.7"
38
38
  python-dotenv = "1.1.0"
39
39
  time-machine = "2.16.0"
40
- moto = {version = "5.1.3", extras = ["all"]}
40
+ moto = {version = "5.1.4", extras = ["all"]}
41
41
 
42
42
  [tool.poetry.group.docs]
43
43
  optional = true
@@ -85,7 +85,7 @@ class DocumentFactory:
85
85
  document.body = kwargs.pop("body") if "body" in kwargs else DocumentBodyFactory.build()
86
86
 
87
87
  if identifiers is None:
88
- document.identifiers.add(FindCaseLawIdentifier(value="a1b2c3"))
88
+ document.identifiers.add(FindCaseLawIdentifier(value="tn4t35ts"))
89
89
  else:
90
90
  for identifier in identifiers:
91
91
  document.identifiers.add(identifier)
@@ -146,15 +146,18 @@ class SearchResultMetadataFactory(SimpleFactory):
146
146
  class SearchResultFactory(SimpleFactory):
147
147
  target_class = SearchResult
148
148
 
149
- # "name_of_attribute": ("name of incoming param", "default value")
150
149
  PARAMS_MAP = {
151
- "uri": "test/2023/123",
150
+ "uri": "d-a1b2c3",
152
151
  "name": "Judgment v Judgement",
153
- "neutral_citation": "[2023] Test 123",
152
+ "neutral_citation": "[2025] UKSC 123",
154
153
  "court": "Court of Testing",
155
- "date": datetime.date(2023, 2, 3),
154
+ "date": datetime.datetime(2023, 2, 3),
155
+ "transformation_date": str(datetime.datetime(2023, 2, 3, 12, 34)),
156
156
  "metadata": SearchResultMetadataFactory.build(),
157
157
  "is_failure": False,
158
+ "matches": None,
159
+ "slug": "uksc/2025/1",
160
+ "content_hash": "ed7002b439e9ac845f22357d822bac1444730fbdb6016d3ec9432297b9ec9f73",
158
161
  }
159
162
 
160
163
 
@@ -173,7 +176,7 @@ class IdentifierResolutionFactory:
173
176
  "documents.compiled_url_slugs.identifier_uuid": resolution_uuid or "24b9a384-8bcf-4f20-996a-5c318f8dc657",
174
177
  "documents.compiled_url_slugs.document_uri": document_uri or "/ewca/civ/2003/547.xml",
175
178
  "documents.compiled_url_slugs.identifier_slug": identifier_slug or "ewca/civ/2003/54721",
176
- "documents.compiled_url_slugs.document_published": "true" if published else "false",
179
+ "documents.compiled_url_slugs.document_published": published,
177
180
  "documents.compiled_url_slugs.identifier_namespace": namespace or "ukncn",
178
181
  "documents.compiled_url_slugs.identifier_value": value or "[2003] EWCA 54721 (Civ)",
179
182
  }
@@ -45,7 +45,7 @@ class IdentifierResolution(NamedTuple):
45
45
  identifier_uuid=row["documents.compiled_url_slugs.identifier_uuid"],
46
46
  document_uri=MarkLogicDocumentURIString(row["documents.compiled_url_slugs.document_uri"]),
47
47
  identifier_slug=DocumentIdentifierSlug(row["documents.compiled_url_slugs.identifier_slug"]),
48
- document_published=row["documents.compiled_url_slugs.document_published"] == "true",
48
+ document_published=row["documents.compiled_url_slugs.document_published"],
49
49
  identifier_value=DocumentIdentifierValue(row["documents.compiled_url_slugs.identifier_value"]),
50
50
  identifier_namespace=identifier_namespace,
51
51
  identifier_type=IDENTIFIER_NAMESPACE_MAP[identifier_namespace],
@@ -6,6 +6,8 @@ from lxml import etree
6
6
 
7
7
  from caselawclient.types import DocumentIdentifierSlug, DocumentIdentifierValue
8
8
 
9
+ from .exceptions import IdentifierValidationException, UUIDMismatchError
10
+
9
11
  IDENTIFIER_PACKABLE_ATTRIBUTES: list[str] = [
10
12
  "uuid",
11
13
  "value",
@@ -18,14 +20,6 @@ IDENTIFIER_UNPACKABLE_ATTRIBUTES: list[str] = [
18
20
  ]
19
21
 
20
22
 
21
- class InvalidIdentifierXMLRepresentationException(Exception):
22
- pass
23
-
24
-
25
- class UUIDMismatchError(Exception):
26
- pass
27
-
28
-
29
23
  class IdentifierSchema(ABC):
30
24
  """
31
25
  A base class which describes what an identifier schema should look like.
@@ -89,6 +83,11 @@ class Identifier(ABC):
89
83
  return self.value
90
84
 
91
85
  def __init__(self, value: str, uuid: Optional[str] = None) -> None:
86
+ if not self.schema.validate_identifier(value=value):
87
+ raise IdentifierValidationException(
88
+ f'Identifier value "{value}" is not valid according to the {self.schema.name} schema.'
89
+ )
90
+
92
91
  self.value = DocumentIdentifierValue(value)
93
92
  if uuid:
94
93
  self.uuid = uuid
@@ -0,0 +1,10 @@
1
+ class InvalidIdentifierXMLRepresentationException(Exception):
2
+ pass
3
+
4
+
5
+ class UUIDMismatchError(Exception):
6
+ pass
7
+
8
+
9
+ class IdentifierValidationException(Exception):
10
+ pass
@@ -6,6 +6,7 @@ from ds_caselaw_utils.types import NeutralCitationString
6
6
  from caselawclient.types import DocumentIdentifierSlug
7
7
 
8
8
  from . import Identifier, IdentifierSchema
9
+ from .exceptions import IdentifierValidationException
9
10
 
10
11
  VALID_NCN_PATTERN = re.compile(r"(^\[([0-9]{4})\] ([a-zA-Z]+)(?: ([a-zA-Z]+))? ([0-9]+)(?: \(([a-zA-Z]+)\))?$)")
11
12
  """
@@ -23,6 +24,18 @@ TODO: When these capture groups are being used in anger (eg to build URL slugs)
23
24
  """
24
25
 
25
26
 
27
+ class NCNValidationException(IdentifierValidationException):
28
+ pass
29
+
30
+
31
+ class NCNDoesNotMatchExpectedPatternException(NCNValidationException):
32
+ pass
33
+
34
+
35
+ class NCNCannotConvertToValidURLSlugException(NCNValidationException):
36
+ pass
37
+
38
+
26
39
  class NeutralCitationNumberSchema(IdentifierSchema):
27
40
  """
28
41
  Identifier schema describing a Neutral Citation Number.
@@ -37,7 +50,16 @@ class NeutralCitationNumberSchema(IdentifierSchema):
37
50
 
38
51
  @classmethod
39
52
  def validate_identifier(cls, value: str) -> bool:
40
- return bool(VALID_NCN_PATTERN.match(value))
53
+ # Quick check to see if the NCN matches the expected pattern
54
+ if not bool(VALID_NCN_PATTERN.match(value)):
55
+ raise NCNDoesNotMatchExpectedPatternException(f"NCN '{value}' is not in the expected format")
56
+
57
+ # Can we convert this to a URL? neutral_url returns False if not.
58
+ # This functionally tests to see if the court exists, since only valid patterns (where we know how to match the court code) will convert
59
+ if not neutral_url(NeutralCitationString(value)):
60
+ raise NCNCannotConvertToValidURLSlugException(f"NCN '{value}' cannot be converted to an NCN-based URL slug")
61
+
62
+ return True
41
63
 
42
64
  @classmethod
43
65
  def compile_identifier_url_slug(cls, value: str) -> DocumentIdentifierSlug:
@@ -45,7 +67,7 @@ class NeutralCitationNumberSchema(IdentifierSchema):
45
67
  NeutralCitationString(value)
46
68
  ) # TODO: At some point this should move out of utils and into this class.
47
69
  if not ncn_based_uri_string:
48
- raise Exception(f"Unable to convert NCN {value} into NCN-based URL slug")
70
+ raise NCNCannotConvertToValidURLSlugException(f"NCN '{value}' cannot be converted to an NCN-based URL slug")
49
71
  return DocumentIdentifierSlug(ncn_based_uri_string)
50
72
 
51
73
 
@@ -3,7 +3,8 @@ from warnings import warn
3
3
 
4
4
  from lxml import etree
5
5
 
6
- from . import IDENTIFIER_UNPACKABLE_ATTRIBUTES, Identifier, Identifiers, InvalidIdentifierXMLRepresentationException
6
+ from . import IDENTIFIER_UNPACKABLE_ATTRIBUTES, Identifier, Identifiers
7
+ from .exceptions import InvalidIdentifierXMLRepresentationException
7
8
  from .fclid import FindCaseLawIdentifier
8
9
  from .neutral_citation import NeutralCitationNumber
9
10
  from .press_summary_ncn import PressSummaryRelatedNCNIdentifier