Skip to content

Commit

Permalink
Merge pull request #543 from nationalarchives/feature/grc-subdivisions
Browse files Browse the repository at this point in the history
Add methods to set/get jurisdiction of a document, for GRC subdivisions
  • Loading branch information
timcowlishaw authored Jan 31, 2024
2 parents 46cafbd + 491958d commit 458bf47
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog 1.0.0].
## Unreleased

- **Breaking:** `Client.get_pending_enrichment_for_version` now requires both a target enrichment version and a target parser version, and will not include documents which have not been parsed with the target version.
- **Feature:** Add accessors for judgment jurisdiction

## [Release 20.0.0]

Expand Down
18 changes: 18 additions & 0 deletions src/caselawclient/Client.py
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,24 @@ def set_document_court(

return self._send_to_eval(vars, "set_metadata_court.xqy")

def set_document_jurisdiction(
self, document_uri: DocumentURIString, content: str
) -> requests.Response:
uri = self._format_uri_for_marklogic(document_uri)
vars: query_dicts.SetMetadataJurisdictionDict = {"uri": uri, "content": content}
return self._send_to_eval(vars, "set_metadata_jurisdiction.xqy")

def set_document_court_and_jurisdiction(
self, document_uri: DocumentURIString, content: str
) -> requests.Response:
if "/" in content:
court, jurisdiction = re.split("\\s*/\\s*", content)
self.set_document_court(document_uri, court)
return self.set_document_jurisdiction(document_uri, jurisdiction)
else:
self.set_document_court(document_uri, content)
return self.set_document_jurisdiction(document_uri, "")

def set_judgment_this_uri(
self, judgment_uri: DocumentURIString
) -> requests.Response:
Expand Down
14 changes: 14 additions & 0 deletions src/caselawclient/models/documents.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,20 @@ def court(self) -> str:
},
)

@cached_property
def jurisdiction(self) -> str:
return self.xml.get_xpath_match_string(
"/akn:akomaNtoso/akn:*/akn:meta/akn:proprietary/uk:jurisdiction/text()",
{
"uk": "https://caselaw.nationalarchives.gov.uk/akn",
"akn": "http://docs.oasis-open.org/legaldocml/ns/akn/3.0",
},
)

@property
def court_and_jurisdiction(self) -> str:
return "/".join((self.court, self.jurisdiction))

@cached_property
def document_date_as_string(self) -> str:
return self.xml.get_xpath_match_string(
Expand Down
37 changes: 37 additions & 0 deletions src/caselawclient/xquery/set_metadata_jurisdiction.xqy
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
xquery version "1.0-ml";

declare namespace akn = "http://docs.oasis-open.org/legaldocml/ns/akn/3.0";
declare namespace uk = "https://caselaw.nationalarchives.gov.uk/akn";

declare variable $uri as xs:string external;
declare variable $content as xs:string external;
declare variable $proprietary-node := document($uri)/akn:akomaNtoso/akn:*/akn:meta/akn:proprietary;
declare variable $jurisdiction-node := $proprietary-node/uk:jurisdiction;

declare function local:delete($uri)
{
xdmp:node-delete($jurisdiction-node)
};

declare function local:edit($uri, $content)
{
xdmp:node-replace(
$jurisdiction-node,
<uk:jurisdiction>{$content}</uk:jurisdiction>
)
};

declare function local:add($uri, $content)
{
xdmp:node-insert-child(
$proprietary-node,
<uk:jurisdiction>{$content}</uk:jurisdiction>
)
};

if (fn:boolean(
cts:search(doc($uri),
cts:element-query(xs:QName('uk:jurisdiction'),cts:and-query(()))))) then
if ($content = "") then local:delete($uri) else local:edit($uri, $content)
else
local:add($uri, $content)
6 changes: 6 additions & 0 deletions src/caselawclient/xquery_type_dicts.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ class SetMetadataCourtDict(MarkLogicAPIDict):
uri: MarkLogicDocumentURIString


# set_metadata_jurisdiction.xqy
class SetMetadataJurisdictionDict(MarkLogicAPIDict):
content: str
uri: MarkLogicDocumentURIString


# set_metadata_name.xqy
class SetMetadataNameDict(MarkLogicAPIDict):
content: str
Expand Down
64 changes: 64 additions & 0 deletions tests/client/test_get_set_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,70 @@ def test_set_document_court(self):
)
assert mock_eval.call_args.kwargs["vars"] == json.dumps(expected_vars)

def test_set_document_jurisdiction(self):
with patch.object(self.client, "eval") as mock_eval:
uri = "judgment/uri"
content = "new jurisdiction"
expected_vars = {"uri": "/judgment/uri.xml", "content": content}
self.client.set_document_jurisdiction(uri, content)

