Skip to content

Module omnipy.modules.tables.models

Overview

View Source
from omnipy.data.model import Model

from omnipy.modules.json.models import JsonDictM, JsonListM

class TableOfStrings(Model[list[dict[str, str]]]):

    ...

class JsonTableOfStrings(JsonListM[JsonDictM[str]]):

    ...

class TableOfStringsAndLists(Model[list[dict[str, str | list[str]]]]):

    ...

Classes

JsonTableOfStrings

class JsonTableOfStrings(
    value: Union[Any, pydantic.fields.UndefinedType] = PydanticUndefined,
    *,
    __root__: Union[Any, pydantic.fields.UndefinedType] = PydanticUndefined,
    **data: Any
)

A data model containing a value parsed according to the model.

If no value is provided, the value is set to the default value of the data model, found by calling the model class without parameters, e.g. int().

Model is a generic class that cannot be instantiated directly. Instead, a Model class needs to be specialized with a data type before Model objects can be instantiated. A data model functions as a data parser and guarantees that the parsed data follows the specified model.

Example data model specialized as a class alias::

MyNumberList = Model[list[int]]

... alternatively as a Model subclass::

class MyNumberList(Model[list[int]]):
    pass

Once instantiated, a Model object functions as a parser, e.g.::

my_number_list = MyNumberList([2,3,4])

my_number_list.contents = ['3', 4, True]
assert my_number_list.contents == [3,4,1]

While the following should raise a ValidationError::

my_number_list.contents = ['abc', 'def']

The Model class is a wrapper class around the powerful GenericModel class from pydantic.

See also docs of the Dataset class for more usage examples.

View Source
class JsonTableOfStrings(JsonListM[JsonDictM[str]]):

    ...

Class variables

Config

Static methods

to_json_schema
def to_json_schema(
    pretty=False
) -> str

Parameters:

Name Type Description Default
pretty

Returns:

Type Description
str
View Source
    @classmethod

    def to_json_schema(cls, pretty=False) -> str:

        schema = cls.schema()

        if pretty:

            return cls._pretty_print_json(schema)

        else:

            return json.dumps(schema)
validate
def validate(
    value: Any
) -> Model

Hack to allow overwriting of iter method without compromising pydantic validation. Part

of the pydantic API and not the Omnipy API.

Parameters:

Name Type Description Default
value Any

Returns:

Type Description
Model
View Source
    @classmethod

    def validate(cls: Type['Model'], value: Any) -> 'Model':

        """

        Hack to allow overwriting of __iter__ method without compromising pydantic validation. Part

        of the pydantic API and not the Omnipy API.

        """

        if isinstance(value, Model):

            with AttribHolder(value, '__iter__', GenericModel.__iter__, on_class=True):

                return super().validate(value)

        else:

            return super().validate(value)

Instance variables

contents

Methods

delitem
def __delitem__(
    self,
    *args: object,
    **kwargs: object
) -> object

Parameters:

Name Type Description Default
args object
kwargs object

Returns:

Type Description
object
View Source
        def _method(cls_or_self, /, *args, **keywords):

            keywords = {**self.keywords, **keywords}

            return self.func(cls_or_self, *self.args, *args, **keywords)
eq
def __eq__(
    self,
    other: object
) -> bool

Return self==value.

Parameters:

Name Type Description Default
other object

Returns:

Type Description
bool
View Source
    def __eq__(self, other: object) -> bool:

        return isinstance(other, Model) \

            and self.__class__ == other.__class__ \

            and self.contents == other.contents \

            and self.to_data() == other.to_data()  # last is probably unnecessary, but just in case
getattr
def __getattr__(
    self,
    attr: str
) -> Any

Parameters:

Name Type Description Default
attr str

Returns:

Type Description
Any
View Source
    def __getattr__(self, attr: str) -> Any:

        ret = self._getattr_from_contents(attr)

        if callable(ret):

            ret = add_callback_after_call(ret, self.validate_contents)

        return ret
iter
def __iter__(
    self,
    *args: object,
    **kwargs: object
) -> object

Parameters:

Name Type Description Default
args object
kwargs object

Returns:

Type Description
object
View Source
        def _method(cls_or_self, /, *args, **keywords):

            keywords = {**self.keywords, **keywords}

            return self.func(cls_or_self, *self.args, *args, **keywords)
