interfaces
CanDictSerialize
from cai_causal_graph.interfaces import CanDictSerialize
class CanDictSerialize(abc.ABC)
An interface for an object that can be represented as a dictionary.
Methods
to_dict
@abc.abstractmethod
def to_dict() -> dict
Return a dictionary representation of the object.
CanDictDeserialize
from cai_causal_graph.interfaces import CanDictDeserialize
class CanDictDeserialize(abc.ABC)
An interface for an object that can be instantiated from a dictionary.
Methods
from_dict
@classmethod
@abc.abstractmethod
def from_dict(cls, d: dict) -> CanDictDeserialize
Return an instance of itself, constructed from the provided dictionary.
HasIdentifier
from cai_causal_graph.interfaces import HasIdentifier
class HasIdentifier(abc.ABC)
An interface for an object that has an identifier.
Methods
identifier
@property
@abc.abstractmethod
def identifier() -> str
A unique identifier property.
get_identifier
def get_identifier() -> str
Return the identifier.
HasMetadata
from cai_causal_graph.interfaces import HasMetadata
class HasMetadata()
An interface for an object that has metadata.
Metadata is stored in a dictionary which can be passed at construction. A common design pattern is then for a class to have multiple properties which provide user-friendly access to specific metadata fields. These fields can be commonly set at the construction of an object.
Moreover, the original class may be extended by adding more properties. This interface has been designed to facilitate this by ensuring that extending these classes is simple and consistent.
This class has two main functionalities. Firstly, it defines an interface for saving and accessing metadata, which is a simple dictionary with all string keys.
Secondly, it defines a metadata schema, which can be used to easily combine metadata with parameters passed
explicitly. This in particular, accommodates the following usecase. Consider a class ClsWithMeta
which
extends HasMetadata
. While ClsWithMeta
provides a way to store arbitrary metadata, it also provides
a simple way to store and access 'foo'
property, which is stored in the metadata.
from typing import List, Optional
from cai_causal_graph.interfaces import HasMetadata
from cai_causal_graph.metadata_handler import MetaField
class ClsWithMeta(HasMetadata):
def __init__(self, foo: Optional[int] = None, meta: Optional[dict] = None):
meta = self._process_meta(meta=meta, kwargs_dict=dict(foo=foo))
super().__init__(meta=meta)
@property
def foo(self) -> Optional[int]:
return self.meta.get('foo', None)
@foo.setter
def foo(self, foo: Optional[int]):
self.meta['foo'] = foo
@classmethod
def get_metadata_schema(cls) -> List[MetaField]:
return super().get_metadata_schema() + [MetaField(metatag='foo', property_name='foo')]
Notice, that ClsWithMeta
defines a metadata schema using the get_metadata_schema
method, where it adds the
'foo'
metadata to the schema of its parent class. This in turn, enables easily extending the class and supports
multiple inheritence, where the inheritence tree can get complex.
The metadata schema can then be used to process metadata and combine it with explicit parameters. This is
implemented by the cai_causal_graph.interfaces.HasMetadata._process_meta
method, and works by checking the
metadata schema and adding the matching parameters to the metadata. If a value is already set in the metadata, but
is also defined in the parameter, the parameter takes precendence, meaning the value in the metadata is overwritten.
While in the example above, the metadata schema is simple, it is also possible to define fields with tags not matching the property name, as well as not matching the provided parameter name. Moreover, it is possible to define tags with default values.
Methods
__init__
def __init__(meta: Optional[dict] = None)
Construct a HasMetadata
instance with the provided meta.
Arguments:
meta
: Optional metadata dictionary. If provided, the dictionary is shallow-copied. IfNone
, then an empty dictionary is created.
metadata
@property
def metadata() -> Optional[dict]
A metadata property.
get_metadata
def get_metadata() -> Optional[dict]
Return metadata that is a dictionary.
get_metadata_schema
@classmethod
def get_metadata_schema(cls) -> List[MetaField]
Get the schema for metadata of this class.
To support complex class inheritance structures, it is recommended to return a sum of metadata of a parent
class and this class, i.e. return super().get_metadata_schema() + [...]
.