Refactored instances management

This commit is contained in:
2025-11-23 19:52:03 +01:00
parent 97247f824c
commit b1be747101
24 changed files with 783 additions and 216 deletions

View File

@@ -4,6 +4,7 @@ from dataclasses import dataclass
import pytest
from myfasthtml.core.dbmanager import DbManager, DbObject
from myfasthtml.core.instances import SingleInstance, BaseInstance
@pytest.fixture(scope="session")
@@ -19,9 +20,14 @@ def session():
@pytest.fixture
def db_manager(session):
def parent(session):
return SingleInstance(session=session, _id="test_parent_id")
@pytest.fixture
def db_manager(parent):
shutil.rmtree("TestDb", ignore_errors=True)
db_manager_instance = DbManager(session, root="TestDb", auto_register=False)
db_manager_instance = DbManager(parent, root="TestDb", auto_register=False)
yield db_manager_instance
@@ -32,17 +38,17 @@ def simplify(res: dict) -> dict:
return {k: v for k, v in res.items() if not k.startswith("_")}
def test_i_can_init(session, db_manager):
def test_i_can_init(parent, db_manager):
class DummyObject(DbObject):
def __init__(self, sess: dict):
super().__init__(sess, "DummyObject", db_manager)
def __init__(self, owner: BaseInstance):
super().__init__(owner, "DummyObject", db_manager)
with self.initializing():
self.value: str = "hello"
self.number: int = 42
self.none_value: None = None
dummy = DummyObject(session)
dummy = DummyObject(parent)
props = dummy._get_properties()
@@ -52,17 +58,17 @@ def test_i_can_init(session, db_manager):
assert len(history) == 1
def test_i_can_init_from_dataclass(session, db_manager):
def test_i_can_init_from_dataclass(parent, db_manager):
@dataclass
class DummyObject(DbObject):
def __init__(self, sess: dict):
super().__init__(sess, "DummyObject", db_manager)
def __init__(self, owner: BaseInstance):
super().__init__(owner, "DummyObject", db_manager)
value: str = "hello"
number: int = 42
none_value: None = None
DummyObject(session)
DummyObject(parent)
in_db = db_manager.load("DummyObject")
history = db_manager.db.history(db_manager.get_tenant(), "DummyObject")
@@ -70,10 +76,10 @@ def test_i_can_init_from_dataclass(session, db_manager):
assert len(history) == 1
def test_i_can_init_from_db_with(session, db_manager):
def test_i_can_init_from_db_with(parent, db_manager):
class DummyObject(DbObject):
def __init__(self, sess: dict):
super().__init__(sess, "DummyObject", db_manager)
def __init__(self, owner: BaseInstance):
super().__init__(owner, "DummyObject", db_manager)
with self.initializing():
self.value: str = "hello"
@@ -82,17 +88,17 @@ def test_i_can_init_from_db_with(session, db_manager):
# insert other values in db
db_manager.save("DummyObject", {"value": "other_value", "number": 34})
dummy = DummyObject(session)
dummy = DummyObject(parent)
assert dummy.value == "other_value"
assert dummy.number == 34
def test_i_can_init_from_db_with_dataclass(session, db_manager):
def test_i_can_init_from_db_with_dataclass(parent, db_manager):
@dataclass
class DummyObject(DbObject):
def __init__(self, sess: dict):
super().__init__(sess, "DummyObject", db_manager)
def __init__(self, owner: BaseInstance):
super().__init__(owner, "DummyObject", db_manager)
value: str = "hello"
number: int = 42
@@ -100,16 +106,16 @@ def test_i_can_init_from_db_with_dataclass(session, db_manager):
# insert other values in db
db_manager.save("DummyObject", {"value": "other_value", "number": 34})
dummy = DummyObject(session)
dummy = DummyObject(parent)
assert dummy.value == "other_value"
assert dummy.number == 34
def test_i_do_not_save_when_prefixed_by_underscore_or_ns(session, db_manager):
def test_i_do_not_save_when_prefixed_by_underscore_or_ns(parent, db_manager):
class DummyObject(DbObject):
def __init__(self, sess: dict):
super().__init__(sess, "DummyObject", db_manager)
def __init__(self, owner: BaseInstance):
super().__init__(owner, "DummyObject", db_manager)
with self.initializing():
self.to_save: str = "value"
@@ -120,7 +126,7 @@ def test_i_do_not_save_when_prefixed_by_underscore_or_ns(session, db_manager):
_not_to_save: str = "value"
ns_not_to_save: str = "value"
dummy = DummyObject(session)
dummy = DummyObject(parent)
dummy.to_save = "other_value"
dummy.ns_not_to_save = "other_value"
dummy._not_to_save = "other_value"
@@ -131,17 +137,17 @@ def test_i_do_not_save_when_prefixed_by_underscore_or_ns(session, db_manager):
assert "ns_not_to_save" not in in_db
def test_i_do_not_save_when_prefixed_by_underscore_or_ns_with_dataclass(session, db_manager):
def test_i_do_not_save_when_prefixed_by_underscore_or_ns_with_dataclass(parent, db_manager):
@dataclass
class DummyObject(DbObject):
def __init__(self, sess: dict):
super().__init__(sess, "DummyObject", db_manager)
def __init__(self, owner: BaseInstance):
super().__init__(owner, "DummyObject", db_manager)
to_save: str = "value"
_not_to_save: str = "value"
ns_not_to_save: str = "value"
dummy = DummyObject(session)
dummy = DummyObject(parent)
dummy.to_save = "other_value"
dummy.ns_not_to_save = "other_value"
dummy._not_to_save = "other_value"
@@ -152,31 +158,31 @@ def test_i_do_not_save_when_prefixed_by_underscore_or_ns_with_dataclass(session,
assert "ns_not_to_save" not in in_db
def test_db_is_updated_when_attribute_is_modified(session, db_manager):
def test_db_is_updated_when_attribute_is_modified(parent, db_manager):
@dataclass
class DummyObject(DbObject):
def __init__(self, sess: dict):
super().__init__(sess, "DummyObject", db_manager)
def __init__(self, owner: BaseInstance):
super().__init__(owner, "DummyObject", db_manager)
value: str = "hello"
number: int = 42
dummy = DummyObject(session)
dummy = DummyObject(parent)
dummy.value = "other_value"
assert simplify(db_manager.load("DummyObject")) == {"value": "other_value", "number": 42}
def test_i_do_not_save_in_db_when_value_is_the_same(session, db_manager):
def test_i_do_not_save_in_db_when_value_is_the_same(parent, db_manager):
@dataclass
class DummyObject(DbObject):
def __init__(self, sess: dict):
super().__init__(sess, "DummyObject", db_manager)
def __init__(self, owner: BaseInstance):
super().__init__(owner, "DummyObject", db_manager)
value: str = "hello"
number: int = 42
dummy = DummyObject(session)
dummy = DummyObject(parent)
dummy.value = "other_value"
in_db_1 = db_manager.load("DummyObject")
@@ -186,16 +192,16 @@ def test_i_do_not_save_in_db_when_value_is_the_same(session, db_manager):
assert in_db_1["__parent__"] == in_db_2["__parent__"]
def test_i_can_update(session, db_manager):
def test_i_can_update(parent, db_manager):
@dataclass
class DummyObject(DbObject):
def __init__(self, sess: dict):
super().__init__(sess, "DummyObject", db_manager)
def __init__(self, owner: BaseInstance):
super().__init__(owner, "DummyObject", db_manager)
value: str = "hello"
number: int = 42
dummy = DummyObject(session)
dummy = DummyObject(parent)
clone = dummy.copy()
clone.number = 34
@@ -207,54 +213,52 @@ def test_i_can_update(session, db_manager):
assert simplify(db_manager.load("DummyObject")) == {"value": "other_value", "number": 34}
def test_forbidden_attributes_are_not_the_copy(session, db_manager):
def test_forbidden_attributes_are_not_the_copy(parent, db_manager):
class DummyObject(DbObject):
def __init__(self, sess: dict):
super().__init__(sess, "DummyObject", db_manager)
def __init__(self, owner: BaseInstance):
super().__init__(owner, "DummyObject", db_manager)
with self.initializing():
self.value: str = "hello"
self.number: int = 42
self.none_value: None = None
dummy = DummyObject(session)
dummy = DummyObject(parent)
clone = dummy.copy()
for k in DbObject._forbidden_attrs:
assert not hasattr(clone, k), f"Clone should not have forbidden attribute '{k}'"
def test_forbidden_attributes_are_not_the_copy_for_dataclass(session, db_manager):
def test_forbidden_attributes_are_not_the_copy_for_dataclass(parent, db_manager):
@dataclass
class DummyObject(DbObject):
def __init__(self, sess: dict):
super().__init__(sess, "DummyObject", db_manager)
def __init__(self, owner: BaseInstance):
super().__init__(owner, "DummyObject", db_manager)
value: str = "hello"
number: int = 42
none_value: None = None
dummy = DummyObject(session)
dummy = DummyObject(parent)
clone = dummy.copy()
for k in DbObject._forbidden_attrs:
assert not hasattr(clone, k), f"Clone should not have forbidden attribute '{k}'"
def test_i_cannot_update_a_forbidden_attribute(session, db_manager):
def test_i_cannot_update_a_forbidden_attribute(parent, db_manager):
@dataclass
class DummyObject(DbObject):
def __init__(self, sess: dict):
super().__init__(sess, "DummyObject", db_manager)
def __init__(self, owner: BaseInstance):
super().__init__(owner, "DummyObject", db_manager)
value: str = "hello"
number: int = 42
none_value: None = None
dummy = DummyObject(session)
dummy = DummyObject(parent)
dummy.update(_session="other_value")
dummy.update(_owner="other_value")
assert dummy._session == session
assert dummy._owner is parent