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...

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)
# ...
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

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.