fastapi-rtk 2.1.1__tar.gz → 2.1.2__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.
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/PKG-INFO +1 -1
- fastapi_rtk-2.1.2/fastapi_rtk/_version.py +1 -0
- fastapi_rtk-2.1.2/fastapi_rtk/cli/decorators.py +80 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/conftest.py +3 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/cli/commands/test_db.py +1 -3
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/cli/commands/test_export.py +9 -4
- fastapi_rtk-2.1.2/tests/unit/cli/conftest.py +30 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/cli/test_decorators.py +41 -24
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/test_fastapi_react_toolkit.py +32 -7
- fastapi_rtk-2.1.1/fastapi_rtk/_version.py +0 -1
- fastapi_rtk-2.1.1/fastapi_rtk/cli/decorators.py +0 -87
- fastapi_rtk-2.1.1/tests/unit/cli/conftest.py +0 -15
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/.gitignore +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/LICENSE +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/README.md +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/api/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/api/base_api.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_add_mixin.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_bulk_mixin.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_columns.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_delete_mixin.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_download_mixin.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_edit_mixin.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_file_mixin.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_info_mixin.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_list_mixin.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_params.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_show_mixin.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_upload_mixin.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/apis/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/apis/info.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/apis/license.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/auth.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/hashers/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/hashers/pbkdf2.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/hashers/scrypt.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/ldap.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/password_helpers/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/password_helpers/fab.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/strategies/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/strategies/config.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/strategies/db.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/strategies/jwt.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/column.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/db.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/exceptions.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/filters.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/interface.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/model.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/session.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/column.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/db.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/exceptions.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/_decorators_mixin.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/_lifecycle_mixin.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/_logger.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/_processing_mixin.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/audit.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/types.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/filters.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/geometry_converter.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/filters.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/interface.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/model.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/session.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/bases/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/bases/db.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/bases/file_manager.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/bases/filter.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/bases/interface.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/bases/model.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/bases/session.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/cli.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/_security_crypto.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi/README +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi/alembic.ini.mako +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi/env.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi/script.py.mako +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/README +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/alembic.ini.mako +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/env.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/script.py.mako +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/export.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/security.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/translate.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/const.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/types.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/utils.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/config.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/const.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/db.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/decorators.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/dependencies.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/exceptions.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/fastapi_react_toolkit.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/file_managers/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/file_managers/file_manager.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/file_managers/image_manager.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/file_managers/s3_file_manager.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/file_managers/s3_image_manager.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/filters.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/globals.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/babel/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/babel/cli.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/babel/config.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/babel.cfg +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/lazy_text.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/messages.pot +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.mo +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.po +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.mo +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.po +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/manager.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/middlewares.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/mixins.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/models.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/py.typed +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/registry.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/routers.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/schemas.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/security/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/apis.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/models.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_association_mixin.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_builtin_role_mixin.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_cleanup_mixin.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_exception_filters.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_export.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_import.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_role_mixin.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_user_mixin.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/setting.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/types.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/async_task_runner.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/class_factory.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/csv_json_converter.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/deep_merge.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/extender_mixin.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/flask_appbuilder_utils.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/formatter.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/hooks.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/lazy.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/merge_schema.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/multiple_async_contexts.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/pydantic.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/run_utils.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/self_dependencies.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/smartdefaultdict.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/sqla.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/timezone.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/update_signature.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/use_default_when_none.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/version.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/pyproject.toml +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/docker-compose.gis.yml +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/integration/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/integration/api/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/integration/api/test_model_rest_api.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/integration/apis/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/integration/apis/test_info_contract.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/integration/auth/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/integration/auth/test_auth_flow.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/integration/auth/test_oauth.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/integration/conftest.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/integration/file_managers/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/integration/file_managers/test_file_routes.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/integration/security/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/integration/security/sqla/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/integration/security/sqla/test_security_manager.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/integration/test_app_smoke.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/api/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/api/conftest.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/api/model_rest_api/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/api/model_rest_api/test_columns.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/api/model_rest_api/test_file_mixin.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/api/model_rest_api/test_init.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/api/test_base_api.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/apis/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/apis/test_info.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/apis/test_license.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/auth/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/auth/hashers/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/auth/hashers/test_pbkdf2.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/auth/hashers/test_scrypt.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/auth/password_helpers/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/auth/password_helpers/test_fab.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/auth/strategies/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/auth/strategies/test_config.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/auth/strategies/test_db.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/auth/strategies/test_jwt.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/auth/test_auth.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/backends/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/test_column.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/test_db.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/test_exceptions.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/test_filters.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/test_interface.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/test_model.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/test_session.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/conftest.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_audit.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_audit_types.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_column.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_db.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_filters.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_geoalchemy2.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_interface.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_model.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_session.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/bases/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/bases/test_db.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/bases/test_file_manager.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/bases/test_filter.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/bases/test_interface.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/bases/test_model.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/bases/test_session.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/cli/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/cli/commands/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/cli/commands/conftest.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/cli/commands/test_security.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/cli/commands/test_security_crypto.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/cli/commands/test_translate.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/cli/test_cli.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/cli/test_types.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/cli/test_utils.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/file_managers/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/file_managers/conftest.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/file_managers/test_file_manager.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/file_managers/test_image_manager.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/file_managers/test_s3_file_manager.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/file_managers/test_s3_image_manager.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/lang/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/lang/test_babel_cli.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/lang/test_babel_config.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/lang/test_lazy_text.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/security/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/security/sqla/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/security/sqla/conftest.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/security/sqla/test_apis.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/security/sqla/test_models.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/security/sqla/test_security_manager.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/test_config.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/test_const.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/test_db.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/test_decorators.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/test_dependencies.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/test_exceptions.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/test_filters.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/test_globals.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/test_manager.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/test_middlewares.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/test_mixins.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/test_models.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/test_registry.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/test_routers.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/test_schemas.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/test_setting.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/test_types.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/test_version.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/utils/__init__.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/utils/test_async_task_runner.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/utils/test_class_factory.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/utils/test_csv_json_converter.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/utils/test_deep_merge.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/utils/test_extender_mixin.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/utils/test_flask_appbuilder_utils.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/utils/test_formatter.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/utils/test_hooks.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/utils/test_lazy.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/utils/test_merge_schema.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/utils/test_multiple_async_contexts.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/utils/test_pydantic.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/utils/test_run_utils.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/utils/test_self_dependencies.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/utils/test_smartdefaultdict.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/utils/test_sqla.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/utils/test_timezone.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/utils/test_update_signature.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/tests/unit/utils/test_use_default_when_none.py +0 -0
- {fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastapi-rtk
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.2
|
|
4
4
|
Summary: A package that provides a set of tools to build a FastAPI application with a Class-Based CRUD API.
|
|
5
5
|
Project-URL: Homepage, https://codeberg.org/datatactics/fastapi-rtk
|
|
6
6
|
Project-URL: Issues, https://codeberg.org/datatactics/fastapi-rtk/issues
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.1.2"
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
from functools import wraps
|
|
3
|
+
|
|
4
|
+
import typer
|
|
5
|
+
from fastapi_cli.discover import get_import_data
|
|
6
|
+
from fastapi_cli.exceptions import FastAPICLIException
|
|
7
|
+
|
|
8
|
+
from ..db import db
|
|
9
|
+
from ..globals import g
|
|
10
|
+
from .const import logger
|
|
11
|
+
from .utils import run_in_current_event_loop
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def ensure_app_loaded(f):
|
|
15
|
+
"""Ensure a FastAPI app is loaded before running `f`.
|
|
16
|
+
|
|
17
|
+
Only commands that read models or config (not the database) need this.
|
|
18
|
+
"""
|
|
19
|
+
return _check_existing_app(f)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def ensure_fastapi_rtk_tables_exist(f):
|
|
23
|
+
"""Ensure the fastapi-rtk tables exist before running `f`.
|
|
24
|
+
|
|
25
|
+
Implies :func:`ensure_app_loaded`. Use on commands that touch the database.
|
|
26
|
+
|
|
27
|
+
Table-init only runs in CLI mode; an in-process caller (e.g. the lifespan)
|
|
28
|
+
already created the tables on the running loop, and re-running it here on a
|
|
29
|
+
worker-thread loop would crash async drivers (cross-loop connection reuse).
|
|
30
|
+
|
|
31
|
+
For the CLI path, init and body share one loop via
|
|
32
|
+
:func:`run_in_current_event_loop`: an `async def` command (a
|
|
33
|
+
:func:`make_sync` wrapper with `f.__wrapped__`) awaits init, body, and
|
|
34
|
+
`db.close()` in one call; a sync command inits on its own loop then runs.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
body = getattr(f, "__wrapped__", None)
|
|
38
|
+
|
|
39
|
+
@wraps(f)
|
|
40
|
+
def wrapper(*args, **kwargs):
|
|
41
|
+
if not g.is_cli:
|
|
42
|
+
return f(*args, **kwargs)
|
|
43
|
+
|
|
44
|
+
if body is not None and inspect.iscoroutinefunction(body):
|
|
45
|
+
|
|
46
|
+
async def run():
|
|
47
|
+
await db.init_fastapi_rtk_tables()
|
|
48
|
+
try:
|
|
49
|
+
return await body(*args, **kwargs)
|
|
50
|
+
finally:
|
|
51
|
+
await db.close()
|
|
52
|
+
|
|
53
|
+
return run_in_current_event_loop(run())
|
|
54
|
+
|
|
55
|
+
run_in_current_event_loop(db.init_fastapi_rtk_tables())
|
|
56
|
+
return f(*args, **kwargs)
|
|
57
|
+
|
|
58
|
+
return ensure_app_loaded(wrapper)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _check_existing_app(f, *, silent=False):
|
|
62
|
+
@wraps(f)
|
|
63
|
+
def wrapper(*args, **kwargs):
|
|
64
|
+
# No app loaded -> CLI invocation: flag cli (before import, so the
|
|
65
|
+
# toolkit skips the lifespan) and import from path. Else reuse it.
|
|
66
|
+
if g.current_app is None:
|
|
67
|
+
g.is_cli = True
|
|
68
|
+
try:
|
|
69
|
+
get_import_data(path=g.path)
|
|
70
|
+
except FastAPICLIException as e:
|
|
71
|
+
if not silent:
|
|
72
|
+
logger.error(str(e))
|
|
73
|
+
raise typer.Exit(code=1) from None
|
|
74
|
+
return f(*args, **kwargs)
|
|
75
|
+
|
|
76
|
+
return wrapper
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def check_existing_app_silent(f):
|
|
80
|
+
return _check_existing_app(f, silent=True)
|
|
@@ -130,6 +130,7 @@ def make_toolkit_app(tmp_path, config_setter):
|
|
|
130
130
|
extra_apis: optional list of API classes to register via add_api.
|
|
131
131
|
extra_lifespans: optional list of async context managers.
|
|
132
132
|
config_overrides: optional dict of additional config values.
|
|
133
|
+
upgrade_db: run the alembic upgrade step in the lifespan.
|
|
133
134
|
|
|
134
135
|
Returns:
|
|
135
136
|
FastAPI app instance with toolkit initialized.
|
|
@@ -144,6 +145,7 @@ def make_toolkit_app(tmp_path, config_setter):
|
|
|
144
145
|
extra_apis: Iterable[Any] | None = None,
|
|
145
146
|
extra_lifespans: Iterable[Any] | None = None,
|
|
146
147
|
config_overrides: dict | None = None,
|
|
148
|
+
upgrade_db: bool = False,
|
|
147
149
|
):
|
|
148
150
|
db_path = tmp_path / "test.db"
|
|
149
151
|
config_setter("SQLALCHEMY_DATABASE_URI", f"sqlite+aiosqlite:///{db_path}")
|
|
@@ -187,6 +189,7 @@ def make_toolkit_app(tmp_path, config_setter):
|
|
|
187
189
|
|
|
188
190
|
toolkit = FastAPIReactToolkit(
|
|
189
191
|
create_tables=False,
|
|
192
|
+
upgrade_db=upgrade_db,
|
|
190
193
|
exclude_apis=["LicenseApi"],
|
|
191
194
|
lifespans=list(extra_lifespans or []),
|
|
192
195
|
auth={"secret_key": "tier-integration-secret-32-bytes!!"},
|
|
@@ -219,9 +219,7 @@ class TestAppCheckPartition:
|
|
|
219
219
|
neutralize_app_check.get_import_data.assert_called_once()
|
|
220
220
|
neutralize_app_check.run_in_current_event_loop.assert_called_once()
|
|
221
221
|
|
|
222
|
-
def test_migrate_checks_once_via_revision(
|
|
223
|
-
self, monkeypatch, neutralize_app_check
|
|
224
|
-
):
|
|
222
|
+
def test_migrate_checks_once_via_revision(self, monkeypatch, neutralize_app_check):
|
|
225
223
|
from fastapi_rtk.cli.commands.db import migrate
|
|
226
224
|
|
|
227
225
|
self._patch_alembic(monkeypatch, "revision")
|
|
@@ -29,17 +29,22 @@ class TestAppCheckPartition:
|
|
|
29
29
|
neutralize_app_check.get_import_data.assert_called_once()
|
|
30
30
|
neutralize_app_check.run_in_current_event_loop.assert_not_called()
|
|
31
31
|
|
|
32
|
-
def test_api_docs_is_import_only(
|
|
33
|
-
self, tmp_path, monkeypatch, global_setter, neutralize_app_check
|
|
34
|
-
):
|
|
32
|
+
def test_api_docs_is_import_only(self, tmp_path, monkeypatch, neutralize_app_check):
|
|
35
33
|
from unittest.mock import MagicMock
|
|
36
34
|
|
|
37
35
|
from fastapi_rtk.cli.commands import export as ex_mod
|
|
36
|
+
from fastapi_rtk.globals import g
|
|
38
37
|
|
|
39
38
|
app_mock = MagicMock()
|
|
40
39
|
app_mock.apis = []
|
|
41
40
|
app_mock.app.openapi.return_value = {"paths": {}, "components": {}}
|
|
42
|
-
|
|
41
|
+
|
|
42
|
+
# No app loaded yet -> CLI (from-path) branch: importing the app is what
|
|
43
|
+
# populates `g.current_app`, so the mock mirrors that side effect.
|
|
44
|
+
def _load(*args, **kwargs):
|
|
45
|
+
g.current_app = app_mock
|
|
46
|
+
|
|
47
|
+
neutralize_app_check.get_import_data.side_effect = _load
|
|
43
48
|
|
|
44
49
|
ex_mod.api_docs(filename=str(tmp_path / "out.md"))
|
|
45
50
|
neutralize_app_check.get_import_data.assert_called_once()
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Shared fixtures for tier 14 cli/ tests.
|
|
2
|
+
|
|
3
|
+
Commands decorated with `@ensure_app_loaded` / `@ensure_fastapi_rtk_tables_exist`
|
|
4
|
+
discriminate CLI from in-process by `g.current_app`: when it is unset they import
|
|
5
|
+
the app from path and flag `g.is_cli = True`. Both flags leak into later tests,
|
|
6
|
+
so isolate them. `current_app` is cleared *before* each test so the CLI
|
|
7
|
+
(from-path) branch is exercised, and both are restored afterwards.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import pytest
|
|
11
|
+
|
|
12
|
+
from fastapi_rtk.globals import g
|
|
13
|
+
|
|
14
|
+
_MISSING = object()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@pytest.fixture(autouse=True)
|
|
18
|
+
def _reset_cli_globals():
|
|
19
|
+
saved_boot = g._bootstrap_values.pop("current_app", _MISSING)
|
|
20
|
+
saved_var = g._vars.pop("current_app", _MISSING)
|
|
21
|
+
yield
|
|
22
|
+
g.is_cli = False
|
|
23
|
+
if saved_boot is _MISSING:
|
|
24
|
+
g._bootstrap_values.pop("current_app", None)
|
|
25
|
+
else:
|
|
26
|
+
g._bootstrap_values["current_app"] = saved_boot
|
|
27
|
+
if saved_var is _MISSING:
|
|
28
|
+
g._vars.pop("current_app", None)
|
|
29
|
+
else:
|
|
30
|
+
g._vars["current_app"] = saved_var
|
|
@@ -8,7 +8,6 @@ import typer
|
|
|
8
8
|
|
|
9
9
|
from fastapi_rtk.cli.decorators import (
|
|
10
10
|
_check_existing_app,
|
|
11
|
-
_set_cli_mode,
|
|
12
11
|
check_existing_app_silent,
|
|
13
12
|
ensure_app_loaded,
|
|
14
13
|
ensure_fastapi_rtk_tables_exist,
|
|
@@ -16,29 +15,6 @@ from fastapi_rtk.cli.decorators import (
|
|
|
16
15
|
from fastapi_rtk.cli.utils import make_sync
|
|
17
16
|
|
|
18
17
|
|
|
19
|
-
class TestSetCliMode:
|
|
20
|
-
def test_sets_cli_flag(self, global_setter):
|
|
21
|
-
global_setter("is_cli", False)
|
|
22
|
-
|
|
23
|
-
from fastapi_rtk.globals import g
|
|
24
|
-
|
|
25
|
-
captured = []
|
|
26
|
-
|
|
27
|
-
@_set_cli_mode
|
|
28
|
-
def fn():
|
|
29
|
-
captured.append(g.is_cli)
|
|
30
|
-
return "ok"
|
|
31
|
-
|
|
32
|
-
try:
|
|
33
|
-
result = fn()
|
|
34
|
-
assert result == "ok"
|
|
35
|
-
assert captured == [True]
|
|
36
|
-
finally:
|
|
37
|
-
# Restore the default - the decorator writes to g._vars which
|
|
38
|
-
# bypasses the global_setter fixture's restore semantics.
|
|
39
|
-
g.is_cli = False
|
|
40
|
-
|
|
41
|
-
|
|
42
18
|
class TestCheckExistingApp:
|
|
43
19
|
def test_runs_when_app_exists(self):
|
|
44
20
|
with patch("fastapi_rtk.cli.decorators.get_import_data"):
|
|
@@ -125,6 +101,47 @@ class TestEnsureAppLoaded:
|
|
|
125
101
|
g.is_cli = False
|
|
126
102
|
|
|
127
103
|
|
|
104
|
+
class TestInProcessReusesLoadedApp:
|
|
105
|
+
"""When `g.current_app` is set (in-process, e.g. the app lifespan) the
|
|
106
|
+
decorators reuse the loaded app: no import, no CLI flag, no table-init.
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
def test_check_existing_app_skips_import_when_app_loaded(self):
|
|
110
|
+
from fastapi_rtk.globals import g
|
|
111
|
+
|
|
112
|
+
g.current_app = object()
|
|
113
|
+
with patch("fastapi_rtk.cli.decorators.get_import_data") as mock_import:
|
|
114
|
+
|
|
115
|
+
@_check_existing_app
|
|
116
|
+
def fn():
|
|
117
|
+
return "result"
|
|
118
|
+
|
|
119
|
+
assert fn() == "result"
|
|
120
|
+
|
|
121
|
+
mock_import.assert_not_called()
|
|
122
|
+
assert g.is_cli is False
|
|
123
|
+
|
|
124
|
+
def test_tables_exist_skips_init_when_app_loaded(self):
|
|
125
|
+
from fastapi_rtk.globals import g
|
|
126
|
+
|
|
127
|
+
g.current_app = object()
|
|
128
|
+
with (
|
|
129
|
+
patch("fastapi_rtk.cli.decorators.get_import_data") as mock_import,
|
|
130
|
+
patch("fastapi_rtk.cli.decorators.run_in_current_event_loop") as mock_run,
|
|
131
|
+
):
|
|
132
|
+
|
|
133
|
+
@ensure_fastapi_rtk_tables_exist
|
|
134
|
+
def fn():
|
|
135
|
+
return "done"
|
|
136
|
+
|
|
137
|
+
assert fn() == "done"
|
|
138
|
+
|
|
139
|
+
# In-process: no app import and no table-init (the foreign-loop touch).
|
|
140
|
+
mock_import.assert_not_called()
|
|
141
|
+
mock_run.assert_not_called()
|
|
142
|
+
assert g.is_cli is False
|
|
143
|
+
|
|
144
|
+
|
|
128
145
|
class TestEnsureFastapiRtkTablesExist:
|
|
129
146
|
def test_initializes_tables(self):
|
|
130
147
|
with (
|
|
@@ -133,7 +133,9 @@ class TestInitializeWithFeatures:
|
|
|
133
133
|
assert "SecWebPatchDocsMiddleware" in names
|
|
134
134
|
assert "SecWebPatchReDocMiddleware" in names
|
|
135
135
|
|
|
136
|
-
def test_profiler_enabled_adds_middleware(
|
|
136
|
+
def test_profiler_enabled_adds_middleware(
|
|
137
|
+
self, config_setter, tmp_path, monkeypatch
|
|
138
|
+
):
|
|
137
139
|
import sys
|
|
138
140
|
from unittest.mock import MagicMock
|
|
139
141
|
|
|
@@ -239,16 +241,12 @@ class TestTemplateFolderRoute:
|
|
|
239
241
|
# Without index.html we hit the TemplateNotFound -> 404
|
|
240
242
|
assert r.status_code == 404
|
|
241
243
|
|
|
242
|
-
def test_template_folder_index_renders_when_present(
|
|
243
|
-
self, tmp_path, config_setter
|
|
244
|
-
):
|
|
244
|
+
def test_template_folder_index_renders_when_present(self, tmp_path, config_setter):
|
|
245
245
|
from starlette.testclient import TestClient
|
|
246
246
|
|
|
247
247
|
tmpl_dir = tmp_path / "tmpl"
|
|
248
248
|
tmpl_dir.mkdir()
|
|
249
|
-
(tmpl_dir / "index.html").write_text(
|
|
250
|
-
"<html>{{ app_name }}</html>"
|
|
251
|
-
)
|
|
249
|
+
(tmpl_dir / "index.html").write_text("<html>{{ app_name }}</html>")
|
|
252
250
|
config_setter("TEMPLATE_FOLDER", str(tmpl_dir))
|
|
253
251
|
config_setter("APP_NAME", "MyApp")
|
|
254
252
|
|
|
@@ -616,6 +614,33 @@ class TestToolkitLifespanSmoke:
|
|
|
616
614
|
assert app is not None
|
|
617
615
|
|
|
618
616
|
|
|
617
|
+
class TestToolkitLifespanUpgradeDb:
|
|
618
|
+
"""Regression: `upgrade_db=True` must not crash on async drivers.
|
|
619
|
+
|
|
620
|
+
The lifespan creates the fastapi-rtk tables on the running loop and then
|
|
621
|
+
runs the alembic upgrade. Routing that upgrade through the CLI
|
|
622
|
+
`ensure_fastapi_rtk_tables_exist` decorator re-touches the shared async
|
|
623
|
+
engine on a fresh event loop in a worker thread, which asyncpg / aiosqlite
|
|
624
|
+
reject with "got Future ... attached to a different loop". The upgrade must
|
|
625
|
+
run without re-entering the async table-init.
|
|
626
|
+
"""
|
|
627
|
+
|
|
628
|
+
@pytest.mark.asyncio
|
|
629
|
+
async def test_upgrade_db_lifespan_no_cross_loop(self, make_toolkit_app):
|
|
630
|
+
from unittest.mock import MagicMock
|
|
631
|
+
|
|
632
|
+
from fastapi_rtk.cli.commands import db as db_mod
|
|
633
|
+
|
|
634
|
+
with patch.object(db_mod.alembic.command, "upgrade", MagicMock()) as upgrade:
|
|
635
|
+
app = make_toolkit_app(upgrade_db=True)
|
|
636
|
+
async with app.router.lifespan_context(app):
|
|
637
|
+
pass
|
|
638
|
+
|
|
639
|
+
# Alembic ran (on its own sync engine), and the lifespan completed
|
|
640
|
+
# without the cross-loop RuntimeError.
|
|
641
|
+
upgrade.assert_called_once()
|
|
642
|
+
|
|
643
|
+
|
|
619
644
|
class TestToolkitDebugLogLevel:
|
|
620
645
|
"""Line 634: DEBUG=True sets logger level to DEBUG."""
|
|
621
646
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.1.1"
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import inspect
|
|
2
|
-
from functools import wraps
|
|
3
|
-
|
|
4
|
-
import typer
|
|
5
|
-
from fastapi_cli.discover import get_import_data
|
|
6
|
-
from fastapi_cli.exceptions import FastAPICLIException
|
|
7
|
-
|
|
8
|
-
from ..db import db
|
|
9
|
-
from ..globals import g
|
|
10
|
-
from .const import logger
|
|
11
|
-
from .utils import run_in_current_event_loop
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def ensure_app_loaded(f):
|
|
15
|
-
"""Load the app for the CLI: set `g.is_cli`, then import the app.
|
|
16
|
-
|
|
17
|
-
Importing the app is what registers the models and populates `g.config`,
|
|
18
|
-
so any command that reads models or config (but does not touch the
|
|
19
|
-
database) only needs this.
|
|
20
|
-
"""
|
|
21
|
-
return _set_cli_mode(_check_existing_app(f))
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def ensure_fastapi_rtk_tables_exist(f):
|
|
25
|
-
"""Ensure the fastapi-rtk tables exist before running `f`.
|
|
26
|
-
|
|
27
|
-
Creating the tables reads config and reflects the registered models, so it
|
|
28
|
-
implies :func:`ensure_app_loaded`. Use this on commands that touch the
|
|
29
|
-
database; use :func:`ensure_app_loaded` on the rest.
|
|
30
|
-
|
|
31
|
-
The table-creation and the command body must run on the **same** event
|
|
32
|
-
loop: the async engine pools a connection bound to whichever loop opened
|
|
33
|
-
it, and asyncpg / aiosqlite raise when that connection is reused from a
|
|
34
|
-
second loop. `f` is normally a :func:`fastapi_rtk.cli.utils.make_sync`
|
|
35
|
-
wrapper whose original coroutine is exposed as ``f.__wrapped__``; when so,
|
|
36
|
-
the table init and the body are awaited inside one
|
|
37
|
-
:func:`run_in_current_event_loop` call and the engine is disposed before
|
|
38
|
-
that loop closes. A plain synchronous `f` cannot share the loop (it has no
|
|
39
|
-
coroutine), so the init runs on its own loop and `f` is called directly.
|
|
40
|
-
"""
|
|
41
|
-
|
|
42
|
-
body = getattr(f, "__wrapped__", None)
|
|
43
|
-
|
|
44
|
-
@wraps(f)
|
|
45
|
-
def wrapper(*args, **kwargs):
|
|
46
|
-
if body is not None and inspect.iscoroutinefunction(body):
|
|
47
|
-
|
|
48
|
-
async def run():
|
|
49
|
-
await db.init_fastapi_rtk_tables()
|
|
50
|
-
try:
|
|
51
|
-
return await body(*args, **kwargs)
|
|
52
|
-
finally:
|
|
53
|
-
await db.close()
|
|
54
|
-
|
|
55
|
-
return run_in_current_event_loop(run())
|
|
56
|
-
|
|
57
|
-
run_in_current_event_loop(db.init_fastapi_rtk_tables())
|
|
58
|
-
return f(*args, **kwargs)
|
|
59
|
-
|
|
60
|
-
return ensure_app_loaded(wrapper)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def _check_existing_app(f, *, silent=False):
|
|
64
|
-
@wraps(f)
|
|
65
|
-
def wrapper(*args, **kwargs):
|
|
66
|
-
try:
|
|
67
|
-
get_import_data(path=g.path)
|
|
68
|
-
except FastAPICLIException as e:
|
|
69
|
-
if not silent:
|
|
70
|
-
logger.error(str(e))
|
|
71
|
-
raise typer.Exit(code=1) from None
|
|
72
|
-
return f(*args, **kwargs)
|
|
73
|
-
|
|
74
|
-
return wrapper
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
def check_existing_app_silent(f):
|
|
78
|
-
return _check_existing_app(f, silent=True)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
def _set_cli_mode(f):
|
|
82
|
-
@wraps(f)
|
|
83
|
-
def wrapper(*args, **kwargs):
|
|
84
|
-
g.is_cli = True
|
|
85
|
-
return f(*args, **kwargs)
|
|
86
|
-
|
|
87
|
-
return wrapper
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"""Shared fixtures for tier 14 cli/ tests.
|
|
2
|
-
|
|
3
|
-
Commands decorated with `@ensure_app_loaded` / `@ensure_fastapi_rtk_tables_exist`
|
|
4
|
-
set `g.is_cli = True`. The flag leaks into later tests, so reset it after each.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import pytest
|
|
8
|
-
|
|
9
|
-
from fastapi_rtk.globals import g
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
@pytest.fixture(autouse=True)
|
|
13
|
-
def _reset_is_cli():
|
|
14
|
-
yield
|
|
15
|
-
g.is_cli = False
|
|
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
|
|
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
|
|
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
|
{fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/_logger.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/__init__.py
RENAMED
|
File without changes
|
{fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/filters.py
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
|
|
File without changes
|
{fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi/README
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi/env.py
RENAMED
|
File without changes
|
{fastapi_rtk-2.1.1 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi/script.py.mako
RENAMED
|
File without changes
|