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)