> It's more about the full IO stack than just making Python faster.
Does it mean that your db adapter isn't necessarily DBAPI (PEP-249) compliant? That is, it could be that DBAPI exception hierarchy isn't respected, so that middlewares that expect to work across the stack and catch all DB-related issues, may not work if the underlying DB access stack is using your drivers?
> but F() is still stringly-typed. Room for improvement there.
Yeah, I'm pretty sure F() isn't needed. You can look at how sqlalchemy implements combinator-style API around field attributes:
import sqlalchemy as sa
from sqlalchemy.orm import DeclarativeBase
class Base(sa.orm.DeclarativeBase):
pass
class Stats(Base):
__tablename__ = "stats"
id = sa.Column(sa.Integer, primary_key=True)
views = sa.Column(sa.Integer, nullable=False)
print(Stats.views + 1)
The expression `Stats.views + 1` is self-contained, and can be re-used across queries. `Stats.views` is a smart object (https://docs.sqlalchemy.org/en/21/orm/internals.html#sqlalch...) with overloaded operators that make it re-usable in different contexts, such as result getters and query builders.
Right, it's not DBAPI compliant. The whole IO stack goes through Rust/sqlx, so PEP-249 doesn't apply. Oxyde has its own exception hierarchy (OxydeError, IntegrityError, NotFoundError, etc.). In practice most people catch ORM-level exceptions rather than DBAPI ones, but fair to call out.
On F(), good point. The descriptor approach is something I've been thinking about. Definitely on the radar.