~chiefnoah/quark

11465da1d3e6b6aa3a22710de65a1f72c71a0b5c — Noah Pederson 2 years ago 02a480c master
Fixes some bugs, tests are borked
3 files changed, 56 insertions(+), 8 deletions(-)

M quark/__init__.py
R quark/{quark.py => db.py}
R quark/{test_quark.py => test_db.py}
M quark/__init__.py => quark/__init__.py +1 -1
@@ 1,4 1,4 @@
from .squuid import squuid, squuid_time_millis
from .quark import Quark, Entity
from .db import Quark, Entity

__all__ = ["squuid", "squuid_time_millis", "Quark", "Entity"]

R quark/quark.py => quark/db.py +7 -7
@@ 10,7 10,7 @@ from logging import getLogger
from typing import Any, Dict, Generator, List, Optional, Tuple, Union
from uuid import UUID

import quark.sql as sql
from quark import sql
from quark.errors import (
    DBError,
    IntegrityError,


@@ 130,7 130,7 @@ class Entity(UserDict):
        self.data = properties
        self.db = db
        self.modified = set()
        self.deleted = set()
        self.deleted = dict()

    def detach(self) -> None:
        self.db = None


@@ 162,6 162,7 @@ class Entity(UserDict):
    def __setitem__(self, key, value):
        self.modified.add(key)
        self.data[key] = value
        self.deleted.pop(key, None)

    def commit(self) -> TX:
        if self.db is None:


@@ 169,13 170,12 @@ class Entity(UserDict):
        assertions: List[Assertion] = []
        for key in self.modified:
            assertions.append((":db/add", self.eid, key, self[key]))
        for key in self.deleted:
            assertions.append((":db/retract", self.eid, key, self[key]))
        for key, value in self.deleted.items():
            assertions.append((":db/retract", self.eid, key, value))
        return self.db.transact(assertions)

    def __delitem__(self, key):
        self.deleted.add(key)
        self.pop(key)
        self.deleted[key] = self.data.pop(key)


class Quark:


@@ 375,7 375,7 @@ class Quark:

    def _update_entity_refs(self, assertion: Assertion):
        e = self._entity_refs.get(assertion[1])
        if e:
        if e and e.db:
            e.data[assertion[2]] = assertion[3]

    def _normalize(

R quark/test_quark.py => quark/test_db.py +48 -0
@@ 138,6 138,54 @@ def test_cardinality_many(quark):
    assert entity[':user/email'] == 'noah@packetlost.dev'
    assert isinstance(entity[':user/reportsTo'], Entity)

@pytest.fixture
def db_with_entity(quark):
    schema = [
        {":db/ident": ":user/email", ":db/unique": ":db.unique/identity"},
        {":db/ident": ":user/firstname", ":db/valueType": ":db.type/string"},
        {":db/ident": ":user/lastname", ":db/valueType": ":db.type/string"},
        {":db/ident": ":user/address", ":db/valueType": ":db.type/string"},
        {":db/ident": ":user/job", ":db/valueType": ":db.type/string"},
    ]
    tx = quark.transact(schema)
    temp_id = "abc"
    assertion = {
        ":db/id": temp_id,
        ":user/email": "noah@packetlost.dev",
        ":user/firstname": "Noah",
        ":user/lastname": "Pederson",
        ":user/address": "Fake address",
        ":user/job": "Software Engineer",
    }
    tx = quark.transact([assertion])
    return quark, tx.temp_ids[temp_id]

def test_entity_sync_update(db_with_entity):
    quark, eid = db_with_entity
    noah = quark.get_entity(eid)
    # Check that we have the right entity
    assert noah[":user/job"] == "Software Engineer"
    other_noah = quark.get_entity(eid)
    assert noah[':user/job'] == other_noah[':user/job']
    noah[':user/job'] = 'CEO'
    assert noah[':user/job'] == 'CEO'
    assert other_noah[":user/job"] == "Software Engineer"
    noah.commit()
    assert other_noah[":user/job"] == "CEO"

def test_entity_sync_del(db_with_entity):
    quark, eid = db_with_entity
    noah = quark.get_entity(eid)
    other_noah = quark.get_entity(eid)
    assert noah[':user/job'] == 'Software Engineer'
    del noah[':user/job']
    with pytest.raises(KeyError):
        noah[':user/job']
    assert other_noah[':user/job'] == 'Software Engineer'
    noah.commit()
    with pytest.raises(KeyError):
        other_noah[':user/job']



if __name__ == "__main__":