tempest-fastapi-sdk 0.62.0__tar.gz → 0.63.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/CHANGELOG.md +35 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/PKG-INFO +10 -1
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/README.md +9 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/migration.en.md +30 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/migration.md +30 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/pyproject.toml +1 -1
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/__init__.py +1 -1
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/dependencies/auth.py +60 -16
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/service.py +31 -4
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/repository.py +23 -3
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/auth/test_service.py +63 -1
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_repository.py +32 -1
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/uv.lock +2 -2
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/.github/workflows/ci.yml +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/.github/workflows/docs.yml +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/.github/workflows/release-pypi.yml +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/.gitignore +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/.python-version +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/CLAUDE.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/Makefile +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/architecture.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/architecture.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/changelog.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/changelog.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/contributing.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/contributing.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/index.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/index.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/installation.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/installation.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/index.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/index.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/api.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/api.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/business-rules.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/business-rules.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/domain.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/domain.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/flows.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/flows.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/index.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/index.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/admin.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/admin.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/audit-trail.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/audit-trail.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/auth-flow.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/auth-flow.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/br-helpers.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/br-helpers.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/cache.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/cache.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/cli.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/cli.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/database.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/database.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/deploy-safety.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/deploy-safety.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/downloads.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/downloads.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/email.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/email.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/feature-flags.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/feature-flags.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/http-client.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/http-client.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/http.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/http.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/idempotency.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/idempotency.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/index.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/index.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/logging.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/logging.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/metrics.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/metrics.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/mfa.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/mfa.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/multi-tenant.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/multi-tenant.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/observability.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/observability.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/offline-sync.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/offline-sync.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/outbox.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/outbox.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/queue-tasks.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/queue-tasks.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/realtime.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/realtime.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/security.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/security.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/sessions.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/sessions.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/storage.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/storage.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/testing.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/testing.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/uploads.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/uploads.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/utilities.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/utilities.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/webpush.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/webpush.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/websocket.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/recipes/websocket.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/reference.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/reference.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/roadmap.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/roadmap.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/tutorial.en.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/tutorial.md +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/mkdocs.yml +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/scripts/extract_recipe.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/auth.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/config.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/forms.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/router.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/session.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/site.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/static/admin.css +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/templates/base.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/templates/dashboard.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/templates/detail.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/templates/form.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/templates/list.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/templates/login.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/templates/logs.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/admin/templates/mfa.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/cookies.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/dependencies/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/handlers.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/middlewares/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/middlewares/body_size.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/middlewares/cors.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/middlewares/csrf.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/middlewares/graceful.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/middlewares/idempotency.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/middlewares/rate_limit.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/middlewares/request_id.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/oauth.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/routers/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/routers/health.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/routers/logs.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/routers/metrics.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/routers/tool_spec.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/server.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/static.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/tracing.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/api/webhooks.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/guards.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/locale.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/page_renderer.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/router.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/schemas.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/en-US/activation.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/en-US/activation_error.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/en-US/activation_success.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_error.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_form.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_success.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation_error.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation_success.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_error.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_form.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_success.html +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cache/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cache/decorator.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cache/invalidation.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cache/redis_manager.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/README.md.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/env.example.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/gitignore.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/main.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/pyproject.toml.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/api/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/api/app.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/auth.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/resources.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/api/routers/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/controllers/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/core/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/core/exceptions.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/core/settings.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/db/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/db/models/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/db/models/user.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/db/repositories/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/schemas/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/server.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/services/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/src/utils/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/tests/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/_templates/tests/test_smoke.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/db.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/docker_compose.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/generate.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/lint.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/main.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/new.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/secrets.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/src_layers.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/cli/user.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/controllers/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/controllers/base.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/core/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/core/context.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/core/enums.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/core/logging.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/_alembic_templates/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/_alembic_templates/env.py.template +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/alembic_hooks.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/audit.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/connection.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/migrations.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/mixins.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/model.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/outbox.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/slow_query.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/tenant.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/user_model.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/user_recovery_code_model.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/user_token_model.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/base.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/conflict.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/forbidden.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/i18n.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/jwt.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/not_found.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/too_many_requests.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/unauthorized.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/upload.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/exceptions/validation.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/flags/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/flags/backends.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/flags/dependencies.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/flags/service.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/py.typed +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/queue/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/queue/manager.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/schemas/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/schemas/base.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/schemas/link_headers.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/schemas/logs.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/schemas/pagination.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/schemas/response.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/services/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/services/base.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/sessions/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/sessions/dependencies.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/sessions/middleware.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/sessions/router.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/sessions/schemas.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/sessions/service.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/sessions/store.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/settings/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/settings/base.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/settings/mixins.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/sse/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/sse/event_stream.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/storage/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/storage/minio_client.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/tasks/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/tasks/manager.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/tasks/scheduler.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/testing/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/testing/database.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/client_ip.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/data/br_locations.json +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/datetime.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/dict.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/download.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/email.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/http_client.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/jwt.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/locations.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/log.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/metrics.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/opaque_token.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/password.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/regex.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/storage_backends.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/throttle.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/totp.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/utils/upload.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/webpush/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/webpush/dispatcher.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/webpush/schemas.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/websockets/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/websockets/hub.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/websockets/router.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/websockets/schemas.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/admin/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/admin/test_auth.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/admin/test_forms.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/admin/test_logs_nav.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/admin/test_mfa.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/admin/test_router.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/admin/test_site.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/admin/test_user_model.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_body_size.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_cookies.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_cors.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_csrf.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_dependencies_auth.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_graceful.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_handlers.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_health_router.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_idempotency.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_jwt_dependency.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_logs_router.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_oauth.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_prometheus.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_rate_limit.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_rate_limit_extras.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_request_id_middleware.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_role_dependency.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_server.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_static.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_tool_spec.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_tracing.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_webhooks.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/api/test_webhooks_rsa.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/auth/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/auth/test_guards.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/auth/test_locale.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/auth/test_mfa.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/cache/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/cache/test_decorator.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/cache/test_invalidation.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/cache/test_redis_manager.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/cli/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/cli/test_db.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/cli/test_db_seed.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/cli/test_docker_compose.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/cli/test_generate.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/cli/test_main.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/cli/test_secrets.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/cli/test_user.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/conftest.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/controllers/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/controllers/test_base.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/core/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/core/test_context.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/core/test_enums.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/core/test_logging.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/db/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_alembic_hooks.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_audit.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_bulk_ops.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_connection.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_migrations.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_mixins.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_model.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_outbox.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_safe_upgrade.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_slow_query.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/db/test_tenant.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/exceptions/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/exceptions/test_exceptions.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/exceptions/test_i18n.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/flags/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/flags/test_flags.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/queue/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/queue/test_manager.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/schemas/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/schemas/test_base.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/schemas/test_cursor_pagination.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/schemas/test_link_headers.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/schemas/test_pagination.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/schemas/test_response.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/services/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/services/test_base.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/sessions/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/sessions/test_sessions.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/settings/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/settings/test_base.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/settings/test_mixins.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/sse/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/sse/test_event_stream.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/storage/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/storage/test_minio_client.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/tasks/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/tasks/test_manager.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/tasks/test_scheduler.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/testing/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/testing/test_database.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_client_ip.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_datetime.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_dict.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_download.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_email.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_http_client.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_jwt.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_lazy_extras.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_locations.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_log.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_metrics.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_opaque_token.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_password.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_regex.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_storage_backends.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_throttle.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/utils/test_upload.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/webpush/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/webpush/test_dispatcher.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/webpush/test_schemas.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/websockets/__init__.py +0 -0
- {tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tests/websockets/test_hub_and_router.py +0 -0
|
@@ -5,6 +5,41 @@ All notable changes to **tempest-fastapi-sdk** are listed below.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.63.0] — 2026-06-21
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- **`UserAuthService.current_user_dependency()` now loads the authenticated
|
|
13
|
+
user on the request-scoped session** (`db.session_dependency` by default)
|
|
14
|
+
instead of opening its own short-lived session through `load_user`.
|
|
15
|
+
Previously the returned `UserModel` was **detached** — mutating it and
|
|
16
|
+
committing/refreshing on the request's repository session raised
|
|
17
|
+
`InvalidRequestError: Instance is not persistent within this Session`,
|
|
18
|
+
and lazy-relationship access raised `DetachedInstanceError`. The user is
|
|
19
|
+
now attached to the same session repositories use. **Breaking** only for
|
|
20
|
+
apps whose repositories do not share the auth service's session callable;
|
|
21
|
+
pass `session_dependency=` to point both at the same provider. See the
|
|
22
|
+
**Migration guide** (`docs/migration.md`). The single-argument `user_loader` path
|
|
23
|
+
of `make_jwt_user_dependency` is unchanged; the new behavior is opt-in via
|
|
24
|
+
the new `session_dependency=` parameter (which `current_user_dependency`
|
|
25
|
+
now passes by default).
|
|
26
|
+
- **`BaseRepository.resolve()` re-attaches detached instances** via
|
|
27
|
+
`session.merge()` instead of returning them as-is. A detached model passed
|
|
28
|
+
to a mutating service is brought back into the active session, so the
|
|
29
|
+
subsequent `update()` commits instead of raising. `merge` issues a
|
|
30
|
+
`SELECT` only when the row is not already in the session's identity map.
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
|
|
34
|
+
- **`make_jwt_user_dependency(..., session_dependency=...)`** — when given a
|
|
35
|
+
request-scoped session provider, the dependency injects it and calls the
|
|
36
|
+
two-argument loader `user_loader(subject, session)`, sharing the session
|
|
37
|
+
with the request's repositories.
|
|
38
|
+
- **`UserAuthService.current_user_dependency(session_dependency=...)`** —
|
|
39
|
+
override the session provider shared with repositories (defaults to
|
|
40
|
+
`self.db.session_dependency`). Now raises `RuntimeError` eagerly when the
|
|
41
|
+
service was built without `db=`.
|
|
42
|
+
|
|
8
43
|
## [0.62.0] — 2026-06-20
|
|
9
44
|
|
|
10
45
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tempest-fastapi-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.63.0
|
|
4
4
|
Summary: Shared FastAPI building blocks: base schemas, ORM model, async repository, exceptions, pagination and settings — the conventions used across Tempest projects.
|
|
5
5
|
Project-URL: Homepage, https://github.com/mauriciobenjamin700/tempest-fastapi-sdk
|
|
6
6
|
Project-URL: Repository, https://github.com/mauriciobenjamin700/tempest-fastapi-sdk
|
|
@@ -1167,6 +1167,15 @@ async def me(current: UserModel = Depends(get_current_user)) -> UserResponseSche
|
|
|
1167
1167
|
> get_current_user = auth_service.current_user_dependency()
|
|
1168
1168
|
> get_current_user_or_none = auth_service.current_user_dependency(soft=True)
|
|
1169
1169
|
> ```
|
|
1170
|
+
>
|
|
1171
|
+
> The authenticated user is loaded on the **request-scoped session**
|
|
1172
|
+
> (`db.session_dependency`), so it is attached to the same session your
|
|
1173
|
+
> repositories use — you can mutate it and `commit`/`refresh` without an
|
|
1174
|
+
> `InvalidRequestError: Instance is not persistent within this Session`.
|
|
1175
|
+
> Keep one shared session callable (`get_session = db.session_dependency`)
|
|
1176
|
+
> for FastAPI to deduplicate them; if your repositories depend on a
|
|
1177
|
+
> different `get_session` wrapper, pass it as
|
|
1178
|
+
> `current_user_dependency(session_dependency=get_session)`.
|
|
1170
1179
|
|
|
1171
1180
|
#### Soft auth (optional user)
|
|
1172
1181
|
|
|
@@ -1064,6 +1064,15 @@ async def me(current: UserModel = Depends(get_current_user)) -> UserResponseSche
|
|
|
1064
1064
|
> get_current_user = auth_service.current_user_dependency()
|
|
1065
1065
|
> get_current_user_or_none = auth_service.current_user_dependency(soft=True)
|
|
1066
1066
|
> ```
|
|
1067
|
+
>
|
|
1068
|
+
> The authenticated user is loaded on the **request-scoped session**
|
|
1069
|
+
> (`db.session_dependency`), so it is attached to the same session your
|
|
1070
|
+
> repositories use — you can mutate it and `commit`/`refresh` without an
|
|
1071
|
+
> `InvalidRequestError: Instance is not persistent within this Session`.
|
|
1072
|
+
> Keep one shared session callable (`get_session = db.session_dependency`)
|
|
1073
|
+
> for FastAPI to deduplicate them; if your repositories depend on a
|
|
1074
|
+
> different `get_session` wrapper, pass it as
|
|
1075
|
+
> `current_user_dependency(session_dependency=get_session)`.
|
|
1067
1076
|
|
|
1068
1077
|
#### Soft auth (optional user)
|
|
1069
1078
|
|
|
@@ -2,6 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
Breaking-change walkthroughs grouped by minor release. Stick to the version that matches what you're upgrading **from**.
|
|
4
4
|
|
|
5
|
+
## 0.63.0 — authenticated user loaded on the request session
|
|
6
|
+
|
|
7
|
+
Before 0.63.0, `UserAuthService.current_user_dependency()` loaded the authenticated user through `load_user`, which opened its **own** session (via `db.get_session_context()`) and closed it on exit. The `UserModel` handed to the route was therefore **detached**: mutating it and calling `commit`/`refresh` on the request session (the one your repositories use) raised
|
|
8
|
+
`InvalidRequestError: Instance is not persistent within this Session`.
|
|
9
|
+
|
|
10
|
+
From 0.63.0 the dependency loads the user on the **request session** (`db.session_dependency` by default) via `get_user(subject, session)`. The user is attached to the same session repositories use, so lazy-relationship reads and writes work without re-attaching anything.
|
|
11
|
+
|
|
12
|
+
!!! warning "Compatibility"
|
|
13
|
+
The auth dependency and your repositories must share the **same** session callable for FastAPI's sub-dependency cache to deduplicate them. The recommended pattern is already covered:
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
# resources.py
|
|
17
|
+
get_session = db.session_dependency # one object, reused
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
If you wrap the session in your own provider (`async def get_session(): ...`), pass it explicitly, otherwise the dependency opens a second session and the user is detached again:
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
get_current_user = auth.current_user_dependency(session_dependency=get_session)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
!!! info "Extra safety net"
|
|
27
|
+
`BaseRepository.resolve()` now re-attaches detached instances via `session.merge()`. Even if some flow still hands in a detached user, `resolve` brings it back into the active session instead of breaking — so services that worked around this (re-fetch by id before mutating) can drop the workaround.
|
|
28
|
+
|
|
29
|
+
### Verify
|
|
30
|
+
|
|
31
|
+
- Drop any "re-fetch by id before mutating the authenticated user" workaround — it's no longer needed.
|
|
32
|
+
- A single-argument `user_loader` passed to `make_jwt_user_dependency` keeps working. To share the request session, pass `session_dependency=` and use a two-argument loader `(subject, session)`.
|
|
33
|
+
|
|
34
|
+
## 0.8.0 — `ServerSettings` rename
|
|
5
35
|
|
|
6
36
|
0.8.0 renames every field on `ServerSettings`, extracts log fields to a new `LogSettings` mixin, and adds eleven other primitives. The renames are the only **breaking** changes — every new primitive is opt-in.
|
|
7
37
|
|
|
@@ -2,6 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
Passo a passo das mudanças que quebram compatibilidade, agrupadas por release minor. Siga a versão que casa com aquela **de onde** você está atualizando.
|
|
4
4
|
|
|
5
|
+
## 0.63.0 — usuário autenticado carregado na sessão de request
|
|
6
|
+
|
|
7
|
+
Antes da 0.63.0, `UserAuthService.current_user_dependency()` carregava o usuário autenticado chamando `load_user`, que abria a **própria** sessão (via `db.get_session_context()`) e a fechava ao terminar. O `UserModel` entregue à rota ficava **detached**: mutá-lo e dar `commit`/`refresh` na sessão de request (a dos seus repositories) levantava
|
|
8
|
+
`InvalidRequestError: Instance is not persistent within this Session`.
|
|
9
|
+
|
|
10
|
+
A partir da 0.63.0 a dependência carrega o usuário na **sessão de request** (`db.session_dependency` por padrão), via `get_user(subject, session)`. O usuário fica anexado à mesma sessão que os repositories usam, então leituras de relacionamentos lazy e escritas funcionam sem reanexar nada.
|
|
11
|
+
|
|
12
|
+
!!! warning "Compatibilidade"
|
|
13
|
+
A dependência de auth e seus repositories precisam compartilhar o **mesmo callable** de sessão para o cache de sub-dependências do FastAPI casar. Quem segue o padrão recomendado já está coberto:
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
# resources.py
|
|
17
|
+
get_session = db.session_dependency # um único objeto, reutilizado
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Se você embrulha a sessão num provider próprio (`async def get_session(): ...`), passe-o explicitamente para a dependência, senão ela abre uma segunda sessão e o usuário volta a ficar detached:
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
get_current_user = auth.current_user_dependency(session_dependency=get_session)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
!!! info "Defesa adicional"
|
|
27
|
+
`BaseRepository.resolve()` agora reanexa instâncias detached via `session.merge()`. Mesmo que algum fluxo ainda receba um usuário detached, o `resolve` o traz de volta à sessão ativa em vez de quebrar — então serviços que faziam workarounds manuais (re-fetch por id antes de mutar) podem removê-los.
|
|
28
|
+
|
|
29
|
+
### Verifique
|
|
30
|
+
|
|
31
|
+
- Remova qualquer workaround do tipo "re-fetch por id antes de mutar o usuário autenticado" — não é mais necessário.
|
|
32
|
+
- Se você passava um `user_loader` de um argumento para `make_jwt_user_dependency`, ele continua funcionando. Para compartilhar a sessão de request, passe `session_dependency=` e use um loader de dois argumentos `(subject, session)`.
|
|
33
|
+
|
|
34
|
+
## 0.8.0 — renomeação de `ServerSettings`
|
|
5
35
|
|
|
6
36
|
A 0.8.0 renomeia todos os campos de `ServerSettings`, extrai os campos de log para um novo mixin `LogSettings` e adiciona onze outros primitivos. As renomeações são as únicas mudanças **que quebram** — todo primitivo novo é opt-in.
|
|
7
37
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "tempest-fastapi-sdk"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.63.0"
|
|
4
4
|
description = "Shared FastAPI building blocks: base schemas, ORM model, async repository, exceptions, pagination and settings — the conventions used across Tempest projects."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -139,6 +139,7 @@ def make_jwt_user_dependency(
|
|
|
139
139
|
bearer_scheme: HTTPBearer | None = None,
|
|
140
140
|
subject_claim: str = "sub",
|
|
141
141
|
error_message: str = "Authorization token is missing or invalid",
|
|
142
|
+
session_dependency: Callable[..., Any] | None = None,
|
|
142
143
|
) -> Callable[..., Coroutine[Any, Any, Any]]:
|
|
143
144
|
"""Build a FastAPI dependency that returns the authenticated user.
|
|
144
145
|
|
|
@@ -150,15 +151,33 @@ def make_jwt_user_dependency(
|
|
|
150
151
|
4. Awaits ``user_loader(<id>)`` and returns whatever it yields.
|
|
151
152
|
|
|
152
153
|
``user_loader`` is the single seam where the service maps
|
|
153
|
-
``payload[subject_claim]`` to an actual user.
|
|
154
|
-
|
|
155
|
-
|
|
154
|
+
``payload[subject_claim]`` to an actual user.
|
|
155
|
+
|
|
156
|
+
**Session sharing.** When ``session_dependency`` is given, the
|
|
157
|
+
returned dependency declares it as a sub-dependency and calls the
|
|
158
|
+
two-argument ``user_loader(subject, session)`` with the
|
|
159
|
+
**request-scoped** session. Because FastAPI caches a sub-dependency
|
|
160
|
+
by its callable within a single request, the authenticated user is
|
|
161
|
+
loaded on the *same* session the request's repositories use — so the
|
|
162
|
+
instance stays attached and can be mutated / refreshed without the
|
|
163
|
+
``InvalidRequestError: Instance is not persistent within this
|
|
164
|
+
Session`` that a per-loader private session would cause. Pass the
|
|
165
|
+
**exact** callable your repositories depend on (e.g.
|
|
166
|
+
``db.session_dependency``); a different wrapper would resolve to a
|
|
167
|
+
second, distinct session and defeat the sharing.
|
|
168
|
+
|
|
169
|
+
When ``session_dependency`` is ``None`` the loader is called with a
|
|
170
|
+
single argument (``user_loader(subject)``) and owns its own session
|
|
171
|
+
lifecycle — useful outside a request scope, but it yields a
|
|
172
|
+
**detached** instance.
|
|
156
173
|
|
|
157
174
|
Args:
|
|
158
175
|
tokens (JWTUtils): The JWT helper used to verify the token.
|
|
159
176
|
user_loader (Callable[..., Coroutine[Any, Any, Any]]): Async
|
|
160
177
|
callable that receives the subject (typically the user id
|
|
161
|
-
as a string) and returns the loaded user.
|
|
178
|
+
as a string) and returns the loaded user. When
|
|
179
|
+
``session_dependency`` is set it is called as
|
|
180
|
+
``user_loader(subject, session)``. Raise
|
|
162
181
|
:class:`UnauthorizedException` or
|
|
163
182
|
:class:`NotFoundException` from inside the loader when the
|
|
164
183
|
user no longer exists.
|
|
@@ -169,6 +188,10 @@ def make_jwt_user_dependency(
|
|
|
169
188
|
Defaults to ``"sub"``.
|
|
170
189
|
error_message (str): Message attached to the raised
|
|
171
190
|
:class:`UnauthorizedException` when ``soft`` is ``False``.
|
|
191
|
+
session_dependency (Callable[..., Any] | None): The
|
|
192
|
+
request-scoped session provider to share with repositories.
|
|
193
|
+
When set, ``user_loader`` is called with ``(subject,
|
|
194
|
+
session)``.
|
|
172
195
|
|
|
173
196
|
Returns:
|
|
174
197
|
Callable[..., Coroutine[Any, Any, Any]]: An async FastAPI
|
|
@@ -181,20 +204,41 @@ def make_jwt_user_dependency(
|
|
|
181
204
|
error_message=error_message,
|
|
182
205
|
)
|
|
183
206
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
if subject is None:
|
|
191
|
-
if soft:
|
|
207
|
+
if session_dependency is None:
|
|
208
|
+
|
|
209
|
+
async def _current_user_owns_session(
|
|
210
|
+
payload: dict[str, Any] | None = Depends(decode_bearer),
|
|
211
|
+
) -> Any:
|
|
212
|
+
if payload is None:
|
|
192
213
|
return None
|
|
193
|
-
|
|
194
|
-
|
|
214
|
+
subject = payload.get(subject_claim)
|
|
215
|
+
if subject is None:
|
|
216
|
+
if soft:
|
|
217
|
+
return None
|
|
218
|
+
raise UnauthorizedException(message=error_message)
|
|
219
|
+
return await user_loader(subject)
|
|
220
|
+
|
|
221
|
+
dependency = _current_user_owns_session
|
|
222
|
+
|
|
223
|
+
else:
|
|
224
|
+
|
|
225
|
+
async def _current_user_shared_session(
|
|
226
|
+
payload: dict[str, Any] | None = Depends(decode_bearer),
|
|
227
|
+
session: Any = Depends(session_dependency),
|
|
228
|
+
) -> Any:
|
|
229
|
+
if payload is None:
|
|
230
|
+
return None
|
|
231
|
+
subject = payload.get(subject_claim)
|
|
232
|
+
if subject is None:
|
|
233
|
+
if soft:
|
|
234
|
+
return None
|
|
235
|
+
raise UnauthorizedException(message=error_message)
|
|
236
|
+
return await user_loader(subject, session)
|
|
237
|
+
|
|
238
|
+
dependency = _current_user_shared_session
|
|
195
239
|
|
|
196
|
-
|
|
197
|
-
return
|
|
240
|
+
dependency.__doc__ = "Decode the bearer JWT and resolve the authenticated user."
|
|
241
|
+
return dependency
|
|
198
242
|
|
|
199
243
|
|
|
200
244
|
def make_role_dependency(
|
{tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/auth/service.py
RENAMED
|
@@ -528,11 +528,12 @@ class UserAuthService:
|
|
|
528
528
|
self,
|
|
529
529
|
*,
|
|
530
530
|
soft: bool = False,
|
|
531
|
+
session_dependency: Callable[..., Any] | None = None,
|
|
531
532
|
) -> Callable[..., Coroutine[Any, Any, Any]]:
|
|
532
533
|
"""Build a FastAPI dependency that returns the authenticated user.
|
|
533
534
|
|
|
534
535
|
Wraps :func:`tempest_fastapi_sdk.make_jwt_user_dependency` with
|
|
535
|
-
this service's own :class:`JWTUtils` and :meth:`
|
|
536
|
+
this service's own :class:`JWTUtils` and :meth:`get_user`, so
|
|
536
537
|
the bearer token is verified with the **same** secret the
|
|
537
538
|
service signs with — there is no second ``JWTUtils`` to keep in
|
|
538
539
|
sync. Mount it on any of your routes:
|
|
@@ -542,23 +543,49 @@ class UserAuthService:
|
|
|
542
543
|
... soft=True
|
|
543
544
|
... )
|
|
544
545
|
|
|
545
|
-
|
|
546
|
-
|
|
546
|
+
The authenticated user is loaded on the **request-scoped**
|
|
547
|
+
session (``self.db.session_dependency`` by default), so it is
|
|
548
|
+
attached to the same session the request's repositories use and
|
|
549
|
+
can be mutated / refreshed without an
|
|
550
|
+
``InvalidRequestError: Instance is not persistent within this
|
|
551
|
+
Session``. If your repositories depend on a different session
|
|
552
|
+
callable (e.g. a project-local ``get_session`` wrapper), pass it
|
|
553
|
+
as ``session_dependency`` so both resolve to the *same* request
|
|
554
|
+
session — FastAPI caches a sub-dependency by its callable, so a
|
|
555
|
+
distinct wrapper would open a second session and detach the user.
|
|
556
|
+
|
|
557
|
+
Requires the service to have been built with ``db=``.
|
|
547
558
|
|
|
548
559
|
Args:
|
|
549
560
|
soft (bool): When ``True``, the dependency returns ``None``
|
|
550
561
|
instead of raising on a missing / invalid token — for
|
|
551
562
|
endpoints that work both authenticated and anonymous.
|
|
563
|
+
session_dependency (Callable[..., Any] | None): The
|
|
564
|
+
request-scoped session provider to share with
|
|
565
|
+
repositories. Defaults to ``self.db.session_dependency``.
|
|
552
566
|
|
|
553
567
|
Returns:
|
|
554
568
|
Callable[..., Coroutine[Any, Any, Any]]: An async FastAPI
|
|
555
569
|
dependency yielding the user (or ``None`` in soft mode).
|
|
570
|
+
|
|
571
|
+
Raises:
|
|
572
|
+
RuntimeError: When the service was created without ``db=``.
|
|
556
573
|
"""
|
|
574
|
+
if self.db is None:
|
|
575
|
+
raise RuntimeError(
|
|
576
|
+
"UserAuthService was created without `db=`; pass an "
|
|
577
|
+
"AsyncDatabaseManager to use current_user_dependency."
|
|
578
|
+
)
|
|
557
579
|
from tempest_fastapi_sdk.api.dependencies.auth import (
|
|
558
580
|
make_jwt_user_dependency,
|
|
559
581
|
)
|
|
560
582
|
|
|
561
|
-
return make_jwt_user_dependency(
|
|
583
|
+
return make_jwt_user_dependency(
|
|
584
|
+
self.jwt,
|
|
585
|
+
self.get_user,
|
|
586
|
+
soft=soft,
|
|
587
|
+
session_dependency=session_dependency or self.db.session_dependency,
|
|
588
|
+
)
|
|
562
589
|
|
|
563
590
|
# ------------------------------------------------------------------
|
|
564
591
|
# Authorization guards (imperative, on an already-loaded user)
|
{tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/tempest_fastapi_sdk/db/repository.py
RENAMED
|
@@ -9,7 +9,16 @@ from datetime import date, datetime
|
|
|
9
9
|
from typing import Any, Generic, List, TypeVar, cast
|
|
10
10
|
from uuid import UUID
|
|
11
11
|
|
|
12
|
-
from sqlalchemy import
|
|
12
|
+
from sqlalchemy import (
|
|
13
|
+
CursorResult,
|
|
14
|
+
Select,
|
|
15
|
+
delete,
|
|
16
|
+
func,
|
|
17
|
+
insert,
|
|
18
|
+
inspect,
|
|
19
|
+
select,
|
|
20
|
+
update,
|
|
21
|
+
)
|
|
13
22
|
from sqlalchemy.exc import IntegrityError
|
|
14
23
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
15
24
|
|
|
@@ -337,14 +346,23 @@ class BaseRepository(Generic[ModelType]):
|
|
|
337
346
|
``if isinstance(x, UUID): ... else: ...`` boilerplate services
|
|
338
347
|
reimplement whenever a method takes ``UUID | Model``.
|
|
339
348
|
|
|
349
|
+
When given a **detached** instance (one whose session has been
|
|
350
|
+
closed — e.g. a user loaded by an auth dependency on its own
|
|
351
|
+
short-lived session) it is re-attached to this repository's
|
|
352
|
+
session via :meth:`AsyncSession.merge`. Returning it as-is would
|
|
353
|
+
later raise ``InvalidRequestError: Instance is not persistent
|
|
354
|
+
within this Session`` on the first ``commit`` / ``refresh``.
|
|
355
|
+
``merge`` issues a ``SELECT`` only when the row is not already in
|
|
356
|
+
this session's identity map.
|
|
357
|
+
|
|
340
358
|
Args:
|
|
341
359
|
ref (UUID | ModelType): The primary key to look up, or an
|
|
342
|
-
already-loaded instance to return
|
|
360
|
+
already-loaded instance to attach and return.
|
|
343
361
|
for_update (bool): Whether to acquire a row-level lock when
|
|
344
362
|
``ref`` is a ``UUID`` (ignored when an instance is given).
|
|
345
363
|
|
|
346
364
|
Returns:
|
|
347
|
-
ModelType: The resolved instance.
|
|
365
|
+
ModelType: The resolved instance, attached to this session.
|
|
348
366
|
|
|
349
367
|
Raises:
|
|
350
368
|
AppException: ``self.not_found_exception`` when ``ref`` is a
|
|
@@ -352,6 +370,8 @@ class BaseRepository(Generic[ModelType]):
|
|
|
352
370
|
"""
|
|
353
371
|
if isinstance(ref, UUID):
|
|
354
372
|
return await self.get_by_id(ref, for_update=for_update)
|
|
373
|
+
if inspect(ref).detached:
|
|
374
|
+
return await self.session.merge(ref)
|
|
355
375
|
return ref
|
|
356
376
|
|
|
357
377
|
async def exists(self, filters: dict[str, Any]) -> bool:
|
|
@@ -9,7 +9,7 @@ from typing import Any
|
|
|
9
9
|
import pytest
|
|
10
10
|
from fastapi import Depends, FastAPI
|
|
11
11
|
from httpx import ASGITransport, AsyncClient
|
|
12
|
-
from sqlalchemy import select
|
|
12
|
+
from sqlalchemy import inspect, select
|
|
13
13
|
from sqlalchemy.ext.asyncio import (
|
|
14
14
|
AsyncSession,
|
|
15
15
|
async_sessionmaker,
|
|
@@ -1507,6 +1507,68 @@ class TestCurrentUserResolution:
|
|
|
1507
1507
|
finally:
|
|
1508
1508
|
await db.disconnect()
|
|
1509
1509
|
|
|
1510
|
+
async def test_current_user_attached_to_request_session(self) -> None:
|
|
1511
|
+
"""The authenticated user is attached to the request-scoped session.
|
|
1512
|
+
|
|
1513
|
+
Regression for ``InvalidRequestError: Instance is not persistent
|
|
1514
|
+
within this Session``: loading the user on a private auth session
|
|
1515
|
+
yielded a *detached* instance, so mutating it on the request's
|
|
1516
|
+
repository session never persisted (and ``refresh`` raised). The
|
|
1517
|
+
dependency now shares ``db.session_dependency`` with the route, so
|
|
1518
|
+
the user is live and a mutation commits.
|
|
1519
|
+
"""
|
|
1520
|
+
db, service = await _db_service()
|
|
1521
|
+
try:
|
|
1522
|
+
async with db.get_session_context() as s:
|
|
1523
|
+
user, _ = await service.signup(
|
|
1524
|
+
s,
|
|
1525
|
+
email="attached@a.com",
|
|
1526
|
+
password="strong-pass-12-chars",
|
|
1527
|
+
)
|
|
1528
|
+
user.is_active = True
|
|
1529
|
+
await s.commit()
|
|
1530
|
+
await s.refresh(user)
|
|
1531
|
+
user_id = user.id
|
|
1532
|
+
access, _ = service.issue_jwt_pair(user)
|
|
1533
|
+
|
|
1534
|
+
get_current_user = service.current_user_dependency()
|
|
1535
|
+
app = FastAPI()
|
|
1536
|
+
|
|
1537
|
+
@app.post("/deactivate")
|
|
1538
|
+
async def deactivate(
|
|
1539
|
+
current: Any = Depends(get_current_user),
|
|
1540
|
+
session: AsyncSession = Depends(db.session_dependency),
|
|
1541
|
+
) -> dict[str, bool]:
|
|
1542
|
+
# The user is attached to this very request session: its
|
|
1543
|
+
# underlying sync Session is the dependency's shared one.
|
|
1544
|
+
same_session = inspect(current).session is session.sync_session
|
|
1545
|
+
current.is_active = False
|
|
1546
|
+
await session.commit()
|
|
1547
|
+
await session.refresh(current) # would raise if detached
|
|
1548
|
+
return {"same_session": same_session}
|
|
1549
|
+
|
|
1550
|
+
async with AsyncClient(
|
|
1551
|
+
transport=ASGITransport(app=app), base_url="http://t"
|
|
1552
|
+
) as client:
|
|
1553
|
+
resp = await client.post(
|
|
1554
|
+
"/deactivate", headers={"Authorization": f"Bearer {access}"}
|
|
1555
|
+
)
|
|
1556
|
+
assert resp.status_code == 200
|
|
1557
|
+
assert resp.json() == {"same_session": True}
|
|
1558
|
+
|
|
1559
|
+
# The mutation actually hit the database.
|
|
1560
|
+
async with db.get_session_context() as verify:
|
|
1561
|
+
reloaded = await service.get_user(user_id, verify)
|
|
1562
|
+
assert reloaded.is_active is False
|
|
1563
|
+
finally:
|
|
1564
|
+
await db.disconnect()
|
|
1565
|
+
|
|
1566
|
+
async def test_current_user_without_db_raises(self) -> None:
|
|
1567
|
+
"""``current_user_dependency`` needs ``db=`` to share its session."""
|
|
1568
|
+
service = _service() # built without db=
|
|
1569
|
+
with pytest.raises(RuntimeError):
|
|
1570
|
+
service.current_user_dependency()
|
|
1571
|
+
|
|
1510
1572
|
async def test_current_user_dependency_soft_returns_none(self) -> None:
|
|
1511
1573
|
db, service = await _db_service()
|
|
1512
1574
|
try:
|
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
from datetime import UTC, datetime
|
|
4
4
|
|
|
5
5
|
import pytest
|
|
6
|
-
from sqlalchemy import Integer, String
|
|
6
|
+
from sqlalchemy import Integer, String, inspect
|
|
7
7
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
8
8
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
9
9
|
|
|
10
10
|
from tempest_fastapi_sdk import (
|
|
11
|
+
AsyncDatabaseManager,
|
|
11
12
|
BaseModel,
|
|
12
13
|
BaseRepository,
|
|
13
14
|
ConflictException,
|
|
@@ -235,6 +236,36 @@ class TestResolve:
|
|
|
235
236
|
with pytest.raises(ProductNotFoundError):
|
|
236
237
|
await repo.resolve(uuid4())
|
|
237
238
|
|
|
239
|
+
async def test_reattaches_detached_instance(self, db: AsyncDatabaseManager) -> None:
|
|
240
|
+
"""A detached instance is merged into the repository's session.
|
|
241
|
+
|
|
242
|
+
Reproduces the production footgun: an instance loaded on one
|
|
243
|
+
session (then closed → detached) is handed to a repository bound
|
|
244
|
+
to a *different* session. ``resolve`` must re-attach it so a
|
|
245
|
+
subsequent ``update`` commits instead of raising
|
|
246
|
+
``InvalidRequestError: Instance is not persistent``.
|
|
247
|
+
"""
|
|
248
|
+
async with db.get_session_context() as first:
|
|
249
|
+
product = Product(name="apple", category="fruit")
|
|
250
|
+
first.add(product)
|
|
251
|
+
await first.commit()
|
|
252
|
+
# ``first`` is closed here → ``product`` is detached.
|
|
253
|
+
assert inspect(product).detached is True
|
|
254
|
+
|
|
255
|
+
async with db.get_session_context() as second:
|
|
256
|
+
repo = ProductRepository(second)
|
|
257
|
+
resolved = await repo.resolve(product)
|
|
258
|
+
|
|
259
|
+
assert inspect(resolved).detached is False
|
|
260
|
+
resolved.category = "pomes"
|
|
261
|
+
updated = await repo.update(resolved)
|
|
262
|
+
assert updated.category == "pomes"
|
|
263
|
+
|
|
264
|
+
async with db.get_session_context() as verify:
|
|
265
|
+
reloaded = await verify.get(Product, product.id)
|
|
266
|
+
assert reloaded is not None
|
|
267
|
+
assert reloaded.category == "pomes"
|
|
268
|
+
|
|
238
269
|
|
|
239
270
|
class TestGetOrNone:
|
|
240
271
|
async def test_returns_none_when_absent(self, repo: ProductRepository) -> None:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
version = 1
|
|
2
|
-
revision =
|
|
2
|
+
revision = 2
|
|
3
3
|
requires-python = ">=3.11"
|
|
4
4
|
resolution-markers = [
|
|
5
5
|
"python_full_version >= '3.15'",
|
|
@@ -2822,7 +2822,7 @@ wheels = [
|
|
|
2822
2822
|
|
|
2823
2823
|
[[package]]
|
|
2824
2824
|
name = "tempest-fastapi-sdk"
|
|
2825
|
-
version = "0.
|
|
2825
|
+
version = "0.63.0"
|
|
2826
2826
|
source = { editable = "." }
|
|
2827
2827
|
dependencies = [
|
|
2828
2828
|
{ name = "alembic" },
|
|
File without changes
|
|
File without changes
|
{tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/.github/workflows/release-pypi.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/api.en.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/domain.en.md
RENAMED
|
File without changes
|
{tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/domain.md
RENAMED
|
File without changes
|
{tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/flows.en.md
RENAMED
|
File without changes
|
{tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/flows.md
RENAMED
|
File without changes
|
{tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/index.en.md
RENAMED
|
File without changes
|
{tempest_fastapi_sdk-0.62.0 → tempest_fastapi_sdk-0.63.0}/docs/learning/marketplace/index.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|