loosen type Mapper args, add more Database tests

This commit is contained in:
Sam G. 2024-04-18 12:31:16 -07:00
parent 6caf2631b8
commit 0509487b62
6 changed files with 61 additions and 29 deletions

View File

@ -56,7 +56,7 @@ class RelationalAccessor[R: Relation](Accessor[R]):
connection,
text: str
):
connection.exec
#connection.exec
raise NotImplementedError
def select(
@ -104,11 +104,17 @@ class SQLAccessor(RelationalAccessor[SQLTable]):
mappings=False,
include_cols=False,
):
res_method = utils.db.sa_exec_dicts
if mappings:
res_method = utils.db.sa_exec_mappings
res = SQLEngine.execute(
connection,
sql,
bind_params=bind_params,
include_cols=include_cols
)
return res_method(self.database.engine, sa.text(sql), bind_params=bind_params, include_cols=include_cols)
if mappings:
return res.mappings().all()
else:
return self.result_dicts(res)
def select(
self,

View File

@ -37,13 +37,13 @@ class Collector[C: Component]:
def __init__(self, schema: Schema[C]):
self.schema = schema
self._inserts = defaultdict(lambda: defaultdict(list))
self._inserts = {}
@property
def inserts(self):
return self._inserts_from_receipts()
def _inserts_from_receipts(self, receipts: list=None, pop=False):
def _inserts_from_receipts(self, receipts: list[str]|None=None, pop=False):
'''
Group up added inserts by Component, often to be used directly for bulk insertion.
Optionally provide a list of `receipts` to group up only the corresponding subset of
@ -104,7 +104,7 @@ class Collector[C: Component]:
return receipt
def collect_inserts(self, receipts=None):
def collect_inserts(self, receipts:list[str]|None=None):
'''
Collect insert-ready dictionaries for the core primitive schema. This method is
effectively a light wrapper around the File and Note-based collection logic

View File

@ -157,17 +157,25 @@ class Mapper[C: Component]:
self.attach(_type, attr_comp, coll_groups=coll_groups)
def get_attribute_comp(
def get_attr_comp(
self,
type_ref: type[CO3]
co3_ref: CO3 | type[CO3]
) -> C | None:
type_ref = co3_ref
if isinstance(co3_ref, CO3):
type_ref = co3_ref.__class__
return self.attribute_comps.get(type_ref, None)
def get_collation_comp(
def get_coll_comp(
self,
type_ref: type[CO3],
co3_ref: CO3 | type[CO3],
group=str | None,
) -> C | None:
type_ref = co3_ref
if isinstance(co3_ref, CO3):
type_ref = co3_ref.__class__
return self.collation_groups.get(type_ref, {}).get(group, None)
def collect(
@ -201,7 +209,7 @@ class Mapper[C: Component]:
receipts = []
for _cls in reversed(obj.__class__.__mro__[:-2]):
attribute_component = self.get_attribute_comp(_cls)
attribute_component = self.get_attr_comp(_cls)
# require an attribute component for type consideration
if attribute_component is None:
@ -222,7 +230,7 @@ class Mapper[C: Component]:
_, action_groups = obj.action_registry.get(action_key, (None, []))
for action_group in action_groups:
collation_component = self.get_collation_comp(_cls, group=action_group)
collation_component = self.get_coll_comp(_cls, group=action_group)
if collation_component is None:
continue
@ -331,7 +339,7 @@ class ComposableMapper[C: ComposableComponent](Mapper[C]):
def compose(
self,
obj: CO3 | type[CO3],
co3_ref: CO3 | type[CO3],
action_groups: list[str] | None = None,
*compose_args,
**compose_kwargs,
@ -348,13 +356,13 @@ class ComposableMapper[C: ComposableComponent](Mapper[C]):
Parameters:
obj: either a CO3 instance or a type reference
'''
class_ref = obj
if isinstance(obj, CO3):
class_ref = obj.__class__
type_ref = co3_ref
if isinstance(co3_ref, CO3):
type_ref = co3_ref.__class__
attr_comp_agg = None
for _cls in reversed(class_ref.__mro__[:-2]):
attr_comp = self.get_attribute_comp(_cls)
for _cls in reversed(type_ref.__mro__[:-2]):
attr_comp = self.get_attr_comp(_cls)
# require an attribute component for type consideration
if attr_comp is None:
@ -364,7 +372,7 @@ class ComposableMapper[C: ComposableComponent](Mapper[C]):
coll_comp_agg = attr_comp
if action_groups is not None:
for action_group in action_groups:
coll_comp = self.get_collation_comp(_cls, group=action_group)
coll_comp = self.get_coll_comp(_cls, group=action_group)
if coll_comp is None:
continue

View File

@ -7,14 +7,14 @@ def test_mapper_getters():
veg_comp = veg.vegetable_schema.get_component('vegetable')
tom_comp = veg.vegetable_schema.get_component('tomato')
assert veg.vegetable_mapper.get_attribute_comp(veg.Vegetable) is veg_comp
assert veg.vegetable_mapper.get_attribute_comp(veg.Tomato) is tom_comp
assert veg.vegetable_mapper.get_attr_comp(veg.Vegetable) is veg_comp
assert veg.vegetable_mapper.get_attr_comp(veg.Tomato) is tom_comp
tom_aging = veg.vegetable_schema.get_component('tomato_aging_states')
tom_cooking = veg.vegetable_schema.get_component('tomato_cooking_states')
assert veg.vegetable_mapper.get_collation_comp(veg.Tomato, 'aging') is tom_aging
assert veg.vegetable_mapper.get_collation_comp(veg.Tomato, 'cooking') is tom_cooking
assert veg.vegetable_mapper.get_coll_comp(veg.Tomato, 'aging') is tom_aging
assert veg.vegetable_mapper.get_coll_comp(veg.Tomato, 'cooking') is tom_cooking
def test_mapper_attach():
assert veg.vegetable_mapper.attach(

View File

@ -20,6 +20,24 @@ def test_database_insert():
tomato = veg.Tomato('t1', 5)
veg.vegetable_mapper.collect(tomato)
# test instance as arg
tom_comp = veg.vegetable_mapper.get_attr_comp(tomato)
inserts = veg.vegetable_mapper.collector.collect_inserts()
tom_inserts = inserts.get(tom_comp)
assert tom_inserts is not None
with db.engine.connect() as connection:
assert db.manager.insert(
connection,
tom_comp,
tom_inserts,
) is not None
def test_database_insert_many():
tomato = veg.Tomato('t2', 5)
veg.vegetable_mapper.collect(tomato)
with db.engine.connect() as connection:
assert db.manager.insert_many(
connection,

View File

@ -7,14 +7,14 @@ def test_mapper_getters():
veg_comp = veg.vegetable_schema.get_component('vegetable')
tom_comp = veg.vegetable_schema.get_component('tomato')
assert veg.vegetable_mapper.get_attribute_comp(veg.Vegetable) is veg_comp
assert veg.vegetable_mapper.get_attribute_comp(veg.Tomato) is tom_comp
assert veg.vegetable_mapper.get_attr_comp(veg.Vegetable) is veg_comp
assert veg.vegetable_mapper.get_attr_comp(veg.Tomato) is tom_comp
tom_aging = veg.vegetable_schema.get_component('tomato_aging_states')
tom_cooking = veg.vegetable_schema.get_component('tomato_cooking_states')
assert veg.vegetable_mapper.get_collation_comp(veg.Tomato, 'aging') is tom_aging
assert veg.vegetable_mapper.get_collation_comp(veg.Tomato, 'cooking') is tom_cooking
assert veg.vegetable_mapper.get_coll_comp(veg.Tomato, 'aging') is tom_aging
assert veg.vegetable_mapper.get_coll_comp(veg.Tomato, 'cooking') is tom_cooking
def test_mapper_attach():
assert veg.vegetable_mapper.attach(