Skip to content

descriptors

BytesDescriptor

Bytes descriptor converts strings to bytes on write and converts bytes to str if represent_as_base64_str flag is set, so the value can be dumped to json

Source code in ormar\models\descriptors\descriptors.py
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
class BytesDescriptor:
    """
    Bytes descriptor converts strings to bytes on write and converts bytes to str
    if represent_as_base64_str flag is set, so the value can be dumped to json
    """

    def __init__(self, name: str) -> None:
        self.name = name

    def __get__(self, instance: "Model", owner: Type["Model"]) -> Any:
        value = instance.__dict__.get(self.name, None)
        field = instance.Meta.model_fields[self.name]
        if (
            value is not None
            and field.represent_as_base64_str
            and not isinstance(value, str)
        ):
            value = base64.b64encode(value).decode()
        return value

    def __set__(self, instance: "Model", value: Any) -> None:
        field = instance.Meta.model_fields[self.name]
        if isinstance(value, str):
            if field.represent_as_base64_str:
                value = base64.b64decode(value)
            else:
                value = value.encode("utf-8")
        instance._internal_set(self.name, value)
        instance.set_save_status(False)

JsonDescriptor

Json descriptor dumps/loads strings to actual data on write/read

Source code in ormar\models\descriptors\descriptors.py
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class JsonDescriptor:
    """
    Json descriptor dumps/loads strings to actual data on write/read
    """

    def __init__(self, name: str) -> None:
        self.name = name

    def __get__(self, instance: "Model", owner: Type["Model"]) -> Any:
        value = instance.__dict__.get(self.name, None)
        return value

    def __set__(self, instance: "Model", value: Any) -> None:
        value = encode_json(value)
        instance._internal_set(self.name, value)
        instance.set_save_status(False)

PkDescriptor

As of now it's basically a copy of PydanticDescriptor but that will change in the future with multi column primary keys

Source code in ormar\models\descriptors\descriptors.py
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
class PkDescriptor:
    """
    As of now it's basically a copy of PydanticDescriptor but that will
    change in the future with multi column primary keys
    """

    def __init__(self, name: str) -> None:
        self.name = name

    def __get__(self, instance: "Model", owner: Type["Model"]) -> Any:
        value = instance.__dict__.get(self.name, None)
        return value

    def __set__(self, instance: "Model", value: Any) -> None:
        instance._internal_set(self.name, value)
        instance.set_save_status(False)

PropertyDescriptor

Property descriptor handles methods decorated with @property_field decorator. They are read only.

Source code in ormar\models\descriptors\descriptors.py
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
class PropertyDescriptor:
    """
    Property descriptor handles methods decorated with @property_field decorator.
    They are read only.
    """

    def __init__(self, name: str, function: Any) -> None:
        self.name = name
        self.function = function

    def __get__(self, instance: "Model", owner: Type["Model"]) -> Any:
        if instance is None:
            return self
        if instance is not None and self.function is not None:
            bound = self.function.__get__(instance, instance.__class__)
            return bound() if callable(bound) else bound

    def __set__(self, instance: "Model", value: Any) -> None:  # pragma: no cover
        # kept here so it's a data-descriptor and precedes __dict__ lookup
        pass

PydanticDescriptor

Pydantic descriptor simply delegates everything to pydantic model

Source code in ormar\models\descriptors\descriptors.py
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class PydanticDescriptor:
    """
    Pydantic descriptor simply delegates everything to pydantic model
    """

    def __init__(self, name: str) -> None:
        self.name = name

    def __get__(self, instance: "Model", owner: Type["Model"]) -> Any:
        value = instance.__dict__.get(self.name, None)
        return value

    def __set__(self, instance: "Model", value: Any) -> None:
        instance._internal_set(self.name, value)
        instance.set_save_status(False)

RelationDescriptor

Relation descriptor expands the relation to initialize the related model before setting it to dict. Note that expanding also registers the related model in RelationManager.

Source code in ormar\models\descriptors\descriptors.py
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
class RelationDescriptor:
    """
    Relation descriptor expands the relation to initialize the related model
    before setting it to __dict__. Note that expanding also registers the
    related model in RelationManager.
    """

    def __init__(self, name: str) -> None:
        self.name = name

    def __get__(self, instance: "Model", owner: Type["Model"]) -> Any:
        if self.name in instance._orm:
            return instance._orm.get(self.name)  # type: ignore
        return None  # pragma no cover

    def __set__(self, instance: "Model", value: Any) -> None:
        model = instance.Meta.model_fields[self.name].expand_relationship(
            value=value, child=instance
        )
        if isinstance(instance.__dict__.get(self.name), list):
            # virtual foreign key or many to many
            # TODO: Fix double items in dict, no effect on real action just ugly repr
            instance.__dict__[self.name].append(model)
        else:
            # foreign key relation
            instance.__dict__[self.name] = model
            instance.set_save_status(False)