setattr
def __setattr__(
    self,
    attr: str,
    value: Any
) -> None

Implement setattr(self, name, value).

Parameters:

Name Type Description Default
attr str
value Any

Returns:

Type Description
NoneType
View Source
    def __setattr__(self, attr: str, value: Any) -> None:

        if attr in self.__dict__ and attr not in [ROOT_KEY]:

            super().__setattr__(attr, value)

        else:

            if attr in ['contents']:

                contents_prop = getattr(self.__class__, attr)

                contents_prop.__set__(self, value)

            else:

                raise RuntimeError('Model does not allow setting of extra attributes')
setitem
def __setitem__(
    self,
    *args: object,
    **kwargs: object
) -> object

Parameters:

Name Type Description Default
args object
kwargs object

Returns:

Type Description
object
View Source
        def _method(cls_or_self, /, *args, **keywords):

            keywords = {**self.keywords, **keywords}

            return self.func(cls_or_self, *self.args, *args, **keywords)
from_data
def from_data(
    self,
    value: Any
) -> None

Parameters:

Name Type Description Default
value Any

Returns:

Type Description
NoneType
View Source
    def from_data(self, value: Any) -> None:

        self.contents = value
from_json
def from_json(
    self,
    json_contents: str
) -> None

Parameters:

Name Type Description Default
json_contents str

Returns:

Type Description
NoneType
View Source
    def from_json(self, json_contents: str) -> None:

        new_model = self.parse_raw(json_contents, proto=pydantic_protocol.json)

        self._set_contents_without_validation(new_model)
inner_type
def inner_type(
    self,
    with_args: bool = False
) -> type | None

Parameters:

Name Type Description Default
with_args bool

Returns:

Type Description
type None
View Source
    def inner_type(self, with_args: bool = False) -> type | None:

        return self.__class__._get_root_type(outer=False, with_args=with_args)
is_nested_type
def is_nested_type(
    self
) -> bool

Returns:

Type Description
bool
View Source
    def is_nested_type(self) -> bool:

        return not self.inner_type(with_args=True) == self.outer_type(with_args=True)
outer_type
def outer_type(
    self,
    with_args: bool = False
) -> type | None

Parameters:

Name Type Description Default
with_args bool

Returns:

Type Description
type None
View Source
    def outer_type(self, with_args: bool = False) -> type | None:

        return self.__class__._get_root_type(outer=True, with_args=with_args)
to_data
def to_data(
    self
) -> Any

Returns:

Type Description
Any
View Source
    def to_data(self) -> Any:

        return self.dict()[ROOT_KEY]
to_json
def to_json(
    self,
    pretty=False
) -> str

Parameters:

Name Type Description Default
pretty

Returns:

Type Description
str
View Source
    def to_json(self, pretty=False) -> str:

        json_content = self.json()

        if pretty:

            return self._pretty_print_json(json.loads(json_content))

        else:

            return json_content
validate_contents
def validate_contents(
    self
)
View Source
    def validate_contents(self):

        self.contents = self.contents

TableOfStrings

class TableOfStrings(
    value: Union[Any, pydantic.fields.UndefinedType] = PydanticUndefined,
    *,
    __root__: Union[Any, pydantic.fields.UndefinedType] = PydanticUndefined,
    **data: Any
)

A data model containing a value parsed according to the model.

If no value is provided, the value is set to the default value of the data model, found by calling the model class without parameters, e.g. int().

Model is a generic class that cannot be instantiated directly. Instead, a Model class needs to be specialized with a data type before Model objects can be instantiated. A data model functions as a data parser and guarantees that the parsed data follows the specified model.

Example data model specialized as a class alias::

MyNumberList = Model[list[int]]

... alternatively as a Model subclass::

class MyNumberList(Model[list[int]]):
    pass

Once instantiated, a Model object functions as a parser, e.g.::

my_number_list = MyNumberList([2,3,4])

my_number_list.contents = ['3', 4, True]
assert my_number_list.contents == [3,4,1]

While the following should raise a ValidationError::

my_number_list.contents = ['abc', 'def']

The Model class is a wrapper class around the powerful GenericModel class from pydantic.

