core.orm.mixins.content

Attributes

_T

_MarkupT

IMMUTABLE_TYPES

content_property

data_property

meta_property

dictionary_based_property_factory

Classes

_dict_property_factory

Base class for protocol classes.

ContentMixin

Mixin providing a meta/content JSON pair. Meta is a JSON column loaded

dict_property

Enables access of dictionaries through properties.

dict_markup_property

Enables access of dictionaries through properties.

Functions

is_valid_default(→ bool)

dict_property_factory(→ _dict_property_factory)

Module Contents

class core.orm.mixins.content._dict_property_factory[source]

Bases: Protocol

Base class for protocol classes.

Protocol classes are defined as:

class Proto(Protocol):
    def meth(self) -> int:
        ...

Such classes are primarily used with static type checkers that recognize structural subtyping (static duck-typing).

For example:

class C:
    def meth(self) -> int:
        return 0

def func(x: Proto) -> int:
    return x.meth()

func(C())  # Passes static type check

See PEP 544 for details. Protocol classes decorated with @typing.runtime_checkable act as simple-minded runtime protocols that check only the presence of given attributes, ignoring their type signatures. Protocol classes can be generic, they are defined as:

class GenProto(Protocol[T]):
    def meth(self) -> T:
        ...
__call__(key: str | None = None, default: None = None, value_type: None = None) dict_property[Any | None][source]
__call__(key: str | None, default: _T | Callable[[], _T], value_type: None = None) dict_property[_T]
__call__(key: str | None = None, *, default: _T | Callable[[], _T], value_type: None = None) dict_property[_T]
__call__(key: str | None, default: None, *, value_type: type[_T]) dict_property[_T]
__call__(key: str | None = None, default: None = None, *, value_type: type[_T]) dict_property[_T]
__call__(key: str | None, default: _T | Callable[[], _T], value_type: type[_T]) dict_property[_T]
__call__(key: str | None = None, *, default: _T | Callable[[], _T], value_type: type[_T]) dict_property[_T]
core.orm.mixins.content._T[source]
core.orm.mixins.content._MarkupT[source]
core.orm.mixins.content.IMMUTABLE_TYPES[source]
class core.orm.mixins.content.ContentMixin[source]

Mixin providing a meta/content JSON pair. Meta is a JSON column loaded with each request, content is a JSON column loaded deferred (to be shown only in the detail view).

property meta: Column[dict[str, Any]][source]
property content: Column[dict[str, Any]][source]
core.orm.mixins.content.is_valid_default(default: object | None) bool[source]
class core.orm.mixins.content.dict_property(attribute: str, key: str | None = None, default: None = None, value_type: None = None)[source]
class core.orm.mixins.content.dict_property(attribute: str, key: str | None, default: _T | Callable[[], _T], value_type: None = None)
class core.orm.mixins.content.dict_property(attribute: str, key: str | None = None, *, default: _T | Callable[[], _T], value_type: None = None)
class core.orm.mixins.content.dict_property(attribute: str, key: str | None, default: None, *, value_type: type[_T])
class core.orm.mixins.content.dict_property(attribute: str, key: str | None = None, default: None = None, *, value_type: type[_T])
class core.orm.mixins.content.dict_property(attribute: str, key: str | None, default: _T | Callable[[], _T], value_type: type[_T])
class core.orm.mixins.content.dict_property(attribute: str, key: str | None = None, *, default: _T | Callable[[], _T], value_type: type[_T])

Bases: sqlalchemy.orm.interfaces.InspectionAttrInfo, Generic[_T]

Enables access of dictionaries through properties.

Usage:

class Model(ContentMixin):
    access_times = dict_property('meta')

This creates a property that accesses the meta directory with the key ‘access_times’. The key is implicitly copied from the definition.

Another way of writing this out would be:

class Model(ContentMixin):
    access_times = dict_property('meta', 'access_times')

As is apparent, the ‘access_times’ key is duplicated in this case. Usually you do not need to provide the name. The exception being if you want the property name and the dictionary key to differ:

class Model(ContentMixin):
    access_times = dict_property('meta', 'access')

Here, the key in the dictionary is ‘access’, while the property is ‘access_times’.

Since we often use the same kind of dictionaries we can use the builtin properties that are scoped to a specific dictionary:

class Model(ContentMixin):
    access_times = meta_property()

This is equivalent to the initial example.

We can also create our own scoped properties as follows:

foo_property = dict_property_factory(‘foo’)

class Model:

foo = {}

bar = foo_property()

Here, model.bar would read model.foo[‘bar’].

Dict properties are compatible with typical python properties, so the usual getter/setter/deleter methods are also available:

class Model(ContentMixin):
    content = meta_property()

    @content.setter
    def set_content(self, value):
        self.meta['content'] = value
        self.meta['content_html'] = to_html_ul(value)

    @content.deleter
    def del_content(self):
        del self.meta['content']
        del self.meta['content_html']

