Skip to main content

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. If None, 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() + [...].