SQLAlchemy¶
One common use of chide is for creating sample objects and making assertions about
database table contents when using SQLAlchemy. As a result, there are specialised
implementations included to make life easier that are described below.
Sets¶
chide has a special Set subclass that helps to make sure
only one sample object is created with a particular primary key in any
one table.
For example, given these two models:
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
child_id = Column(Integer, ForeignKey('child.id'))
child = relationship('Child')
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
value = Column(Integer)
We can set up a collection of sample values as follows:
from chide import Collection, nest
samples = Collection({
Parent: {'id': 1, 'child': nest(Child)},
Child: {'id': 3, 'value': 42}
})
Now we can quickly make sample objects and add them to a session:
>>> session = Session()
>>> session.add(samples.make(Parent))
>>> session.commit()
This gives us a parent and a child:
>>> session.query(Parent).one()
<Parent ...>
>>> _.child
<Child ...>
If we create multiple parent objects and don’t want to have to worry about
clashing children being created by mistake, we can use a
chide.sqlalchemy.Set to make sure that we only have one sample
object with a given primary key at any time:
>>> from chide.sqlalchemy import Set
>>> current_samples = Set(samples)
>>> session = Session()
>>> session.add(current_samples.get(Parent, id=1))
>>> session.add(current_samples.get(Parent, id=2))
>>> session.commit()
This gives us two parents that both point to the same child:
>>> parent1 = session.query(Parent).filter_by(id=1).one()
>>> parent2 = session.query(Parent).filter_by(id=2).one()
>>> parent1.child is parent2.child
True
Of course, if we want different children, that’s easy too:
>>> session = Session()
>>> session.add(current_samples.get(Parent, id=3, child=Child(value=6)))
>>> session.add(current_samples.get(Parent, id=4, child=Child(value=7)))
>>> session.commit()
The children’s primary keys will be created by the database, but the values are as we need them:
>>> parent3 = session.query(Parent).filter_by(id=3).one()
>>> parent3.child.value
6
>>> parent4 = session.query(Parent).filter_by(id=4).one()
>>> parent4.child.value
7
Row Simplifier¶
For a table such as this:
from sqlalchemy import MetaData, Table, Column, Integer, String
metadata = MetaData()
user_table = Table(
"user_account",
metadata,
Column("id", Integer, primary_key=True),
Column("name", String(30)),
Column("fullname", String),
)
A simplifier is included for the rows returned
by a query such as this:
with engine.connect() as conn:
rows = conn.execute(select(user_table))
It is used as follows:
>>> from chide.sqlalchemy import RowSimplifier
>>> for attrs in RowSimplifier().many(rows):
... print(attrs)
{'id': 1, 'name': 'sandy', 'fullname': 'Sandy Cheeks'}
{'id': 2, 'name': 'patrick', 'fullname': 'Patrick Star'}
ORM-Mapped Object Simplifier¶
For an ORM-mapped objects such as this:
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = "user_account"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
fullname: Mapped[str | None]
A simplifier is included that can be used to simplify the results of a query such as this:
with Session(engine) as session:
objects = session.query(User)
It is used as follows:
>>> from chide.sqlalchemy import MappedSimplifier
>>> for attrs in MappedSimplifier().many(objects):
... print(attrs)
{'id': 1, 'name': 'squidward', 'fullname': 'Squidward Tentacles'}
{'id': 2, 'name': 'ehkrabs', 'fullname': 'Eugene H. Krabs'}