2

I'm using pydantic with fastapi. And, I make Model like this.

# model.py
from multiprocessing import RLock
from pydantic import BaseModel
class ModelA(BaseModel):
 file_1: str = 'test'
 def __init__(self, **data: Any):
 super().__init__(**data)
 self._lock = RLock()
 self._instance_variable: int = 1
 @property
 def lock(self):
 return self._lock
 @property
 def instance_variable(self) -> int:
 with self.lock:
 return self._instance_variable
 @instance_variable.setter
 def instance_variable(self, v: int) -> int:
 assert isinstance(v, int)
 with self.lock:
 self._instance_variable = v

And I make test like this

# test_model_a.py
def test_model_a():
 instance = ModelA()
 assert instance.json() == '{"field_1": "test"}'

After, I run the test, but the instance can't create with this error.

E ValueError: "ModelA" object has no field "_lock"

So, How can I pass this test...? Please... help me...

asked Feb 25, 2021 at 4:28
2
  • You should not do your assertion with a string comparison; indeed the indent of JSON may vary (for instance the spaces). I would recommend to use BaseModel.dict() instead and compare 2 objects. Commented Feb 25, 2021 at 8:18
  • your answer is not point, for my question. my question is 'propery.setter' dose not work Commented Feb 25, 2021 at 10:01

1 Answer 1

1

You need to use PrivateAttr field. And instead of a setter, use a workaround with __setattr__

from multiprocessing import RLock, synchronize
from typing import Any
from pydantic import BaseModel, PrivateAttr
class ModelA(BaseModel):
 file_1: str = 'test'
 _lock: synchronize.RLock = PrivateAttr()
 _instance_variable: int = PrivateAttr()
 def __init__(self, **data: Any):
 super().__init__(**data)
 self._lock = RLock()
 self._instance_variable: int = 1
 @property
 def lock(self):
 return self._lock
 @property
 def instance_variable(self) -> int:
 with self.lock:
 return self._instance_variable
 def __setattr__(self, key, val):
 if key == "instance_variable":
 assert isinstance(val, int)
 with self.lock:
 self._instance_variable = val
 return
 super().__setattr__(key, val)

You can also avoid using a custom __init__


class ModelA(BaseModel):
 file_1: str = 'test'
 _lock: synchronize.RLock = PrivateAttr(default_factory=RLock)
 _instance_variable: int = PrivateAttr(1)
# ...
answered Feb 25, 2021 at 10:01
Sign up to request clarification or add additional context in comments.

2 Comments

umm... that's so good idea. but i want property.setter... isn't it possible...?

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.