See also docs of the Dataset class for more usage examples.

View Source
class TableOfStrings(Model[list[dict[str, str]]]):

    ...

Class variables

Config

Static methods

to_json_schema
def to_json_schema(
    pretty=False
) -> str

Parameters:

Name Type Description Default
pretty

Returns:

Type Description
str
View Source
    @classmethod

    def to_json_schema(cls, pretty=False) -> str:

        schema = cls.schema()

        if pretty:

            return cls._pretty_print_json(schema)

        else:

            return json.dumps(schema)
validate
def validate(
    value: Any
) -> Model

Hack to allow overwriting of iter method without compromising pydantic validation. Part

of the pydantic API and not the Omnipy API.

Parameters:

Name Type Description Default
value Any

Returns:

Type Description
Model
View Source
    @classmethod

    def validate(cls: Type['Model'], value: Any) -> 'Model':

        """

        Hack to allow overwriting of __iter__ method without compromising pydantic validation. Part

        of the pydantic API and not the Omnipy API.

        """

        if isinstance(value, Model):

            with AttribHolder(value, '__iter__', GenericModel.__iter__, on_class=True):

                return super().validate(value)

        else:

            return super().validate(value)

Instance variables

contents

Methods

delitem
def __delitem__(
    self,
    *args: object,
    **kwargs: object
) -> object

Parameters:

Name Type Description Default
args object
kwargs object

Returns:

Type Description
object
View Source
        def _method(cls_or_self, /, *args, **keywords):

            keywords = {**self.keywords, **keywords}

            return self.func(cls_or_self, *self.args, *args, **keywords)
eq
def __eq__(
    self,
    other: object
) -> bool

Return self==value.

Parameters:

Name Type Description Default
other object

Returns:

Type Description
bool
View Source
    def __eq__(self, other: object) -> bool:

        return isinstance(other, Model) \

            and self.__class__ == other.__class__ \

            and self.contents == other.contents \

            and self.to_data() == other.to_data()  # last is probably unnecessary, but just in case
getattr
def __getattr__(
    self,
    attr: str
) -> Any

Parameters:

Name Type Description Default
attr str

Returns:

Type Description
Any
View Source
    def __getattr__(self, attr: str) -> Any:

        ret = self._getattr_from_contents(attr)

        if callable(ret):

            ret = add_callback_after_call(ret, self.validate_contents)

        return ret
iter
def __iter__(
    self,
    *args: object,
    **kwargs: object
) -> object

Parameters:

Name Type Description Default
args object
kwargs object

Returns:

Type Description
object
View Source
        def _method(cls_or_self, /, *args, **keywords):

            keywords = {**self.keywords, **keywords}

            return self.func(cls_or_self, *self.args, *args, **keywords)
setattr
def __setattr__(
    self,
    attr: str,
    value: Any
) -> None

Implement setattr(self, name, value).

Parameters:

Name Type Description Default
attr str
value Any

Returns:

Type Description
NoneType
View Source
    def __setattr__(self, attr: str, value: Any) -> None:

        if attr in self.__dict__ and attr not in [ROOT_KEY]:

            super().__setattr__(attr, value)

        else:

            if attr in ['contents']:

                contents_prop = getattr(self.__class__, attr)

                contents_prop.__set__(self, value)

            else:

                raise RuntimeError('Model does not allow setting of extra attributes')
setitem
def __setitem__(
    self,
    *args: object,
    **kwargs: object
) -> object

Parameters:

Name Type Description Default
args object
kwargs object

Returns:

Type Description
object
View Source
        def _method(cls_or_self, /, *args, **keywords):

            keywords = {**self.keywords, **keywords}

            return self.func(cls_or_self, *self.args, *args, **keywords)
from_data
def from_data(
    self,
    value: Any
) -> None

Parameters:

Name Type Description Default
value Any

Returns:

Type Description
NoneType
View Source
    def from_data(self, value: Any) -> None:

        self.contents = value
from_json
def from_json(
    self,
    json_contents: str
) -> None

Parameters:

Name Type Description Default
json_contents str

Returns:

Type Description
NoneType
View Source
    def from_json(self, json_contents: str) -> None:

        new_model = self.parse_raw(json_contents, proto=pydantic_protocol.json)

        self._set_contents_without_validation(new_model)