assert mock_eval.call_args.args[0] == (
os.path.join(ROOT_DIR, "xquery", "set_metadata_jurisdiction.xqy")
)
assert mock_eval.call_args.kwargs["vars"] == json.dumps(expected_vars)

def test_set_document_court_and_jurisdiction_when_both_passed(self):
# It splits the provided value on '/'
# and sets both court and jurisdiction
with patch.object(self.client, "eval") as mock_eval:
uri = "judgment/uri"
court_content = "court"
jurisdiction_content = "jurisdiction"
court_expected_vars = {"uri": "/judgment/uri.xml", "content": court_content}
jurisdiction_expected_vars = {
"uri": "/judgment/uri.xml",
"content": jurisdiction_content,
}
self.client.set_document_court_and_jurisdiction(uri, "court/jurisdiction")

assert mock_eval.call_args_list[0].args[0] == (
os.path.join(ROOT_DIR, "xquery", "set_metadata_court.xqy")
)
assert mock_eval.call_args_list[0].kwargs["vars"] == json.dumps(
court_expected_vars
)

assert mock_eval.call_args_list[1].args[0] == (
os.path.join(ROOT_DIR, "xquery", "set_metadata_jurisdiction.xqy")
)
assert mock_eval.call_args_list[1].kwargs["vars"] == json.dumps(
jurisdiction_expected_vars
)

def test_set_document_court_and_jurisdiction_when_just_court_passed(self):
# When no jurisdiction is included
# It sets the court and deletes the jurisdiction.
with patch.object(self.client, "eval") as mock_eval:
uri = "judgment/uri"
content = "court"
court_expected_vars = {"uri": "/judgment/uri.xml", "content": content}
jurisdiction_expected_vars = {"uri": "/judgment/uri.xml", "content": ""}
self.client.set_document_court_and_jurisdiction(uri, content)

assert mock_eval.call_args_list[0].args[0] == (
os.path.join(ROOT_DIR, "xquery", "set_metadata_court.xqy")
)
assert mock_eval.call_args_list[0].kwargs["vars"] == json.dumps(
court_expected_vars
)

assert mock_eval.call_args_list[1].args[0] == (
os.path.join(ROOT_DIR, "xquery", "set_metadata_jurisdiction.xqy")
)
assert mock_eval.call_args_list[1].kwargs["vars"] == json.dumps(
jurisdiction_expected_vars
)

def test_set_document_date(self):
with patch.object(self.client, "eval") as mock_eval:
uri = "judgment/uri"
Expand Down
61 changes: 61 additions & 0 deletions tests/models/test_documents.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,67 @@ def test_court(self, opening_tag, closing_tag, mock_api_client):
"test/1234", show_unpublished=True
)

@pytest.mark.parametrize(
"opening_tag, closing_tag",
[
("judgment", "judgment"),
('doc name="pressSummary"', "doc"),
],
)
def test_jurisdiction(self, opening_tag, closing_tag, mock_api_client):
mock_api_client.get_judgment_xml_bytestring.return_value = f"""
<akomaNtoso xmlns:uk="https://caselaw.nationalarchives.gov.uk/akn"
xmlns="http://docs.oasis-open.org/legaldocml/ns/akn/3.0">
<{opening_tag}>
<meta>
<proprietary>
<uk:jurisdiction>SoftwareTesting</uk:jurisdiction>
</proprietary>
</meta>
</{closing_tag}>
</akomaNtoso>
""".encode(
"utf-8"
)

document = Document("test/1234", mock_api_client)

assert document.jurisdiction == "SoftwareTesting"
mock_api_client.get_judgment_xml_bytestring.assert_called_once_with(
"test/1234", show_unpublished=True
)

@pytest.mark.parametrize(
"opening_tag, closing_tag",
[
("judgment", "judgment"),
('doc name="pressSummary"', "doc"),
],
)
def test_court_and_jurisdiction(self, opening_tag, closing_tag, mock_api_client):
mock_api_client.get_judgment_xml_bytestring.return_value = f"""
<akomaNtoso xmlns:uk="https://caselaw.nationalarchives.gov.uk/akn"
xmlns="http://docs.oasis-open.org/legaldocml/ns/akn/3.0">
<{opening_tag}>
<meta>
<proprietary>
<uk:court>UKFTT-CourtOfTesting</uk:court>
<uk:jurisdiction>SoftwareTesting</uk:jurisdiction>
</proprietary>
</meta>
</{closing_tag}>
</akomaNtoso>
""".encode(
"utf-8"
)

document = Document("test/1234", mock_api_client)

assert document.court_and_jurisdiction == "UKFTT-CourtOfTesting/SoftwareTesting"
mock_api_client.get_judgment_xml_bytestring.assert_called_once_with(
"test/1234", show_unpublished=True
)

@pytest.mark.parametrize(
"opening_tag, closing_tag",
[
Expand Down

0 comments on commit 458bf47

Please sign in to comment.