Reference

Extensions

webfluid.extensions — the base extension and the battery set. All of them follow the same shape: a class with an expand_fluid method, instantiated once and reachable through webfluid.core.ext.

FluidExtension

from webfluid.extensions import FluidExtension — the base class for all extensions.

  • expand_fluid(fluid, *args) — override to hook into the app; called automatically when an extension is constructed with a fluid.
  • cli_entry(app, name) — mounts the extension's _cli Typer app under wf.

SQLAlchemy

  • Model — the declarative base; resolves __tablename__ from the snake-cased class name, supports __bind_key__ and Model.set_bind(key).
  • executor(bind_key=None, model=None) / async_executor(...) — context managers yielding an executor with exec, insert, delete, flush; commit/rollback handled for you, and rows survive the block.
  • ensured_executor(...) / ensured_async_executor(...) — reuse an already-open executor or open a fresh one; current_executor / current_async_executor reach the active one or raise.
  • The executors subclass BaseContext, so current(), try_current() and outer() (see Core) work on them too; db.bind_keys lists the configured binds.
  • exec(statement, scalars=True) — returns a ScalarResult by default; pass scalars=False for the raw Result.
  • get_bind_for_model(model) / get_bind(key) — resolve the Bind (with its lazily created sync_engine / async_engine and its own metadata) for a model or key.
  • Config: SQLALCHEMY_DATABASE_URI, SQLALCHEMY_BINDS, SQLALCHEMY_ENGINE_OPTIONS. Drivers are derived; don't put them in the uri.

Babel

  • gettext, ngettext, pgettext, npgettext, their awaitable a* twins and their lazy_* variants (which stay synchronous, since a lazy string resolves through str()).
  • locale_selector(fn) / timezone_selector(fn) — register custom resolvers.
  • force(locale, timezone) / aforce(...) — context managers to pin locale/timezone.
  • register_domain(name, package=None), domain_context(name), current_domain, update_translations(domain, translations) — runtime, db-backed catalogs.
  • load_locale(locale), the CLI (wf babel extract / compile), and the helpers in webfluid.extensions.babel.utils (translation_resolver, get_locale, get_timezone, parse_best_match, to_user_timezone / to_utc, and the format_date / format_currency / ... filters).
  • Three of those changed shape in this release: every formatter's keyword is fmt (format_date spelled it ftm before), to_utc converts to UTC rather than only dropping the offset, and parse_best_match answers a missing header with None instead of the first supported locale.
  • Companions: Domain, I18nKey / I18nMessage (the translation models), LazyString.

Security

Reached through webfluid.core.ext.security; needs EXT_SECURITY and EXT_SQLALCHEMY.

  • user_service — the current-user dependencies (current_user, require_user, require_2fa, require_admin), the require_roles / require_permissions (plus _any_) guard factories, and a _fn twin of each that skips the Depends wrapper.
  • Predicates for a user you already hold: has_2fa, is_admin, has_roles, has_any_role, has_permissions, has_any_permission, check_requirement. All but has_2fa are awaitable.
  • requirement_or_grant(requirement, grant) / requirement_and_grant(...) — accept a session, a JWT grant, or both; resolve_bearer / bearer_principal for the token side alone.
  • hash_service — argon2 hash / verify and the thread-pooled ahash / averify.
  • token_service — CSRF (csrf_protect, csrf_response) and signed single-use tokens (generate_token, validate_token, backed by the ExpiredToken model).
  • oauth_service — authlib-backed social login: the client, prepare_session and userinfo dependencies, authorize_response, and register_provider / unregister_provider for runtime changes.
  • Models in webfluid.extensions.security.models: User, Identity, Role, Permission, TOTPSecret, WebAuthnCredential, BackupCode, ExpiredToken; validators validate_username / validate_password and the PasswordPolicy behind them.

EventManager

  • create_signal(name, singleton=False, internal=False) — declare an event channel. Needs the running loop, so call it from a startup or enable hook.
  • event(name, ...) / query(name, ...) — decorators registering handlers; internal=False exposes them to the browser.
  • trigger(event, data) — publish, synchronously and without waiting; request(query, data) — ask and await a result; listen(event) — async stream.
  • Client: window.wf.ext.events.EventManager.

Mail

  • send(to, subject, body, ...)body is a MIME-subtype map; threads delivery by default (fake_async).
  • asend(...) — the awaited variant. Both accept attachments, cc, bcc, from_email.
  • client() / async_client() — bare SMTP connections as context managers. A send inside one reuses that connection instead of opening its own.
  • Only the async client honours MAIL_USE_TLS; the synchronous one upgrades through MAIL_USE_STARTTLS or stays plaintext.

Cache

  • set / get / delete / clear and the async aset / aget / adelete / aclear.
  • Backends selected by CACHE_TYPE: legacy (in-process, self-expiring) or redis. Reachable as cache.backend.

JWTManager

  • encode(payload, audience="default", expire=None) / decode(token, audience="default") and the async aencode / adecode.
  • Requires EXT_SCHEDULING and EXT_CACHE; rotates its signing secret on a schedule and keeps recent ones in the cache under their key id — which means it needs the redis backend to outlive a restart.
  • A payload carrying a jti is checked against jwt:revoked:<jti> in the cache on decode.

Migrate

A CLI-only extension (wf migrate ...) wrapping Alembic. It builds your app through prepare_fluid() in main.py:

  • init <app> — enroll the matching single- or multi-db template.
  • revision <app> [-a] [-m] — create a revision (optionally autogenerated).
  • upgrade <app> / downgrade <app> [-r] — apply / revert migrations.

Continue reading

From here you can continue straight with Surface.