diff --git a/src/beakers/record.py b/src/beakers/record.py new file mode 100644 index 0000000..5c358d6 --- /dev/null +++ b/src/beakers/record.py @@ -0,0 +1,23 @@ +import uuid +from pydantic import BaseModel + + +class Record: + _reserved_names = ("id",) + + def __init__(self, id: str | None = None): + self._id = id if id else str(uuid.uuid1()) + self._data: dict[str, BaseModel] = {} + + def __getattr__(self, name: str) -> str | BaseModel: + if name == "id": + return self._id + return self._data[name] + + def __setattr__(self, name: str, value: BaseModel) -> None: + if name.startswith("_"): + super().__setattr__(name, value) + elif name not in self._data and name not in self._reserved_names: + self._data[name] = value + else: + raise AttributeError(f"DataObject attribute {name} already exists") diff --git a/tests/test_record.py b/tests/test_record.py new file mode 100644 index 0000000..d30c570 --- /dev/null +++ b/tests/test_record.py @@ -0,0 +1,34 @@ +from beakers.record import Record +import pytest + + +def test_record_id_autogen(): + r = Record() + assert len(r.id) == 36 + r2, r3 = Record(), Record() + assert r2.id != r3.id + + +def test_record_id_assign(): + r = Record(id="test") + assert r.id == "test" + + +def test_record_setattr_good(): + r = Record() + r.attrib = "set" + assert r.attrib == "set" + + +def test_record_setattr_duplicate(): + r = Record() + r.attrib = "set" + with pytest.raises(AttributeError): + r.attrib = "changed" + assert r.attrib == "set" + + +def test_record_setattr_id(): + r = Record() + with pytest.raises(AttributeError): + r.id = "changed"