Skip to content

Commit

Permalink
Merge pull request #83 from casework/support_strict_review_on_example_py
Browse files Browse the repository at this point in the history
Add type signatures in support of strict type-review on example.py
  • Loading branch information
kchason authored Dec 2, 2024
2 parents 1331422 + 9734853 commit 89649a3
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 86 deletions.
44 changes: 22 additions & 22 deletions case.jsonld
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,6 @@
"uco-core:createdBy": {
"@id": "kb:aef8e4c4-db83-59fd-8f71-b65cd7676c0a"
},
"@context": {
"@vocab": "http://caseontology.org/core#",
"case-investigation": "https://ontology.caseontology.org/case/investigation/",
"drafting": "http://example.org/ontology/drafting/",
"co": "http://purl.org/co/",
"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"rdfs": "http://www.w3.org/2000/01/rdf-schema#",
"uco-action": "https://ontology.unifiedcyberontology.org/uco/action/",
"uco-core": "https://ontology.unifiedcyberontology.org/uco/core/",
"uco-identity": "https://ontology.unifiedcyberontology.org/uco/identity/",
"uco-location": "https://ontology.unifiedcyberontology.org/uco/location/",
"uco-role": "https://ontology.unifiedcyberontology.org/uco/role/",
"uco-observable": "https://ontology.unifiedcyberontology.org/uco/observable/",
"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#",
"kb": "http://example.org/kb/"
},
"uco-core:object": [
{
"@id": "kb:aef8e4c4-db83-59fd-8f71-b65cd7676c0a",
Expand Down Expand Up @@ -579,7 +560,6 @@
"@id": "kb:a19e1e1f-3953-5fb9-92b6-2b46f85752b2",
"@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": [
{
Expand Down Expand Up @@ -710,7 +690,8 @@
}
]
}
]
],
"case-investigation:focus": "Transfer of Illicit Materials"
},
{
"@id": "kb:6f79d4ae-d92c-5cad-bbe5-a0afde6f475a",
Expand Down Expand Up @@ -1853,5 +1834,24 @@
}
]
}
]
],
"@context": {
"@vocab": "http://caseontology.org/core#",
"case-investigation": "https://ontology.caseontology.org/case/investigation/",
"drafting": "http://example.org/ontology/drafting/",
"co": "http://purl.org/co/",
"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"rdfs": "http://www.w3.org/2000/01/rdf-schema#",
"uco-action": "https://ontology.unifiedcyberontology.org/uco/action/",
"uco-core": "https://ontology.unifiedcyberontology.org/uco/core/",
"uco-identity": "https://ontology.unifiedcyberontology.org/uco/identity/",
"uco-location": "https://ontology.unifiedcyberontology.org/uco/location/",
"uco-role": "https://ontology.unifiedcyberontology.org/uco/role/",
"uco-observable": "https://ontology.unifiedcyberontology.org/uco/observable/",
"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#",
"kb": "http://example.org/kb/"
}
}
10 changes: 4 additions & 6 deletions case_mapping/case/investigation.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from ..base import Facet, UcoObject
from ..uco.action import Action
from ..uco.core import ContextualCompilation
from ..uco.location import Location


