From 7434c6fb81aa281b194d175787f11966f66730a1 Mon Sep 17 00:00:00 2001 From: Alex Nelson Date: Tue, 12 Mar 2024 14:26:06 -0400 Subject: [PATCH 1/5] Add and confirm prefix customization; start doctests This patch is an isolated and expanded change drawn from PR 38. This patch was written to integrate into the current class hierarchy without disruption to existing code. This patch does not necessarily indicate agreement with the current class hierarchy. A follow-on patch will regenerate Make-managed files. References: * https://github.com/casework/CASE-Mapping-Python/pull/38 Signed-off-by: Alex Nelson --- .gitignore | 1 + Makefile | 23 ++++++++++++++++++++-- case_mapping/base.py | 35 ++++++++++++++++++++++++++++++++-- case_mapping/uco/core.py | 19 ++++++++++++++++-- case_mapping/uco/observable.py | 13 ++++++++----- 5 files changed, 80 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index ad89e2d..2d7de5f 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ __pycache__/ # Build Artifacts build/ dist/ +case.ttl diff --git a/Makefile b/Makefile index 8abb4e9..1c1326b 100644 --- a/Makefile +++ b/Makefile @@ -81,7 +81,26 @@ case.jsonld: \ _$@ mv _$@ $@ +case.ttl: \ + case.jsonld + source venv/bin/activate \ + && rdfpipe \ + --output-format turtle \ + $< \ + > _$@ + source venv/bin/activate \ + && case_validate \ + _$@ + @# In instances where graph nodes omit use of a prefix, a 'default' prefix-base is used that incorporates the local directory as a file URL. This is likely to be an undesired behavior, so for the generated example JSON-LD in the top source directory, check that "file:///" doesn't start any of the graph individuals' IRIs. + test \ + 0 \ + -eq \ + $$(grep 'file:' _$@ | wc -l) \ + || ( echo "ERROR:Some graph IRIs do not supply a resolving prefix. Look for the string 'file:///' in the file _$@ to see these instances." ; exit 1) + mv _$@ $@ + check: \ - all + all \ + case.ttl source venv/bin/activate \ - && poetry run pytest + && poetry run pytest --doctest-modules diff --git a/case_mapping/base.py b/case_mapping/base.py index 2f789f6..ffc7b9a 100644 --- a/case_mapping/base.py +++ b/case_mapping/base.py @@ -1,5 +1,6 @@ import json from datetime import datetime +from typing import Any from cdo_local_uuid import local_uuid @@ -20,8 +21,35 @@ def wrapper(self, *args, **kwargs): class FacetEntity(dict): - def __init__(self): - self["@id"] = str(local_uuid()) + def __init__( + self, + *args: Any, + prefix_iri: str = "http://example.org/kb/", + prefix_label: str = "kb", + **kwargs: Any, + ) -> None: + """ + :param prefix_iri: The IRI to be concatenated with the prefixed name's local part in order to form the node's absolute IRI. + :param prefix_label: The prefix separated from the compact IRI's local name by a colon. + + References + ========== + + .. [#turtle_prefixed_name] https://www.w3.org/TR/turtle/#prefixed-name + + Examples + ======== + + When instantiating a ``FacetEntity``, the JSON dictionary's ``@id`` key will start with the object's ``prefix_label``. + + >>> x = FacetEntity() + >>> assert x["@id"][0:3] == "kb:" + >>> y = FacetEntity(prefix_label="ex") + >>> assert y["@id"][0:3] == "ex:" + """ + self.prefix_iri = prefix_iri + self.prefix_label = prefix_label + self["@id"] = prefix_label + ":" + str(local_uuid()) def __str__(self): return json.dumps(self, indent=4) @@ -159,6 +187,9 @@ def __handle_var_type_errors(var_name, var_val, expected_type): class ObjectEntity(FacetEntity): + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + @unpack_args_array def append_facets(self, *args): """ diff --git a/case_mapping/uco/core.py b/case_mapping/uco/core.py index 29a57ca..d59288c 100644 --- a/case_mapping/uco/core.py +++ b/case_mapping/uco/core.py @@ -1,3 +1,5 @@ +from typing import Any + from ..base import ObjectEntity, unpack_args_array @@ -8,11 +10,13 @@ def __init__( uco_core_name=None, spec_version=None, description=None, - ): + *args: Any, + **kwargs: Any, + ) -> None: """ The main CASE Object for representing a case and its activities and objects. """ - super().__init__() + super().__init__(*args, **kwargs) self.build = [] self["@context"] = { "@vocab": "http://caseontology.org/core#", @@ -31,6 +35,17 @@ def __init__( "uco-vocabulary": "https://ontology.unifiedcyberontology.org/uco/vocabulary/", "xsd": "http://www.w3.org/2001/XMLSchema#", } + + # Assign caller-selectible prefix label and IRI, after checking + # for conflicts with hard-coded prefixes. + # https://www.w3.org/TR/turtle/#prefixed-name + if self.prefix_label in self["@context"]: + raise ValueError( + "Requested prefix label already in use in hard-coded dictionary: '%s'. Please revise caller to use another label." + % self.prefix_label + ) + self["@context"][self.prefix_label] = self.prefix_iri + self["@type"] = "uco-core:Bundle" self._str_vars( **{ diff --git a/case_mapping/uco/observable.py b/case_mapping/uco/observable.py index 2fb00ba..58e347d 100644 --- a/case_mapping/uco/observable.py +++ b/case_mapping/uco/observable.py @@ -269,7 +269,10 @@ def __init__( } if hash_method is not None or hash_value is not None or hash_value != "-": - data = {"@id": str(local_uuid()), "@type": "uco-types:Hash"} + data = { + "@id": self.prefix_label + ":" + str(local_uuid()), + "@type": "uco-types:Hash", + } if hash_method is not None: data["uco-types:hashMethod"] = { "@type": "uco-vocabulary:HashNameVocab", @@ -416,7 +419,7 @@ def __init__(self, browser=None, history_entries=None): self["uco-observable:urlHistoryEntry"] = [] for entry in history_entries: history_entry = {} - history_entry["@id"] = local_uuid() + history_entry["@id"] = self.prefix_label + ":" + local_uuid() history_entry["@type"] = "uco-observable:URLHistoryEntry" for key, var in entry.items(): if key in keys_str: @@ -858,14 +861,14 @@ def __init__(self, **kwargs): self["@type"] = "uco-observable:EXIFFacet" self["uco-observable:exifData"] = { - "@id": str(local_uuid()), + "@id": self.prefix_label + ":" + str(local_uuid()), "@type": "uco-types:ControlledDictionary", "uco-types:entry": [], } for k, v in kwargs.items(): if v not in ["", " "]: item = { - "@id": str(local_uuid()), + "@id": self.prefix_label + ":" + str(local_uuid()), "@type": "uco-types:ControlledDictionaryEntry", "uco-types:key": k, "uco-types:value": v, @@ -1356,7 +1359,7 @@ def __init__( self._node_reference_vars(**{"uco-observable:participant": participants}) self["uco-observable:messageThread"] = { - "@id": str(local_uuid()), + "@id": self.prefix_label + ":" + local_uuid(), "@type": "uco-types:Thread", } From cd887f8b30525fcdbaaf1cb64fb218420a13c047 Mon Sep 17 00:00:00 2001 From: Alex Nelson Date: Tue, 12 Mar 2024 14:37:36 -0400 Subject: [PATCH 2/5] Regenerate Make-managed files Signed-off-by: Alex Nelson --- case.jsonld | 191 ++++++++++++++++++++++++++-------------------------- 1 file changed, 96 insertions(+), 95 deletions(-) diff --git a/case.jsonld b/case.jsonld index f87e17a..2e0aafe 100644 --- a/case.jsonld +++ b/case.jsonld @@ -1,5 +1,5 @@ { - "@id": "aef8e4c4-db83-59fd-8f71-b65cd7676c0a", + "@id": "kb:aef8e4c4-db83-59fd-8f71-b65cd7676c0a", "@context": { "@vocab": "http://caseontology.org/core#", "case-investigation": "https://ontology.caseontology.org/case/investigation/", @@ -15,36 +15,37 @@ "uco-tool": "https://ontology.unifiedcyberontology.org/uco/tool/", "uco-types": "https://ontology.unifiedcyberontology.org/uco/types/", "uco-vocabulary": "https://ontology.unifiedcyberontology.org/uco/vocabulary/", - "xsd": "http://www.w3.org/2001/XMLSchema#" + "xsd": "http://www.w3.org/2001/XMLSchema#", + "kb": "http://example.org/kb/" }, "@type": "uco-core:Bundle", "uco-core:description": "An Example Case File", "uco-core:object": [ { - "@id": "307df50e-0116-5c51-904c-d5aa69279018", + "@id": "kb:307df50e-0116-5c51-904c-d5aa69279018", "@type": "uco-identity:Organization", "uco-core:name": "Nikon" }, { - "@id": "1ccd06e1-1a39-53c2-8e70-86ad7c48ec5c", + "@id": "kb:1ccd06e1-1a39-53c2-8e70-86ad7c48ec5c", "@type": "uco-observable:ObservableObject", "uco-core:hasFacet": [ { - "@id": "e26d7f7d-081c-58e5-8990-77ec13d60d89", + "@id": "kb:e26d7f7d-081c-58e5-8990-77ec13d60d89", "@type": "uco-observable:DeviceFacet", "uco-observable:manufacturer": { - "@id": "307df50e-0116-5c51-904c-d5aa69279018" + "@id": "kb:307df50e-0116-5c51-904c-d5aa69279018" }, "uco-observable:model": "D750" } ] }, { - "@id": "fa07818e-5832-5d5f-81b4-f7e143e98252", + "@id": "kb:fa07818e-5832-5d5f-81b4-f7e143e98252", "@type": "uco-observable:ObservableObject", "uco-core:hasFacet": [ { - "@id": "9ab260ac-cdf5-5524-9047-3ea85ebfb6e2", + "@id": "kb:9ab260ac-cdf5-5524-9047-3ea85ebfb6e2", "@type": "uco-observable:FileFacet", "uco-observable:fileSystemType": "EXT4", "uco-observable:fileName": "IMG_0123.jpg", @@ -56,7 +57,7 @@ } }, { - "@id": "09cab366-d82b-57f8-a94c-9814bf7ef63d", + "@id": "kb:09cab366-d82b-57f8-a94c-9814bf7ef63d", "@type": "uco-observable:ContentDataFacet", "uco-observable:magicNumber": "/9j/ww==", "uco-observable:mimeType": "image/jpg", @@ -71,7 +72,7 @@ }, "uco-observable:hash": [ { - "@id": "84c0e1ca-a4da-59f3-b60a-096983862089", + "@id": "kb:84c0e1ca-a4da-59f3-b60a-096983862089", "@type": "uco-types:Hash", "uco-types:hashMethod": { "@type": "uco-vocabulary:HashNameVocab", @@ -85,7 +86,7 @@ ] }, { - "@id": "f3ce4eee-0a5d-54a7-9cc7-5ac043234d77", + "@id": "kb:f3ce4eee-0a5d-54a7-9cc7-5ac043234d77", "@type": "uco-observable:RasterPictureFacet", "uco-observable:pictureType": "jpg", "uco-observable:pictureHeight": { @@ -102,20 +103,20 @@ } }, { - "@id": "d6585cd5-ad4b-54c3-a649-d45d12d1605d", + "@id": "kb:d6585cd5-ad4b-54c3-a649-d45d12d1605d", "@type": "uco-observable:EXIFFacet", "uco-observable:exifData": { - "@id": "ab4cd39a-dea8-558b-a49e-4aedd9aff7f1", + "@id": "kb:ab4cd39a-dea8-558b-a49e-4aedd9aff7f1", "@type": "uco-types:ControlledDictionary", "uco-types:entry": [ { - "@id": "7721bd93-fff7-5e1d-a14e-2d627c399ebe", + "@id": "kb:7721bd93-fff7-5e1d-a14e-2d627c399ebe", "@type": "uco-types:ControlledDictionaryEntry", "uco-types:key": "Make", "uco-types:value": "Canon" }, { - "@id": "9ed3e5de-cde8-5cec-a71b-774e485da67d", + "@id": "kb:9ed3e5de-cde8-5cec-a71b-774e485da67d", "@type": "uco-types:ControlledDictionaryEntry", "uco-types:key": "Model", "uco-types:value": "Powershot" @@ -126,12 +127,12 @@ ] }, { - "@id": "2ed228fb-6c23-567a-8128-c891ccdb0dc6", + "@id": "kb:2ed228fb-6c23-567a-8128-c891ccdb0dc6", "@type": "uco-identity:Organization", "uco-core:name": "Apple" }, { - "@id": "268ab394-417e-579a-871b-84947adc9926", + "@id": "kb:268ab394-417e-579a-871b-84947adc9926", "@type": "case-investigation:InvestigativeAction", "uco-core:name": "annotated", "uco-action:startTime": { @@ -144,10 +145,10 @@ }, "uco-core:hasFacet": [ { - "@id": "102c218a-bc39-52e6-8228-abbc200378cf", + "@id": "kb:102c218a-bc39-52e6-8228-abbc200378cf", "@type": "uco-observable:DeviceFacet", "uco-observable:manufacturer": { - "@id": "2ed228fb-6c23-567a-8128-c891ccdb0dc6" + "@id": "kb:2ed228fb-6c23-567a-8128-c891ccdb0dc6" }, "uco-observable:deviceType": "iPhone", "uco-observable:model": "6XS", @@ -156,12 +157,12 @@ ] }, { - "@id": "f3f8c0fb-6a78-5547-aa4f-7c995d9a8732", + "@id": "kb:f3f8c0fb-6a78-5547-aa4f-7c995d9a8732", "@type": "uco-identity:Organization", "uco-core:name": "oneplus" }, { - "@id": "19ff5a9d-1d15-5a6f-858d-28528d5f90d9", + "@id": "kb:19ff5a9d-1d15-5a6f-858d-28528d5f90d9", "@type": "case-investigation:InvestigativeAction", "uco-core:name": "annotated", "uco-action:startTime": { @@ -174,10 +175,10 @@ }, "uco-core:hasFacet": [ { - "@id": "713d0464-a90c-52f3-88f4-1f0a4a9de091", + "@id": "kb:713d0464-a90c-52f3-88f4-1f0a4a9de091", "@type": "uco-observable:DeviceFacet", "uco-observable:manufacturer": { - "@id": "f3f8c0fb-6a78-5547-aa4f-7c995d9a8732" + "@id": "kb:f3f8c0fb-6a78-5547-aa4f-7c995d9a8732" }, "uco-observable:deviceType": "Android", "uco-observable:model": "8", @@ -186,7 +187,7 @@ ] }, { - "@id": "56004659-8649-5ef2-b2e9-e1dae56877f0", + "@id": "kb:56004659-8649-5ef2-b2e9-e1dae56877f0", "@type": "uco-observable:ObservableRelationship", "uco-core:isDirectional": { "@type": "xsd:boolean", @@ -194,38 +195,38 @@ }, "uco-core:kindOfRelationship": "Contained_Within", "uco-core:source": { - "@id": "1ccd06e1-1a39-53c2-8e70-86ad7c48ec5c" + "@id": "kb:1ccd06e1-1a39-53c2-8e70-86ad7c48ec5c" }, "uco-core:target": { - "@id": "fa07818e-5832-5d5f-81b4-f7e143e98252" + "@id": "kb:fa07818e-5832-5d5f-81b4-f7e143e98252" }, "uco-core:hasFacet": [ { - "@id": "862e79c2-ecab-5798-8c43-09ac916ab0d4", + "@id": "kb:862e79c2-ecab-5798-8c43-09ac916ab0d4", "@type": "uco-observable:PathRelationFacet", "uco-observable:path": "/sdcard/IMG_0123.jpg" } ] }, { - "@id": "72930cf3-7693-5c80-ae79-ca82151b5d30", + "@id": "kb:72930cf3-7693-5c80-ae79-ca82151b5d30", "@type": "uco-observable:ObservableObject", "uco-core:hasFacet": [ { - "@id": "5a33cc98-bf34-5011-82ee-1e664da00d29", + "@id": "kb:5a33cc98-bf34-5011-82ee-1e664da00d29", "@type": "uco-observable:EmailAccountFacet", "uco-observable:emailAddress": { - "@id": "94adcf50-cad5-5a2d-9be3-e1e42d698028" + "@id": "kb:94adcf50-cad5-5a2d-9be3-e1e42d698028" } } ] }, { - "@id": "94adcf50-cad5-5a2d-9be3-e1e42d698028", + "@id": "kb:94adcf50-cad5-5a2d-9be3-e1e42d698028", "@type": "uco-observable:ObservableObject", "uco-core:hasFacet": [ { - "@id": "069043f2-89ee-532e-892b-d90a55ed987c", + "@id": "kb:069043f2-89ee-532e-892b-d90a55ed987c", "@type": "uco-observable:EmailAddressFacet", "uco-observable:addressValue": "info@example.com", "uco-observable:displayName": "Example User" @@ -233,24 +234,24 @@ ] }, { - "@id": "742fedd8-ec56-5efd-bbae-eac6de464215", + "@id": "kb:742fedd8-ec56-5efd-bbae-eac6de464215", "@type": "uco-observable:ObservableObject", "uco-core:hasFacet": [ { - "@id": "1e2a360e-9b34-5fa9-978d-e28c455e59d0", + "@id": "kb:1e2a360e-9b34-5fa9-978d-e28c455e59d0", "@type": "uco-observable:EmailAccountFacet", "uco-observable:emailAddress": { - "@id": "a3f00ca2-db54-51a9-a281-1125bbd37783" + "@id": "kb:a3f00ca2-db54-51a9-a281-1125bbd37783" } } ] }, { - "@id": "a3f00ca2-db54-51a9-a281-1125bbd37783", + "@id": "kb:a3f00ca2-db54-51a9-a281-1125bbd37783", "@type": "uco-observable:ObservableObject", "uco-core:hasFacet": [ { - "@id": "f72553c7-7fa7-5354-aa68-7837e9e7b8c4", + "@id": "kb:f72553c7-7fa7-5354-aa68-7837e9e7b8c4", "@type": "uco-observable:EmailAddressFacet", "uco-observable:addressValue": "admin@example.com", "uco-observable:displayName": "Example Admin" @@ -258,11 +259,11 @@ ] }, { - "@id": "70e47458-fd7d-594d-816e-272d5bb1e440", + "@id": "kb:70e47458-fd7d-594d-816e-272d5bb1e440", "@type": "uco-observable:ObservableObject", "uco-core:hasFacet": [ { - "@id": "60d29bf6-1cb0-5974-866a-2f1d60ee4a51", + "@id": "kb:60d29bf6-1cb0-5974-866a-2f1d60ee4a51", "@type": "uco-observable:EmailMessageFacet", "uco-observable:subject": "Thoughts on Our Next Book Club Pick?", "uco-observable:body": "Hello fellow bookworms! It's that time again.", @@ -276,54 +277,54 @@ "@value": "2023-01-01T01:06:06.000006+00:00" }, "uco-observable:from": { - "@id": "94adcf50-cad5-5a2d-9be3-e1e42d698028" + "@id": "kb:94adcf50-cad5-5a2d-9be3-e1e42d698028" }, "uco-observable:to": [ { - "@id": "94adcf50-cad5-5a2d-9be3-e1e42d698028" + "@id": "kb:94adcf50-cad5-5a2d-9be3-e1e42d698028" }, { - "@id": "a3f00ca2-db54-51a9-a281-1125bbd37783" + "@id": "kb:a3f00ca2-db54-51a9-a281-1125bbd37783" } ] } ] }, { - "@id": "41bc2540-fdd8-5753-864c-00a5de7d0d2e", + "@id": "kb:41bc2540-fdd8-5753-864c-00a5de7d0d2e", "@type": "uco-observable:ObservableObject", "uco-core:hasFacet": [ { - "@id": "0f0b71e7-39a8-5249-83a5-b52888d5c8b7", + "@id": "kb:0f0b71e7-39a8-5249-83a5-b52888d5c8b7", "@type": "uco-observable:URLFacet", "uco-observable:fullValue": "www.docker.com/howto" } ] }, { - "@id": "9af4324d-cb7b-54d7-aba4-95714396435e", + "@id": "kb:9af4324d-cb7b-54d7-aba4-95714396435e", "@type": "uco-observable:ObservableObject", "uco-core:hasFacet": [ { - "@id": "d5797860-8d73-5a53-a6fc-660a4e8c64e2", + "@id": "kb:d5797860-8d73-5a53-a6fc-660a4e8c64e2", "@type": "uco-observable:ApplicationFacet", "uco-core:name": "Safari" } ] }, { - "@id": "997f05df-f309-588d-829f-c20e3cbadb57", + "@id": "kb:997f05df-f309-588d-829f-c20e3cbadb57", "@type": "uco-observable:ObservableObject", "uco-core:hasFacet": [ { - "@id": "697d25c6-00bd-571e-aebd-5a96e34ea4b5", + "@id": "kb:697d25c6-00bd-571e-aebd-5a96e34ea4b5", "@type": "uco-observable:URLHistoryFacet", "uco-observable:browserInformation": { - "@id": "9af4324d-cb7b-54d7-aba4-95714396435e" + "@id": "kb:9af4324d-cb7b-54d7-aba4-95714396435e" }, "uco-observable:urlHistoryEntry": [ { - "@id": "641fc5c4-49a3-573e-bdb2-d6d8dc000fee", + "@id": "kb:641fc5c4-49a3-573e-bdb2-d6d8dc000fee", "@type": "uco-observable:URLHistoryEntry", "uco-observable:browserUserProfile": "Jill", "uco-observable:expirationTime": { @@ -346,7 +347,7 @@ }, "uco-observable:pageTitle": "Docker tutorial", "uco-observable:url": { - "@id": "41bc2540-fdd8-5753-864c-00a5de7d0d2e" + "@id": "kb:41bc2540-fdd8-5753-864c-00a5de7d0d2e" }, "uco-observable:visitCount": { "@type": "xsd:integer", @@ -354,7 +355,7 @@ } }, { - "@id": "5860f49a-8471-5984-9610-402672d63f56", + "@id": "kb:5860f49a-8471-5984-9610-402672d63f56", "@type": "uco-observable:URLHistoryEntry", "uco-observable:browserUserProfile": "Tamasin", "uco-observable:expirationTime": { @@ -377,7 +378,7 @@ }, "uco-observable:pageTitle": "GitHub actions tutorial", "uco-observable:url": { - "@id": "41bc2540-fdd8-5753-864c-00a5de7d0d2e" + "@id": "kb:41bc2540-fdd8-5753-864c-00a5de7d0d2e" }, "uco-observable:visitCount": { "@type": "xsd:integer", @@ -389,33 +390,33 @@ ] }, { - "@id": "6e0ac6ce-6afc-58c6-b4b6-501fa5de2699", + "@id": "kb:6e0ac6ce-6afc-58c6-b4b6-501fa5de2699", "@type": "uco-observable:ObservableObject", "uco-core:hasFacet": [ { - "@id": "00f08d34-2abd-53e3-b758-cd5ba00300c9", + "@id": "kb:00f08d34-2abd-53e3-b758-cd5ba00300c9", "@type": "uco-observable:PhoneAccountFacet", "uco-observable:phoneNumber": "123456" } ] }, { - "@id": "3d6f634e-7c5d-5ff8-b996-8d738bb2793a", + "@id": "kb:3d6f634e-7c5d-5ff8-b996-8d738bb2793a", "@type": "uco-observable:ObservableObject", "uco-core:hasFacet": [ { - "@id": "17525359-a042-5503-ad5f-f8f9bcd53472", + "@id": "kb:17525359-a042-5503-ad5f-f8f9bcd53472", "@type": "uco-observable:PhoneAccountFacet", "uco-observable:phoneNumber": "987654" } ] }, { - "@id": "1c09087a-0577-5025-a23b-c3e0155a5bf7", + "@id": "kb:1c09087a-0577-5025-a23b-c3e0155a5bf7", "@type": "uco-observable:ObservableObject", "uco-core:hasFacet": [ { - "@id": "0336f3a3-ff74-5e34-97bb-14534316f393", + "@id": "kb:0336f3a3-ff74-5e34-97bb-14534316f393", "@type": "uco-observable:MessageFacet", "uco-observable:messageText": "Are you free this weekend?", "uco-observable:sentTime": { @@ -423,39 +424,39 @@ "@value": "2023-01-01T01:08:08.000008+00:00" }, "uco-observable:from": { - "@id": "6e0ac6ce-6afc-58c6-b4b6-501fa5de2699" + "@id": "kb:6e0ac6ce-6afc-58c6-b4b6-501fa5de2699" }, "uco-observable:to": [ { - "@id": "6e0ac6ce-6afc-58c6-b4b6-501fa5de2699" + "@id": "kb:6e0ac6ce-6afc-58c6-b4b6-501fa5de2699" }, { - "@id": "3d6f634e-7c5d-5ff8-b996-8d738bb2793a" + "@id": "kb:3d6f634e-7c5d-5ff8-b996-8d738bb2793a" } ], "uco-observable:application": { - "@id": "80c8f41b-e720-51db-b650-1df11b5f2acb" + "@id": "kb:80c8f41b-e720-51db-b650-1df11b5f2acb" } } ] }, { - "@id": "80c8f41b-e720-51db-b650-1df11b5f2acb", + "@id": "kb:80c8f41b-e720-51db-b650-1df11b5f2acb", "@type": "uco-observable:ObservableObject", "uco-core:hasFacet": [ { - "@id": "35fb4ae9-6e55-59b7-a797-6aff1494a314", + "@id": "kb:35fb4ae9-6e55-59b7-a797-6aff1494a314", "@type": "uco-observable:ApplicationFacet", "uco-core:name": "WhatsApp" } ] }, { - "@id": "6d5906a1-df3f-5aa3-8c0d-c76c570d8b96", + "@id": "kb:6d5906a1-df3f-5aa3-8c0d-c76c570d8b96", "@type": "uco-identity:Identity", "uco-core:hasFacet": [ { - "@id": "742d8932-3fe2-5c0f-afc4-9dd2e20533e3", + "@id": "kb:742d8932-3fe2-5c0f-afc4-9dd2e20533e3", "@type": "uco-identity:BirthInformationFacet", "uco-identity:birthdate": { "@type": "xsd:dateTime", @@ -463,7 +464,7 @@ } }, { - "@id": "24cd8876-1c97-5fce-9976-8733f6e901f6", + "@id": "kb:24cd8876-1c97-5fce-9976-8733f6e901f6", "@type": "uco-identity:SimpleNameFacet", "uco-identity:givenName": "Davey", "uco-identity:familyName": "Jones" @@ -471,11 +472,11 @@ ] }, { - "@id": "32599b39-84d2-5471-9452-c494171897fd", + "@id": "kb:32599b39-84d2-5471-9452-c494171897fd", "@type": "uco-location:Location", "uco-core:hasFacet": [ { - "@id": "6f716a17-3a29-513a-9e21-8bf6112c1d50", + "@id": "kb:6f716a17-3a29-513a-9e21-8bf6112c1d50", "@type": "uco-location:LatLongCoordinatesFacet", "uco-location:latitude": { "@type": "xsd:decimal", @@ -489,18 +490,18 @@ ] }, { - "@id": "3344007e-c9c4-5437-9766-4001fc9f3af5", + "@id": "kb:3344007e-c9c4-5437-9766-4001fc9f3af5", "@type": "case-investigation:Investigation", "uco-core:name": "Crime A", "case-investigation:focus": "Transfer of Illicit Materials", "uco-core:description": "Inquiry into the transfer of illicit materials and the devices used to do so", "uco-core:object": [ { - "@id": "fa07818e-5832-5d5f-81b4-f7e143e98252", + "@id": "kb:fa07818e-5832-5d5f-81b4-f7e143e98252", "@type": "uco-observable:ObservableObject", "uco-core:hasFacet": [ { - "@id": "9ab260ac-cdf5-5524-9047-3ea85ebfb6e2", + "@id": "kb:9ab260ac-cdf5-5524-9047-3ea85ebfb6e2", "@type": "uco-observable:FileFacet", "uco-observable:fileSystemType": "EXT4", "uco-observable:fileName": "IMG_0123.jpg", @@ -512,7 +513,7 @@ } }, { - "@id": "09cab366-d82b-57f8-a94c-9814bf7ef63d", + "@id": "kb:09cab366-d82b-57f8-a94c-9814bf7ef63d", "@type": "uco-observable:ContentDataFacet", "uco-observable:magicNumber": "/9j/ww==", "uco-observable:mimeType": "image/jpg", @@ -527,7 +528,7 @@ }, "uco-observable:hash": [ { - "@id": "84c0e1ca-a4da-59f3-b60a-096983862089", + "@id": "kb:84c0e1ca-a4da-59f3-b60a-096983862089", "@type": "uco-types:Hash", "uco-types:hashMethod": { "@type": "uco-vocabulary:HashNameVocab", @@ -541,7 +542,7 @@ ] }, { - "@id": "f3ce4eee-0a5d-54a7-9cc7-5ac043234d77", + "@id": "kb:f3ce4eee-0a5d-54a7-9cc7-5ac043234d77", "@type": "uco-observable:RasterPictureFacet", "uco-observable:pictureType": "jpg", "uco-observable:pictureHeight": { @@ -558,20 +559,20 @@ } }, { - "@id": "d6585cd5-ad4b-54c3-a649-d45d12d1605d", + "@id": "kb:d6585cd5-ad4b-54c3-a649-d45d12d1605d", "@type": "uco-observable:EXIFFacet", "uco-observable:exifData": { - "@id": "ab4cd39a-dea8-558b-a49e-4aedd9aff7f1", + "@id": "kb:ab4cd39a-dea8-558b-a49e-4aedd9aff7f1", "@type": "uco-types:ControlledDictionary", "uco-types:entry": [ { - "@id": "7721bd93-fff7-5e1d-a14e-2d627c399ebe", + "@id": "kb:7721bd93-fff7-5e1d-a14e-2d627c399ebe", "@type": "uco-types:ControlledDictionaryEntry", "uco-types:key": "Make", "uco-types:value": "Canon" }, { - "@id": "9ed3e5de-cde8-5cec-a71b-774e485da67d", + "@id": "kb:9ed3e5de-cde8-5cec-a71b-774e485da67d", "@type": "uco-types:ControlledDictionaryEntry", "uco-types:key": "Model", "uco-types:value": "Powershot" @@ -582,7 +583,7 @@ ] }, { - "@id": "268ab394-417e-579a-871b-84947adc9926", + "@id": "kb:268ab394-417e-579a-871b-84947adc9926", "@type": "case-investigation:InvestigativeAction", "uco-core:name": "annotated", "uco-action:startTime": { @@ -595,10 +596,10 @@ }, "uco-core:hasFacet": [ { - "@id": "102c218a-bc39-52e6-8228-abbc200378cf", + "@id": "kb:102c218a-bc39-52e6-8228-abbc200378cf", "@type": "uco-observable:DeviceFacet", "uco-observable:manufacturer": { - "@id": "2ed228fb-6c23-567a-8128-c891ccdb0dc6" + "@id": "kb:2ed228fb-6c23-567a-8128-c891ccdb0dc6" }, "uco-observable:deviceType": "iPhone", "uco-observable:model": "6XS", @@ -609,7 +610,7 @@ ] }, { - "@id": "bb9cd337-eb51-50dd-9cee-00f9e9acbf94", + "@id": "kb:bb9cd337-eb51-50dd-9cee-00f9e9acbf94", "@type": "uco-observable:Message", "uco-observable:state": "some state", "uco-observable:hasChanged": { @@ -620,45 +621,45 @@ "olo:slot": null, "uco-core:hasFacet": [ { - "@id": "73af707b-f00e-5327-8fd4-83467b4441c4", + "@id": "kb:73af707b-f00e-5327-8fd4-83467b4441c4", "@type": "uco-observable:MessageFacet" } ] }, { - "@id": "7c4d5cff-deb0-5031-b881-c572d6ef2fd7", + "@id": "kb:7c4d5cff-deb0-5031-b881-c572d6ef2fd7", "@type": "uco-observable:Message", "olo:length": null, "olo:slot": null, "uco-core:hasFacet": [ { - "@id": "551338f3-0bb6-5325-a63a-f164f8750a17", + "@id": "kb:551338f3-0bb6-5325-a63a-f164f8750a17", "@type": "uco-observable:MessageFacet" } ] }, { - "@id": "09b10c04-d04b-5808-a1b6-0392dd3a00e8", + "@id": "kb:09b10c04-d04b-5808-a1b6-0392dd3a00e8", "@type": "uco-observable:Message", "olo:length": null, "olo:slot": null, "uco-core:hasFacet": [ { - "@id": "a19e1e1f-3953-5fb9-92b6-2b46f85752b2", + "@id": "kb:a19e1e1f-3953-5fb9-92b6-2b46f85752b2", "@type": "uco-observable:MessageFacet" } ] }, { - "@id": "562c20c5-bef7-5919-a969-6c820a80e0d3", + "@id": "kb:562c20c5-bef7-5919-a969-6c820a80e0d3", "@type": "uco-observable:MessageThread", "uco-core:hasFacet": [ { - "@id": "6f79d4ae-d92c-5cad-bbe5-a0afde6f475a", + "@id": "kb:6f79d4ae-d92c-5cad-bbe5-a0afde6f475a", "@type": "uco-observable:MessageThreadFacet", "uco-observable:displayName": "some name", "uco-observable:messageThread": { - "@id": "56f74818-1d3d-51f9-8cb1-d6bdc8ecee60", + "@id": "kb:56f74818-1d3d-51f9-8cb1-d6bdc8ecee60", "@type": "uco-types:Thread", "co:size": { "@type": "xsd:nonNegativeInteger", @@ -666,13 +667,13 @@ }, "co:element": [ { - "@id": "09b10c04-d04b-5808-a1b6-0392dd3a00e8" + "@id": "kb:09b10c04-d04b-5808-a1b6-0392dd3a00e8" }, { - "@id": "7c4d5cff-deb0-5031-b881-c572d6ef2fd7" + "@id": "kb:7c4d5cff-deb0-5031-b881-c572d6ef2fd7" }, { - "@id": "bb9cd337-eb51-50dd-9cee-00f9e9acbf94" + "@id": "kb:bb9cd337-eb51-50dd-9cee-00f9e9acbf94" } ] } From 777a504959c75f6198adf8f15d7ef28507d780d2 Mon Sep 17 00:00:00 2001 From: Alex Nelson Date: Tue, 12 Mar 2024 16:58:03 -0400 Subject: [PATCH 3/5] Align test Signed-off-by: Alex Nelson --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a2b4da1..47ce9a6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: run: pre-commit run --all-files - name: Unit Tests - run: poetry run pytest + run: poetry run pytest --doctest-modules - name: Run Example run: poetry run python example.py > case.jsonld From c6d4f8b5b4a771820e52af1035f6dd2f6f7490eb Mon Sep 17 00:00:00 2001 From: Alex Nelson Date: Tue, 12 Mar 2024 17:06:52 -0400 Subject: [PATCH 4/5] Adjust generated error message Signed-off-by: Alex Nelson --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1c1326b..5b2e0b2 100644 --- a/Makefile +++ b/Makefile @@ -96,7 +96,7 @@ case.ttl: \ 0 \ -eq \ $$(grep 'file:' _$@ | wc -l) \ - || ( echo "ERROR:Some graph IRIs do not supply a resolving prefix. Look for the string 'file:///' in the file _$@ to see these instances." ; exit 1) + || ( echo "ERROR:Makefile:Some graph IRIs do not supply a resolving prefix. Look for the string 'file:///' in the file _$@ to see these instances." >&2 ; exit 1) mv _$@ $@ check: \ From d578183003dc67ef6ed304ddd21fe4fae35d5db1 Mon Sep 17 00:00:00 2001 From: Alex Nelson Date: Tue, 12 Mar 2024 17:07:38 -0400 Subject: [PATCH 5/5] Adapt prefix test for CI process Signed-off-by: Alex Nelson --- .github/workflows/ci.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 47ce9a6..730b081 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: - name: Install Dependencies run: | - pip -q install poetry pre-commit + pip -q install poetry pre-commit rdflib poetry install - name: Pre-commit Checks @@ -44,6 +44,11 @@ jobs: case-version: "case-1.3.0" extension-filter: "jsonld" + - name: Convert example + run: | + rdfpipe --output-format turtle case.jsonld > case.ttl + test 0 -eq $(grep 'file:' case.ttl | wc -l) || (echo "ERROR:ci.yml:Some graph IRIs do not supply a resolving prefix. Look for the string 'file:///' in the file case.ttl (created by running 'make check') to see these instances." >&2 ; exit 1) + # Always build the package as a sanity check to ensure no issues with the build system # exist as part of the CI process - name: Build Package