fix private attributes initialization

This commit is contained in:
collerek
2021-04-12 10:40:29 +02:00
parent b3b1c156b5
commit 6780c9de8a
4 changed files with 56 additions and 15 deletions

View File

@ -18,6 +18,7 @@
* Fix weakref `ReferenceError` error [#118](https://github.com/collerek/ormar/issues/118)
* Fix error raised by Through fields when pydantic `Config.extra="forbid"` is set
* Fix bug with `pydantic.PrivateAttr` not being initialized at `__init__` [#149](https://github.com/collerek/ormar/issues/149)
## 💬 Other
* Introduce link to `sqlalchemy-to-ormar` auto-translator for models

View File

@ -189,6 +189,10 @@ class NewBaseModel(pydantic.BaseModel, ModelTableProxy, metaclass=ModelMetaclass
new_kwargs.get(related), self, to_register=True,
)
if hasattr(self, "_init_private_attributes"):
# introduced in pydantic 1.7
self._init_private_attributes()
def __setattr__(self, name: str, value: Any) -> None: # noqa CCR001
"""
Overwrites setattr in object to allow for special behaviour of certain params.
@ -292,6 +296,7 @@ class NewBaseModel(pydantic.BaseModel, ModelTableProxy, metaclass=ModelMetaclass
value = object.__getattribute__(self, "__dict__").get(item, None)
value = object.__getattribute__(self, "_convert_json")(item, value, "loads")
return value
return object.__getattribute__(self, item) # pragma: no cover
def _verify_model_can_be_initialized(self) -> None:
@ -590,18 +595,19 @@ class NewBaseModel(pydantic.BaseModel, ModelTableProxy, metaclass=ModelMetaclass
for field in fields:
if not relation_map or field not in relation_map:
continue
nested_model = getattr(self, field)
if isinstance(nested_model, MutableSequence):
dict_instance[field] = self._extract_nested_models_from_list(
relation_map=self._skip_ellipsis( # type: ignore
relation_map, field, default_return=dict()
),
models=nested_model,
include=self._skip_ellipsis(include, field),
exclude=self._skip_ellipsis(exclude, field),
)
elif nested_model is not None:
try:
try:
nested_model = getattr(self, field)
if isinstance(nested_model, MutableSequence):
dict_instance[field] = self._extract_nested_models_from_list(
relation_map=self._skip_ellipsis( # type: ignore
relation_map, field, default_return=dict()
),
models=nested_model,
include=self._skip_ellipsis(include, field),
exclude=self._skip_ellipsis(exclude, field),
)
elif nested_model is not None:
dict_instance[field] = nested_model.dict(
relation_map=self._skip_ellipsis(
relation_map, field, default_return=dict()
@ -609,9 +615,9 @@ class NewBaseModel(pydantic.BaseModel, ModelTableProxy, metaclass=ModelMetaclass
include=self._skip_ellipsis(include, field),
exclude=self._skip_ellipsis(exclude, field),
)
except ReferenceError:
else:
dict_instance[field] = None
else:
except ReferenceError:
dict_instance[field] = None
return dict_instance

View File

@ -22,7 +22,7 @@ if TYPE_CHECKING: # pragma no cover
from ormar.relations import Relation
from ormar.models import Model, T
from ormar.queryset import QuerySet
from ormar import RelationType, ForeignKeyField
from ormar import RelationType
else:
T = TypeVar("T", bound="Model")

View File

@ -0,0 +1,34 @@
from typing import List
import databases
import sqlalchemy
from pydantic import PrivateAttr
import ormar
from tests.settings import DATABASE_URL
database = databases.Database(DATABASE_URL, force_rollback=True)
metadata = sqlalchemy.MetaData()
class BaseMeta(ormar.ModelMeta):
metadata = metadata
database = database
class Subscription(ormar.Model):
class Meta(BaseMeta):
tablename = "subscriptions"
id: int = ormar.Integer(primary_key=True)
stripe_subscription_id: str = ormar.String(nullable=False, max_length=256)
_add_payments: List[str] = PrivateAttr(default_factory=list)
def add_payment(self, payment: str):
self._add_payments.append(payment)
def test_private_attribute():
sub = Subscription(stripe_subscription_id="2312312sad231")
sub.add_payment("test")