inner_type
def inner_type(
    self,
    with_args: bool = False
) -> type | None

Parameters:

Name Type Description Default
with_args bool

Returns:

Type Description
type None
View Source
    def inner_type(self, with_args: bool = False) -> type | None:

        return self.__class__._get_root_type(outer=False, with_args=with_args)
is_nested_type
def is_nested_type(
    self
) -> bool

Returns:

Type Description
bool
View Source
    def is_nested_type(self) -> bool:

        return not self.inner_type(with_args=True) == self.outer_type(with_args=True)
outer_type
def outer_type(
    self,
    with_args: bool = False
) -> type | None

Parameters:

Name Type Description Default
with_args bool

Returns:

Type Description
type None
View Source
    def outer_type(self, with_args: bool = False) -> type | None:

        return self.__class__._get_root_type(outer=True, with_args=with_args)
to_data
def to_data(
    self
) -> Any

Returns:

Type Description
Any
View Source
    def to_data(self) -> Any:

        return self.dict()[ROOT_KEY]
to_json
def to_json(
    self,
    pretty=False
) -> str

Parameters:

Name Type Description Default
pretty

Returns:

Type Description
str
View Source
    def to_json(self, pretty=False) -> str:

        json_content = self.json()

        if pretty:

            return self._pretty_print_json(json.loads(json_content))

        else:

            return json_content
validate_contents
def validate_contents(
    self
)
View Source
    def validate_contents(self):

        self.contents = self.contents

TableOfStringsAndLists

class TableOfStringsAndLists(
    value: Union[Any, pydantic.fields.UndefinedType] = PydanticUndefined,
    *,
    __root__: Union[Any, pydantic.fields.UndefinedType] = PydanticUndefined,
    **data: Any
)

A data model containing a value parsed according to the model.

If no value is provided, the value is set to the default value of the data model, found by calling the model class without parameters, e.g. int().

Model is a generic class that cannot be instantiated directly. Instead, a Model class needs to be specialized with a data type before Model objects can be instantiated. A data model functions as a data parser and guarantees that the parsed data follows the specified model.

Example data model specialized as a class alias::

MyNumberList = Model[list[int]]

... alternatively as a Model subclass::

class MyNumberList(Model[list[int]]):
    pass

Once instantiated, a Model object functions as a parser, e.g.::

my_number_list = MyNumberList([2,3,4])

my_number_list.contents = ['3', 4, True]
assert my_number_list.contents == [3,4,1]

While the following should raise a ValidationError::

my_number_list.contents = ['abc', 'def']

The Model class is a wrapper class around the powerful GenericModel class from pydantic.

See also docs of the Dataset class for more usage examples.

View Source
class TableOfStringsAndLists(Model[list[dict[str, str | list[str]]]]):

    ...

Class variables

Config

Static methods

to_json_schema
def to_json_schema(
    pretty=False
) -> str

Parameters:

Name Type Description Default
pretty

Returns:

Type Description
str
View Source
    @classmethod

    def to_json_schema(cls, pretty=False) -> str:

        schema = cls.schema()

        if pretty:

            return cls._pretty_print_json(schema)

        else:

            return json.dumps(schema)
validate
def validate(
    value: Any
) -> Model

Hack to allow overwriting of iter method without compromising pydantic validation. Part

of the pydantic API and not the Omnipy API.

Parameters:

Name Type Description Default
value Any

Returns:

Type Description
Model
View Source
    @classmethod

    def validate(cls: Type['Model'], value: Any) -> 'Model':

        """

        Hack to allow overwriting of __iter__ method without compromising pydantic validation. Part

        of the pydantic API and not the Omnipy API.

        """

        if isinstance(value, Model):

            with AttribHolder(value, '__iter__', GenericModel.__iter__, on_class=True):

                return super().validate(value)

        else:

            return super().validate(value)

Instance variables

contents

Methods

delitem
def __delitem__(
    self,
    *args: object,
    **kwargs: object
) -> object

Parameters:

Name Type Description Default
args object
kwargs object

Returns:

Type Description
object
View Source
        def _method(cls_or_self, /, *args, **keywords):

            keywords = {**self.keywords, **keywords}

            return self.func(cls_or_self, *self.args, *args, **keywords)
