loosen type Mapper args, add more Database tests
This commit is contained in:
parent
b369428eb3
commit
1f89f0dee8
@ -56,7 +56,7 @@ class RelationalAccessor[R: Relation](Accessor[R]):
|
|||||||
connection,
|
connection,
|
||||||
text: str
|
text: str
|
||||||
):
|
):
|
||||||
connection.exec
|
#connection.exec
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def select(
|
def select(
|
||||||
@ -104,11 +104,17 @@ class SQLAccessor(RelationalAccessor[SQLTable]):
|
|||||||
mappings=False,
|
mappings=False,
|
||||||
include_cols=False,
|
include_cols=False,
|
||||||
):
|
):
|
||||||
res_method = utils.db.sa_exec_dicts
|
res = SQLEngine.execute(
|
||||||
if mappings:
|
connection,
|
||||||
res_method = utils.db.sa_exec_mappings
|
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(
|
def select(
|
||||||
self,
|
self,
|
||||||
|
@ -37,13 +37,13 @@ class Collector[C: Component]:
|
|||||||
def __init__(self, schema: Schema[C]):
|
def __init__(self, schema: Schema[C]):
|
||||||
self.schema = schema
|
self.schema = schema
|
||||||
|
|
||||||
self._inserts = defaultdict(lambda: defaultdict(list))
|
self._inserts = {}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def inserts(self):
|
def inserts(self):
|
||||||
return self._inserts_from_receipts()
|
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.
|
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
|
Optionally provide a list of `receipts` to group up only the corresponding subset of
|
||||||
@ -104,7 +104,7 @@ class Collector[C: Component]:
|
|||||||
|
|
||||||
return receipt
|
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
|
Collect insert-ready dictionaries for the core primitive schema. This method is
|
||||||
effectively a light wrapper around the File and Note-based collection logic
|
effectively a light wrapper around the File and Note-based collection logic
|
||||||
|
@ -157,17 +157,25 @@ class Mapper[C: Component]:
|
|||||||
|
|
||||||
self.attach(_type, attr_comp, coll_groups=coll_groups)
|
self.attach(_type, attr_comp, coll_groups=coll_groups)
|
||||||
|
|
||||||
def get_attribute_comp(
|
def get_attr_comp(
|
||||||
self,
|
self,
|
||||||
type_ref: type[CO3]
|
co3_ref: CO3 | type[CO3]
|
||||||
) -> C | None:
|
) -> C | None:
|
||||||
|
type_ref = co3_ref
|
||||||
|
if isinstance(co3_ref, CO3):
|
||||||
|
type_ref = co3_ref.__class__
|
||||||
|
|
||||||
return self.attribute_comps.get(type_ref, None)
|
return self.attribute_comps.get(type_ref, None)
|
||||||
|
|
||||||
def get_collation_comp(
|
def get_coll_comp(
|
||||||
self,
|
self,
|
||||||
type_ref: type[CO3],
|
co3_ref: CO3 | type[CO3],
|
||||||
group=str | None,
|
group=str | None,
|
||||||
) -> C | 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)
|
return self.collation_groups.get(type_ref, {}).get(group, None)
|
||||||
|
|
||||||
def collect(
|
def collect(
|
||||||
@ -201,7 +209,7 @@ class Mapper[C: Component]:
|
|||||||
|
|
||||||
receipts = []
|
receipts = []
|
||||||
for _cls in reversed(obj.__class__.__mro__[:-2]):
|
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
|
# require an attribute component for type consideration
|
||||||
if attribute_component is None:
|
if attribute_component is None:
|
||||||
@ -222,7 +230,7 @@ class Mapper[C: Component]:
|
|||||||
|
|
||||||
_, action_groups = obj.action_registry.get(action_key, (None, []))
|
_, action_groups = obj.action_registry.get(action_key, (None, []))
|
||||||
for action_group in action_groups:
|
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:
|
if collation_component is None:
|
||||||
continue
|
continue
|
||||||
@ -331,7 +339,7 @@ class ComposableMapper[C: ComposableComponent](Mapper[C]):
|
|||||||
|
|
||||||
def compose(
|
def compose(
|
||||||
self,
|
self,
|
||||||
obj: CO3 | type[CO3],
|
co3_ref: CO3 | type[CO3],
|
||||||
action_groups: list[str] | None = None,
|
action_groups: list[str] | None = None,
|
||||||
*compose_args,
|
*compose_args,
|
||||||
**compose_kwargs,
|
**compose_kwargs,
|
||||||
@ -348,13 +356,13 @@ class ComposableMapper[C: ComposableComponent](Mapper[C]):
|
|||||||
Parameters:
|
Parameters:
|
||||||
obj: either a CO3 instance or a type reference
|
obj: either a CO3 instance or a type reference
|
||||||
'''
|
'''
|
||||||
class_ref = obj
|
type_ref = co3_ref
|
||||||
if isinstance(obj, CO3):
|
if isinstance(co3_ref, CO3):
|
||||||
class_ref = obj.__class__
|
type_ref = co3_ref.__class__
|
||||||
|
|
||||||
attr_comp_agg = None
|
attr_comp_agg = None
|
||||||
for _cls in reversed(class_ref.__mro__[:-2]):
|
for _cls in reversed(type_ref.__mro__[:-2]):
|
||||||
attr_comp = self.get_attribute_comp(_cls)
|
attr_comp = self.get_attr_comp(_cls)
|
||||||
|
|
||||||
# require an attribute component for type consideration
|
# require an attribute component for type consideration
|
||||||
if attr_comp is None:
|
if attr_comp is None:
|
||||||
@ -364,7 +372,7 @@ class ComposableMapper[C: ComposableComponent](Mapper[C]):
|
|||||||
coll_comp_agg = attr_comp
|
coll_comp_agg = attr_comp
|
||||||
if action_groups is not None:
|
if action_groups is not None:
|
||||||
for action_group in action_groups:
|
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:
|
if coll_comp is None:
|
||||||
continue
|
continue
|
||||||
|
@ -7,14 +7,14 @@ def test_mapper_getters():
|
|||||||
veg_comp = veg.vegetable_schema.get_component('vegetable')
|
veg_comp = veg.vegetable_schema.get_component('vegetable')
|
||||||
tom_comp = veg.vegetable_schema.get_component('tomato')
|
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_attr_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.Tomato) is tom_comp
|
||||||
|
|
||||||
tom_aging = veg.vegetable_schema.get_component('tomato_aging_states')
|
tom_aging = veg.vegetable_schema.get_component('tomato_aging_states')
|
||||||
tom_cooking = veg.vegetable_schema.get_component('tomato_cooking_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_coll_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, 'cooking') is tom_cooking
|
||||||
|
|
||||||
def test_mapper_attach():
|
def test_mapper_attach():
|
||||||
assert veg.vegetable_mapper.attach(
|
assert veg.vegetable_mapper.attach(
|
||||||
|
@ -20,6 +20,24 @@ def test_database_insert():
|
|||||||
tomato = veg.Tomato('t1', 5)
|
tomato = veg.Tomato('t1', 5)
|
||||||
veg.vegetable_mapper.collect(tomato)
|
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:
|
with db.engine.connect() as connection:
|
||||||
assert db.manager.insert_many(
|
assert db.manager.insert_many(
|
||||||
connection,
|
connection,
|
||||||
|
@ -7,14 +7,14 @@ def test_mapper_getters():
|
|||||||
veg_comp = veg.vegetable_schema.get_component('vegetable')
|
veg_comp = veg.vegetable_schema.get_component('vegetable')
|
||||||
tom_comp = veg.vegetable_schema.get_component('tomato')
|
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_attr_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.Tomato) is tom_comp
|
||||||
|
|
||||||
tom_aging = veg.vegetable_schema.get_component('tomato_aging_states')
|
tom_aging = veg.vegetable_schema.get_component('tomato_aging_states')
|
||||||
tom_cooking = veg.vegetable_schema.get_component('tomato_cooking_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_coll_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, 'cooking') is tom_cooking
|
||||||
|
|
||||||
def test_mapper_attach():
|
def test_mapper_attach():
|
||||||
assert veg.vegetable_mapper.attach(
|
assert veg.vegetable_mapper.attach(
|
||||||
|
Loading…
Reference in New Issue
Block a user