Add crudkit!

This commit is contained in:
Yaro Kasear 2025-08-27 10:27:41 -05:00
parent 30ec29d497
commit 559fd56f33
28 changed files with 881 additions and 23 deletions

42
crudkit/eager.py Normal file
View file

@ -0,0 +1,42 @@
from typing import List
from sqlalchemy.inspection import inspect
from sqlalchemy.orm import Load, joinedload, selectinload
def default_eager_policy(Model, expand: List[str]) -> List[Load]:
"""
Heuristic:
- many-to-one / one-to-one: joinedload
- one-to-many / many-to-many: selectinload
Accepts dotted paths like "author.publisher".
"""
if not expand:
return []
opts: List[Load] = []
for path in expand:
parts = path.split(".")
current_model = Model
current_inspect = inspect(current_model)
# first hop
rel = current_inspect.relationships.get(parts[0])
if not rel:
continue # silently skip bad names
attr = getattr(current_model, parts[0])
loader: Load = selectinload(attr) if rel.uselist else joinedload(attr)
current_model = rel.mapper.class_
# nested hops, if any
for name in parts[1:]:
current_inspect = inspect(current_model)
rel = current_inspect.relationships.get(name)
if not rel:
break
attr = getattr(current_model, name)
loader = loader.selectinload(attr) if rel.uselist else loader.joinedload(attr)
current_model = rel.mapper.class_
opts.append(loader)
return opts