eq
def __eq__(
    self,
    other: object
) -> bool

Return self==value.

Parameters:

Name Type Description Default
other object

Returns:

Type Description
bool
View Source
    def __eq__(self, other: object) -> bool:

        return isinstance(other, Model) \

            and self.__class__ == other.__class__ \

            and self.contents == other.contents \

            and self.to_data() == other.to_data()  # last is probably unnecessary, but just in case
getattr
def __getattr__(
    self,
    attr: str
) -> Any

Parameters:

Name Type Description Default
attr str

Returns:

Type Description
Any
View Source
    def __getattr__(self, attr: str) -> Any:

        ret = self._getattr_from_contents(attr)

        if callable(ret):

            ret = add_callback_after_call(ret, self.validate_contents)

        return ret
iter
def __iter__(
    self,
    *args: object,
    **kwargs: object
) -> object

Parameters:

Name Type Description Default
args object
kwargs object

Returns:

Type Description
object
View Source
        def _method(cls_or_self, /, *args, **keywords):

            keywords = {**self.keywords, **keywords}

            return self.func(cls_or_self, *self.args, *args, **keywords)
setattr
def __setattr__(
    self,
    attr: str,
    value: Any
) -> None

Implement setattr(self, name, value).

Parameters:

Name Type Description Default
attr str
value Any

Returns:

Type Description
NoneType
View Source
    def __setattr__(self, attr: str, value: Any) -> None:

        if attr in self.__dict__ and attr not in [ROOT_KEY]:

            super().__setattr__(attr, value)

        else:

            if attr in ['contents']:

                contents_prop = getattr(self.__class__, attr)

                contents_prop.__set__(self, value)

            else:

                raise RuntimeError('Model does not allow setting of extra attributes')
setitem
def __setitem__(
    self,
    *args: object,
    **kwargs: object
) -> object

Parameters:

Name Type Description Default
args object
kwargs object

Returns:

Type Description
object
View Source
        def _method(cls_or_self, /, *args, **keywords):

            keywords = {**self.keywords, **keywords}

            return self.func(cls_or_self, *self.args, *args, **keywords)
from_data
def from_data(
    self,
    value: Any
) -> None

Parameters:

Name Type Description Default
value Any

Returns:

Type Description
NoneType
View Source
    def from_data(self, value: Any) -> None:

        self.contents = value
from_json
def from_json(
    self,
    json_contents: str
) -> None

Parameters:

Name Type Description Default
json_contents str

Returns:

Type Description
NoneType
View Source
    def from_json(self, json_contents: str) -> None:

        new_model = self.parse_raw(json_contents, proto=pydantic_protocol.json)

        self._set_contents_without_validation(new_model)
inner_type
def inner_type(
    self,
    with_args: bool = False
) -> type | None

Parameters:

Name Type Description Default
with_args bool

Returns:

Type Description
type None
View Source
    def inner_type(self, with_args: bool = False) -> type | None:

        return self.__class__._get_root_type(outer=False, with_args=with_args)
is_nested_type
def is_nested_type(
    self
) -> bool

Returns:

Type Description
bool
View Source
    def is_nested_type(self) -> bool:

        return not self.inner_type(with_args=True) == self.outer_type(with_args=True)
outer_type
def outer_type(
    self,
    with_args: bool = False
) -> type | None

Parameters:

Name Type Description Default
with_args bool

Returns:

Type Description
type None
View Source
    def outer_type(self, with_args: bool = False) -> type | None:

        return self.__class__._get_root_type(outer=True, with_args=with_args)
to_data
def to_data(
    self
) -> Any

Returns:

Type Description
Any
View Source
    def to_data(self) -> Any:

        return self.dict()[ROOT_KEY]
to_json
def to_json(
    self,
    pretty=False
) -> str

Parameters:

Name Type Description Default
pretty

Returns:

Type Description
str
View Source
    def to_json(self, pretty=False) -> str:

        json_content = self.json()

        if pretty:

            return self._pretty_print_json(json.loads(json_content))

        else:

            return json_content
validate_contents
def validate_contents(
    self
)
View Source
    def validate_contents(self):

        self.contents = self.contents