Expand Down Expand Up @@ -46,8 +47,8 @@ def __init__(
self["@type"] = "case-investigation:InvestigativeAction"


class CaseInvestigation(UcoObject):
def __init__(self, name=None, focus=None, description=None, core_objects=None):
class CaseInvestigation(ContextualCompilation):
def __init__(self, *args: Any, focus=None, **kwargs: Any) -> None:
"""
An investigative action is a CASE object that represents the who, where, when of investigation
:param name: The name of an investigation (e.g., Murder of Suspect B,.)
Expand All @@ -57,16 +58,13 @@ def __init__(self, name=None, focus=None, description=None, core_objects=None):
object e.g., Persons involved in investigation, Investigation into a Murder, object refrences a
case-object for a phone investigative action
"""
super().__init__()
super().__init__(*args, **kwargs)
self["@type"] = "case-investigation:Investigation"
self._str_vars(
**{
"uco-core:name": name,
"case-investigation:focus": focus,
"uco-core:description": description,
}
)
self.append_core_objects(core_objects)


class ProvenanceRecord(UcoObject):
Expand Down
8 changes: 6 additions & 2 deletions case_mapping/drafting/entities.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Any

from ..base import Facet, UcoObject, unpack_args_array


Expand Down Expand Up @@ -175,6 +177,7 @@ def __init__(
class SocialMediaActivityFacet(Facet):
def __init__(
self,
*args: Any,
body=None,
page_title=None,
author_identifier=None,
Expand All @@ -187,7 +190,8 @@ def __init__(
created_time=None,
application=None,
url=None,
):
**kwargs: Any,
) -> None:
"""
Used to represent activity on social platfomrs
:param body: The text of the post/message
Expand All @@ -203,7 +207,7 @@ def __init__(
:param application: the application used for creating the post
:param application: the URL of the post
"""
super().__init__()
super().__init__(*args, **kwargs)

self["@type"] = ["drafting:SocialMediaActivityFacet", "uco-core:Facet"]

Expand Down
85 changes: 74 additions & 11 deletions case_mapping/uco/core.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,85 @@
from datetime import datetime
from typing import Any, List, Optional, Union
from typing import Any, Optional, Sequence, Union

from pytz import timezone

from ..base import UcoObject, unpack_args_array


class Bundle(UcoObject):
class Compilation(UcoObject):
def __init__(
self,
*args: Any,
core_objects: Optional[Sequence[UcoObject]] = None,
**kwargs: Any,
) -> None:
"""
A compilation is a grouping of things.
"""
super().__init__(*args, **kwargs)
self["@type"] = "uco-core:Compilation"
if core_objects is not None and len(core_objects) > 0:
self.append_core_objects(core_objects)

@unpack_args_array
def append_to_uco_object(self, *args) -> None:
"""
Add a single/tuple of result(s) to the list of outputs from an action
:param args: A CASE object, or objects, often an observable. (e.g., one of many devices from a search operation)
"""
self._append_observable_objects("uco-core:object", *args)


class ContextualCompilation(Compilation):
def __init__(
self,
*args: Any,
core_objects: Sequence[UcoObject],
**kwargs: Any,
) -> None:
"""
A contextual compilation is a grouping of things sharing some context (e.g., a set of network connections observed on a given day, all accounts associated with a given person).
Future implementation note: At and before CASE 1.3.0, at least one core:object must be supplied at instantiation time of a contextual compilation. At and after CASE 1.4.0, these objects will be optional.
"""
if len(core_objects) == 0:
raise ValueError(
"A ContextualCompilation is required to have at least one UcoObject to link at initiation time. This will become optional in CASE 1.4.0."
)
super().__init__(*args, **kwargs)
self["@type"] = "uco-core:ContextualCompilation"
self.append_core_objects(core_objects)


class EnclosingCompilation(Compilation):
def __init__(
self,
*args: Any,
core_objects: Sequence[UcoObject],
**kwargs: Any,
) -> None:
"""
An enclosing compilation is a container for a grouping of things.
"""
if len(core_objects) == 0:
raise ValueError(
"An EnclosingCompilation is required to have at least one UcoObject to link at initiation time."
)
super().__init__(*args, **kwargs)
self["@type"] = "uco-core:EnclosingCompilation"
self.append_core_objects(core_objects)


class Bundle(EnclosingCompilation):
def __init__(
self,
*args: Any,
**kwargs: Any,
) -> None:
"""
The main CASE Object for representing a case and its activities and objects.
Instantiating this class requires a starter sequence (set, list, or tuple) to be passed using the core_objects parameter. (See EnclosingCompilation.) To confirm conformant CASE will be generated, at least one UcoObject must be passed in this list. However, this does not initially need to be the complete sequence of objects that will be in this Bundle. Other UcoObjects can be added after initialization with bundle.append_to_uco_object.
"""
super().__init__(*args, **kwargs)
self.build = [] # type: ignore
Expand All @@ -39,6 +105,7 @@ def __init__(
# Assign caller-selectible prefix label and IRI, after checking
# for conflicts with hard-coded prefixes.
# https://www.w3.org/TR/turtle/#prefixed-name
assert isinstance(self["@context"], dict)
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."
Expand All @@ -51,14 +118,6 @@ def __init__(
def append_to_case_graph(self, *args):
self._append_observable_objects("@graph", *args)

@unpack_args_array
def append_to_uco_object(self, *args):
"""
Add a single/tuple of result(s) to the list of outputs from an action
:param args: A CASE object, or objects, often an observable. (e.g., one of many devices from a search operation)
"""
self._append_observable_objects("uco-core:object", *args)

@unpack_args_array
def append_to_rdfs_comments(self, *args):
self._append_strings("rdfs:comment", *args)
Expand Down Expand Up @@ -119,4 +178,8 @@ def _addtime(self, _type: str) -> None:
}


directory = {"uco-core:Bundle": Bundle}
directory = {
"uco-core:Bundle": Bundle,
"uco-core:Compilation": Compilation,
"uco-core:ContextualCompilation": ContextualCompilation,
}
12 changes: 7 additions & 5 deletions case_mapping/uco/identity.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
from typing import Dict, Optional
from typing import Any, Dict, Optional

from ..base import Facet, IdentityAbstraction, UcoObject


class BirthInformationFacet(Facet):
def __init__(self, birthdate=None):
def __init__(self, *args: Any, birthdate=None, **kwargs: Any) -> None:
"""
:param birthdate: the date of birth of an identity
"""
super().__init__()
super().__init__(*args, **kwargs)
self["@type"] = "uco-identity:BirthInformationFacet"
self._datetime_vars(**{"uco-identity:birthdate": birthdate})

Expand All @@ -31,12 +31,14 @@ def __init__(self, name: Optional[str] = None, facets=None):


class SimpleNameFacet(Facet):
def __init__(self, given_name=None, family_name=None):
def __init__(
self, *args: Any, given_name=None, family_name=None, **kwargs: Any
) -> None:
"""
:param given_name: Full name of the identity of person
:param family_name: Family name of identity of person
"""
super().__init__()
super().__init__(*args, **kwargs)
self["@type"] = "uco-identity:SimpleNameFacet"
self._str_vars(
**{
Expand Down
7 changes: 3 additions & 4 deletions case_mapping/uco/location.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
from typing import Optional
from typing import Any, Optional

from ..base import Facet, UcoObject


class Location(UcoObject):
def __init__(self, facets=None):
super().__init__()
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self["@type"] = "uco-location:Location"
self.append_facets(facets)


class LatLongCoordinatesFacet(Facet):
Expand Down
Loading

0 comments on commit 89649a3

Please sign in to comment.