"""Base SQLalchemy model class with auto repr and tablename.
Requires:
- inflection(https://pypi.org/project/inflection/)
Optional:
- pytest: The output is nicer than bare doctest
Check class docsting for how to use.
To run tests:
```
python -m doctest sqla_base.py
# Or
pytest sqla_base.py --doctest-modules
```
"""
import inflection
from sqlalchemy.ext.declarative import declared_attr
class Base:
"""Class to use with SQLAlchemy declaration_base().
>>> import sqlalchemy as sql
>>> from sqlalchemy.ext.declarative import declarative_base
...
>>> Model = declarative_base(
... cls=Base, bind=sql.create_engine('sqlite:///repr.db')
... )
...
>>> class Person(Model):
... id = sql.Column(sql.Integer, primary_key=True)
... firstname = sql.Column(sql.String(80))
... lastname = sql.Column(sql.String(80))
...
>>> assert Person.__tablename__ == 'people'
...
>>> person = Person(firstname='John', lastname='Doe')
>>> assert repr(person) == "Person(firstname='John', lastname='Doe')"
...
>>> class AnonymousPerson(Model):
... id = sql.Column(sql.Integer, primary_key=True)
...
>>> assert AnonymousPerson.__tablename__ == 'anonymous_people'
"""
@declared_attr
def __tablename__(cls):
return inflection.underscore(inflection.pluralize(cls.__name__))
def __repr__(self):
return "{class_name}({attributes})".format(
class_name=self.__class__.__name__,
attributes=', '.join([
"{attribute}={value}".format(attribute=key, value=repr(val))
for key, val in sorted(self.__dict__.items())
if not key.startswith('_')
])
)