diff --git a/src/caselawclient/factories.py b/src/caselawclient/factories.py index e22d0293..c3360245 100644 --- a/src/caselawclient/factories.py +++ b/src/caselawclient/factories.py @@ -9,6 +9,8 @@ from caselawclient.identifier_resolution import IdentifierResolution, IdentifierResolutions from caselawclient.models.documents import Document from caselawclient.models.documents.body import DocumentBody +from caselawclient.models.identifiers import Identifier +from caselawclient.models.identifiers.fclid import FindCaseLawIdentifier from caselawclient.models.judgments import Judgment from caselawclient.models.press_summaries import PressSummary from caselawclient.responses.search_result import SearchResult, SearchResultMetadata @@ -68,8 +70,12 @@ def build( cls, uri: DocumentURIString = DocumentURIString("test/2023/123"), api_client: Optional[MarklogicApiClient] = None, + identifiers: Optional[list[Identifier]] = None, **kwargs: Any, ) -> target_class: + def _fake_linked_documents(*args: Any, **kwargs: Any) -> list["Document"]: + return [document] + if not api_client: api_client = Mock(spec=MarklogicApiClient) api_client.get_judgment_xml_bytestring.return_value = DEFAULT_DOCUMENT_BODY_XML.encode(encoding="utf-8") @@ -78,6 +84,14 @@ def build( document = cls.target_class(uri, api_client=api_client) document.body = kwargs.pop("body") if "body" in kwargs else DocumentBodyFactory.build() + if identifiers is None: + document.identifiers.add(FindCaseLawIdentifier(value="a1b2c3")) + else: + for identifier in identifiers: + document.identifiers.add(identifier) + + setattr(document, "linked_documents", _fake_linked_documents) + for param_name, default_value in cls.PARAMS_MAP.items(): value = kwargs.get(param_name, default_value) setattr(document, param_name, value) diff --git a/src/caselawclient/models/documents/__init__.py b/src/caselawclient/models/documents/__init__.py index af2ffac3..ef711056 100644 --- a/src/caselawclient/models/documents/__init__.py +++ b/src/caselawclient/models/documents/__init__.py @@ -161,7 +161,19 @@ def public_uri(self) -> str: """ :return: The absolute, public URI at which a copy of this document can be found """ - return f"https://caselaw.nationalarchives.gov.uk/{self.uri}" + return f"https://caselaw.nationalarchives.gov.uk/{self.slug}" + + @cached_property + def slug(self) -> str: + """ + :return: The best public-facing URL for the judgment, which is the slug + of the most-preferred identifier, which should either be an NCN or fclid. + """ + preferred_identifier = self.identifiers.preferred() + if preferred_identifier: + return preferred_identifier.url_slug + msg = f"No preferred identifier exists for {self.uri}" + raise RuntimeError(msg) @cached_property def is_published(self) -> bool: @@ -497,7 +509,7 @@ def __getattr__(self, name: str) -> Any: raise AttributeError(f"Neither 'Document' nor 'DocumentBody' objects have an attribute '{name}'") def linked_document_resolutions(self, namespaces: list[str], only_published: bool = True) -> IdentifierResolutions: - """Get documents which share the same neutral citation as this document.""" + """Get document resolutions which share the same neutral citation as this document.""" if not hasattr(self, "neutral_citation") or not self.neutral_citation: return IdentifierResolutions([]) @@ -513,3 +525,10 @@ def linked_document_resolutions(self, namespaces: list[str], only_published: boo if resolution.document_uri != self.uri.as_marklogic() and resolution.identifier_namespace in namespaces ] ) + + def linked_documents(self, namespaces: list[str], only_published: bool = True) -> list["Document"]: + resolutions = self.linked_document_resolutions(namespaces=namespaces, only_published=only_published) + return [ + Document(resolution.document_uri.as_document_uri(), api_client=self.api_client) + for resolution in resolutions + ] diff --git a/tests/models/documents/test_document_identifiers.py b/tests/models/documents/test_document_identifiers.py index 9e6875d1..98175004 100644 --- a/tests/models/documents/test_document_identifiers.py +++ b/tests/models/documents/test_document_identifiers.py @@ -8,7 +8,7 @@ class TestDocumentIdentifiers: def test_add_identifiers(self): - document = DocumentFactory.build() + document = DocumentFactory.build(identifiers=[]) identifier_1 = TestIdentifier(uuid="id-1", value="TEST-123") identifier_2 = TestIdentifier(uuid="id-2", value="TEST-456") @@ -26,7 +26,7 @@ def test_validate(self): identifiers.validate() def test_identifiers_as_etree(self): - document = DocumentFactory.build() + document = DocumentFactory.build(identifiers=[]) identifier_1 = TestIdentifier(uuid="e28e3ef1-85ed-4997-87ee-e7428a6cc02e", value="TEST-123") identifier_2 = TestIdentifier(uuid="14ce4b3b-03c8-44f9-a29e-e02ce35fe136", value="TEST-456") diff --git a/tests/models/documents/test_documents.py b/tests/models/documents/test_documents.py index 0e695a21..5c192ffe 100644 --- a/tests/models/documents/test_documents.py +++ b/tests/models/documents/test_documents.py @@ -38,10 +38,9 @@ def test_has_sensible_repr_without_name_or_subclass(self, mock_api_client): document = Document(DocumentURIString("test/1234"), mock_api_client) assert str(document) == "" - def test_public_uri(self, mock_api_client): - document = Document(DocumentURIString("test/1234"), mock_api_client) - - assert document.public_uri == "https://caselaw.nationalarchives.gov.uk/test/1234" + def test_public_uri(self): + document = DocumentFactory.build() + assert document.public_uri == "https://caselaw.nationalarchives.gov.uk/tna.a1b2c3" def test_document_exists_check(self, mock_api_client): mock_api_client.document_exists.return_value = False