This also behaves like a hybrid_property in that you can use these properties inside select and filter statements, if you provider a custom getter you will also need to provide a custom expression, otherwise we will return an expression which retrieves the value from the JSON column:

class Model(ContentMixin):
    names = meta_property(default=list)

session.query(Model).filter(Model.names.contains('foo'))

By default that will mean that the RHS of a comparison will also expect a JSONB object, but if you explicitly pass in a value_type or a default that is not None, then we will try to first convert to that type, so type coercion is a bit more flexible:

class Model(ContentMixin):
    name = meta_property(value_type=str)

session.query(Model.name)
is_attribute = True[source]

True if this object is a Python descriptor.

This can refer to one of many types. Usually a QueryableAttribute which handles attributes events on behalf of a MapperProperty. But can also be an extension type such as AssociationProxy or hybrid_property. The InspectionAttr.extension_type will refer to a constant identifying the specific subtype.

See also

_orm.Mapper.all_orm_descriptors

custom_getter: Callable[[Any], _T] | None[source]
custom_expression: Callable[[type[Any]], ColumnElement[_T]] | None[source]
custom_setter: Callable[[Any, _T], None] | None[source]
custom_deleter: Callable[[Any], None] | None[source]
attribute[source]
key = None[source]
default = None[source]
value_type = None[source]
update_expr = None[source]
__set_name__(owner: type[object], name: str) None[source]

Sets the dictionary key, if none is provided.

property getter: Callable[[Callable[[Any], _T]], Self][source]
property setter: Callable[[Callable[[Any, _T], None]], Self][source]
property deleter: Callable[[Callable[[Any], None]], Self][source]
property expression: Callable[[Callable[[Any], ColumnElement[_T]]], Self][source]
_expr(owner: type[Any]) QueryableAttribute | None[source]
__get__(instance: None, owner: type[object]) QueryableAttribute | None[source]
__get__(instance: object, owner: type[object]) _T
__set__(instance: object, value: _T) None[source]
__delete__(instance: object) None[source]
class core.orm.mixins.content.dict_markup_property(attribute: str, key: str | None = None, default: None = None)[source]
class core.orm.mixins.content.dict_markup_property(attribute: str, key: str | None, default: markupsafe.Markup)
class core.orm.mixins.content.dict_markup_property(attribute: str, key: str | None = None, *, default: markupsafe.Markup)

Bases: dict_property[_MarkupT]

Enables access of dictionaries through properties.

Usage:

class Model(ContentMixin):
    access_times = dict_property('meta')

This creates a property that accesses the meta directory with the key ‘access_times’. The key is implicitly copied from the definition.

Another way of writing this out would be:

class Model(ContentMixin):
    access_times = dict_property('meta', 'access_times')

As is apparent, the ‘access_times’ key is duplicated in this case. Usually you do not need to provide the name. The exception being if you want the property name and the dictionary key to differ:

class Model(ContentMixin):
    access_times = dict_property('meta', 'access')

Here, the key in the dictionary is ‘access’, while the property is ‘access_times’.

Since we often use the same kind of dictionaries we can use the builtin properties that are scoped to a specific dictionary:

class Model(ContentMixin):
    access_times = meta_property()

This is equivalent to the initial example.

We can also create our own scoped properties as follows:

foo_property = dict_property_factory(‘foo’)

class Model:

foo = {}

bar = foo_property()

Here, model.bar would read model.foo[‘bar’].

Dict properties are compatible with typical python properties, so the usual getter/setter/deleter methods are also available:

class Model(ContentMixin):
    content = meta_property()

    @content.setter
    def set_content(self, value):
        self.meta['content'] = value
        self.meta['content_html'] = to_html_ul(value)

    @content.deleter
    def del_content(self):
        del self.meta['content']
        del self.meta['content_html']

This also behaves like a hybrid_property in that you can use these properties inside select and filter statements, if you provider a custom getter you will also need to provide a custom expression, otherwise we will return an expression which retrieves the value from the JSON column:

class Model(ContentMixin):
    names = meta_property(default=list)

session.query(Model).filter(Model.names.contains('foo'))

By default that will mean that the RHS of a comparison will also expect a JSONB object, but if you explicitly pass in a value_type or a default that is not None, then we will try to first convert to that type, so type coercion is a bit more flexible:

class Model(ContentMixin):
    name = meta_property(value_type=str)

session.query(Model.name)
custom_expression[source]
__get__(instance: None, owner: type[object]) QueryableAttribute | None[source]
__get__(instance: object, owner: type[object]) _MarkupT
__set__(instance: object, value: _MarkupT) None[source]
core.orm.mixins.content.dict_property_factory(attribute: str) _dict_property_factory[source]
core.orm.mixins.content.content_property[source]
core.orm.mixins.content.data_property[source]
core.orm.mixins.content.meta_property[source]
core.orm.mixins.content.dictionary_based_property_factory[source]