SQLAlchemy

Model Base

The declarative_base() function, allows you to very concisely opt into two columns which are very commonly included on a majority of tables, created_at and :code`updated_at`.

Mypy

You may encounter typing-related issues such as:

error: Variable "models.Base" is not valid as a type
error: Invalid base class "Base"

Because of the dynamically created type, a mypy plugin is required. An example pyproject.toml file enabling the plugin would look like:

[tool.mypy]
plugins = ["strapp.sqlalchemy.mypy"]

Session

Configly Integration

The config argument accepts URL arguments as a typing.Mapping, in order to make usage with Configly more straightforward.

Applications might define their configuration using configly.

config.yml
...
database:
  drivername: postgesql+postgres
  host: <% ENV[DATABASE_HOST] %>
  username: <% ENV[DATABASE_USERNAME] %>
  ... etc ...
...

Then a typical strapp Flask app would construct a config instance once before app startup, and use that to hook up their database to the flask app.

wsgi.py
from configly import Config
from strapp.flask import callback_factory, sqlalchemy_database

config = Configly.from_yaml('config.yml')
callback = callback_factory(sqlalchemy_database, config.database)
app = create_app(callbacks=[callback])

And a typical strapp Click app, might use the resolver and produce the engine that way.

cli.py
from strapp.click import Resolver
from configly import Config

def config():
    return Config.from_yaml("config.yml")

 def postgres(config):
     return strapp.sqlalchemy.create_session(config.database)

resolver = Resolver(config=config, postgres=postgres)

@resolver.group()
def command(postgres):
    ...

In neither case are you required to actually use Configly, but it is intentionally easy to do!