fastapi-rtk 2.1.0__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.0 → fastapi_rtk-2.1.2}/PKG-INFO +1 -1
- fastapi_rtk-2.1.2/fastapi_rtk/_version.py +1 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/__init__.py +15 -2
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/export.py +5 -2
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/security.py +28 -1
- fastapi_rtk-2.1.2/fastapi_rtk/cli/decorators.py +80 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/fastapi_react_toolkit.py +1 -1
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/globals.py +8 -2
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/conftest.py +3 -0
- fastapi_rtk-2.1.2/tests/unit/cli/commands/conftest.py +48 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/cli/commands/test_db.py +51 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/cli/commands/test_export.py +39 -0
- fastapi_rtk-2.1.2/tests/unit/cli/conftest.py +30 -0
- fastapi_rtk-2.1.2/tests/unit/cli/test_decorators.py +240 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_fastapi_react_toolkit.py +32 -7
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_globals.py +20 -2
- fastapi_rtk-2.1.0/fastapi_rtk/_version.py +0 -1
- fastapi_rtk-2.1.0/fastapi_rtk/cli/decorators.py +0 -48
- fastapi_rtk-2.1.0/tests/unit/cli/conftest.py +0 -16
- fastapi_rtk-2.1.0/tests/unit/cli/test_decorators.py +0 -113
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/.gitignore +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/LICENSE +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/README.md +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/base_api.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_add_mixin.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_bulk_mixin.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_columns.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_delete_mixin.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_download_mixin.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_edit_mixin.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_file_mixin.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_info_mixin.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_list_mixin.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_params.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_show_mixin.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_upload_mixin.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/apis/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/apis/info.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/apis/license.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/auth.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/hashers/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/hashers/pbkdf2.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/hashers/scrypt.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/ldap.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/password_helpers/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/password_helpers/fab.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/strategies/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/strategies/config.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/strategies/db.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/strategies/jwt.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/column.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/db.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/exceptions.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/filters.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/interface.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/model.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/session.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/column.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/db.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/exceptions.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/_decorators_mixin.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/_lifecycle_mixin.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/_logger.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/_processing_mixin.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/audit.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/types.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/filters.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/geometry_converter.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/filters.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/interface.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/model.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/session.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/bases/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/bases/db.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/bases/file_manager.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/bases/filter.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/bases/interface.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/bases/model.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/bases/session.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/cli.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/_security_crypto.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi/README +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi/alembic.ini.mako +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi/env.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi/script.py.mako +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/README +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/alembic.ini.mako +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/env.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/script.py.mako +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/translate.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/const.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/types.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/utils.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/config.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/const.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/db.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/decorators.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/dependencies.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/exceptions.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/file_managers/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/file_managers/file_manager.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/file_managers/image_manager.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/file_managers/s3_file_manager.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/file_managers/s3_image_manager.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/filters.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/babel/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/babel/cli.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/babel/config.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/babel.cfg +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/lazy_text.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/messages.pot +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.mo +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.po +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.mo +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.po +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/manager.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/middlewares.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/mixins.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/models.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/py.typed +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/registry.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/routers.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/schemas.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/apis.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/models.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_association_mixin.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_builtin_role_mixin.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_cleanup_mixin.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_exception_filters.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_export.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_import.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_role_mixin.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_user_mixin.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/setting.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/types.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/async_task_runner.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/class_factory.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/csv_json_converter.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/deep_merge.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/extender_mixin.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/flask_appbuilder_utils.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/formatter.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/hooks.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/lazy.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/merge_schema.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/multiple_async_contexts.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/pydantic.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/run_utils.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/self_dependencies.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/smartdefaultdict.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/sqla.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/timezone.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/update_signature.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/use_default_when_none.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/version.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/pyproject.toml +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/docker-compose.gis.yml +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/api/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/api/test_model_rest_api.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/apis/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/apis/test_info_contract.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/auth/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/auth/test_auth_flow.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/auth/test_oauth.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/conftest.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/file_managers/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/file_managers/test_file_routes.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/security/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/security/sqla/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/security/sqla/test_security_manager.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/test_app_smoke.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/api/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/api/conftest.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/api/model_rest_api/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/api/model_rest_api/test_columns.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/api/model_rest_api/test_file_mixin.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/api/model_rest_api/test_init.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/api/test_base_api.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/apis/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/apis/test_info.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/apis/test_license.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/hashers/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/hashers/test_pbkdf2.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/hashers/test_scrypt.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/password_helpers/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/password_helpers/test_fab.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/strategies/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/strategies/test_config.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/strategies/test_db.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/strategies/test_jwt.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/test_auth.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/test_column.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/test_db.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/test_exceptions.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/test_filters.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/test_interface.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/test_model.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/test_session.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/conftest.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_audit.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_audit_types.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_column.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_db.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_filters.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_geoalchemy2.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_interface.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_model.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_session.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/bases/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/bases/test_db.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/bases/test_file_manager.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/bases/test_filter.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/bases/test_interface.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/bases/test_model.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/bases/test_session.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/cli/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/cli/commands/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/cli/commands/test_security.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/cli/commands/test_security_crypto.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/cli/commands/test_translate.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/cli/test_cli.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/cli/test_types.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/cli/test_utils.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/file_managers/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/file_managers/conftest.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/file_managers/test_file_manager.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/file_managers/test_image_manager.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/file_managers/test_s3_file_manager.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/file_managers/test_s3_image_manager.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/lang/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/lang/test_babel_cli.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/lang/test_babel_config.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/lang/test_lazy_text.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/security/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/security/sqla/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/security/sqla/conftest.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/security/sqla/test_apis.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/security/sqla/test_models.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/security/sqla/test_security_manager.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_config.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_const.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_db.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_decorators.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_dependencies.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_exceptions.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_filters.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_manager.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_middlewares.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_mixins.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_models.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_registry.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_routers.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_schemas.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_setting.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_types.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_version.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/__init__.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_async_task_runner.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_class_factory.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_csv_json_converter.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_deep_merge.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_extender_mixin.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_flask_appbuilder_utils.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_formatter.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_hooks.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_lazy.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_merge_schema.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_multiple_async_contexts.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_pydantic.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_run_utils.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_self_dependencies.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_smartdefaultdict.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_sqla.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_timezone.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_update_signature.py +0 -0
- {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_use_default_when_none.py +0 -0
- {fastapi_rtk-2.1.0 → 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"
|
|
@@ -7,7 +7,7 @@ import alembic.config
|
|
|
7
7
|
import typer
|
|
8
8
|
|
|
9
9
|
from ...cli import app
|
|
10
|
-
from ...decorators import ensure_fastapi_rtk_tables_exist
|
|
10
|
+
from ...decorators import ensure_app_loaded, ensure_fastapi_rtk_tables_exist
|
|
11
11
|
from .. import version_callback
|
|
12
12
|
|
|
13
13
|
|
|
@@ -28,7 +28,6 @@ app.add_typer(db_app, name="db")
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
@db_app.callback()
|
|
31
|
-
@ensure_fastapi_rtk_tables_exist
|
|
32
31
|
def callback(
|
|
33
32
|
version: Annotated[
|
|
34
33
|
Union[bool, None],
|
|
@@ -99,6 +98,7 @@ def init(
|
|
|
99
98
|
|
|
100
99
|
|
|
101
100
|
@db_app.command()
|
|
101
|
+
@ensure_fastapi_rtk_tables_exist
|
|
102
102
|
def revision(
|
|
103
103
|
directory: Annotated[
|
|
104
104
|
Union[str, None], typer.Option(help="Path to migration scripts directory.")
|
|
@@ -167,6 +167,8 @@ def revision(
|
|
|
167
167
|
|
|
168
168
|
|
|
169
169
|
@db_app.command()
|
|
170
|
+
# No decorator: this is an alias that delegates to `revision`, whose own
|
|
171
|
+
# decorator runs the app check once. Decorating here too would double it.
|
|
170
172
|
def migrate(
|
|
171
173
|
directory: Annotated[
|
|
172
174
|
Union[str, None], typer.Option(help="Path to migration scripts directory.")
|
|
@@ -224,6 +226,7 @@ def migrate(
|
|
|
224
226
|
|
|
225
227
|
|
|
226
228
|
@db_app.command()
|
|
229
|
+
@ensure_app_loaded
|
|
227
230
|
def edit(
|
|
228
231
|
directory: Annotated[
|
|
229
232
|
Union[str, None], typer.Option(help="Path to migration scripts directory.")
|
|
@@ -239,6 +242,7 @@ def edit(
|
|
|
239
242
|
|
|
240
243
|
|
|
241
244
|
@db_app.command()
|
|
245
|
+
@ensure_app_loaded
|
|
242
246
|
def merge(
|
|
243
247
|
directory: Annotated[
|
|
244
248
|
Union[str, None], typer.Option(help="Path to migration scripts directory.")
|
|
@@ -273,6 +277,7 @@ def merge(
|
|
|
273
277
|
|
|
274
278
|
|
|
275
279
|
@db_app.command()
|
|
280
|
+
@ensure_fastapi_rtk_tables_exist
|
|
276
281
|
def upgrade(
|
|
277
282
|
directory: Annotated[
|
|
278
283
|
Union[str, None], typer.Option(help="Path to migration scripts directory.")
|
|
@@ -300,6 +305,7 @@ def upgrade(
|
|
|
300
305
|
|
|
301
306
|
|
|
302
307
|
@db_app.command()
|
|
308
|
+
@ensure_fastapi_rtk_tables_exist
|
|
303
309
|
def downgrade(
|
|
304
310
|
directory: Annotated[
|
|
305
311
|
Union[str, None], typer.Option(help="Path to migration scripts directory.")
|
|
@@ -327,6 +333,7 @@ def downgrade(
|
|
|
327
333
|
|
|
328
334
|
|
|
329
335
|
@db_app.command()
|
|
336
|
+
@ensure_app_loaded
|
|
330
337
|
def show(
|
|
331
338
|
directory: Annotated[
|
|
332
339
|
Union[str, None], typer.Option(help="Path to migration scripts directory.")
|
|
@@ -340,6 +347,7 @@ def show(
|
|
|
340
347
|
|
|
341
348
|
|
|
342
349
|
@db_app.command()
|
|
350
|
+
@ensure_app_loaded
|
|
343
351
|
def history(
|
|
344
352
|
directory: Annotated[
|
|
345
353
|
Union[str, None], typer.Option(help="Path to migration scripts directory.")
|
|
@@ -369,6 +377,7 @@ def history(
|
|
|
369
377
|
|
|
370
378
|
|
|
371
379
|
@db_app.command()
|
|
380
|
+
@ensure_app_loaded
|
|
372
381
|
def heads(
|
|
373
382
|
directory: Annotated[
|
|
374
383
|
Union[str, None], typer.Option(help="Path to migration scripts directory.")
|
|
@@ -395,6 +404,7 @@ def heads(
|
|
|
395
404
|
|
|
396
405
|
|
|
397
406
|
@db_app.command()
|
|
407
|
+
@ensure_app_loaded
|
|
398
408
|
def branches(
|
|
399
409
|
directory: Annotated[
|
|
400
410
|
Union[str, None], typer.Option(help="Path to migration scripts directory.")
|
|
@@ -413,6 +423,7 @@ def branches(
|
|
|
413
423
|
|
|
414
424
|
|
|
415
425
|
@db_app.command()
|
|
426
|
+
@ensure_fastapi_rtk_tables_exist
|
|
416
427
|
def current(
|
|
417
428
|
directory: Annotated[
|
|
418
429
|
Union[str, None], typer.Option(help="Path to migration scripts directory.")
|
|
@@ -431,6 +442,7 @@ def current(
|
|
|
431
442
|
|
|
432
443
|
|
|
433
444
|
@db_app.command()
|
|
445
|
+
@ensure_fastapi_rtk_tables_exist
|
|
434
446
|
def stamp(
|
|
435
447
|
directory: Annotated[
|
|
436
448
|
Union[str, None], typer.Option(help="Path to migration scripts directory.")
|
|
@@ -462,6 +474,7 @@ def stamp(
|
|
|
462
474
|
|
|
463
475
|
|
|
464
476
|
@db_app.command()
|
|
477
|
+
@ensure_fastapi_rtk_tables_exist
|
|
465
478
|
def check(
|
|
466
479
|
directory: Annotated[
|
|
467
480
|
Union[str, None], typer.Option(help="Path to migration scripts directory.")
|
|
@@ -26,7 +26,7 @@ from ...globals import g
|
|
|
26
26
|
from ...setting import Setting
|
|
27
27
|
from ..cli import app
|
|
28
28
|
from ..const import logger
|
|
29
|
-
from ..decorators import ensure_fastapi_rtk_tables_exist
|
|
29
|
+
from ..decorators import ensure_app_loaded, ensure_fastapi_rtk_tables_exist
|
|
30
30
|
from ..types import (
|
|
31
31
|
APIDataDocs,
|
|
32
32
|
APIDocs,
|
|
@@ -50,7 +50,6 @@ table_documentation: collections.defaultdict[str, TableDocumentation] = (
|
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
@export_app.callback()
|
|
53
|
-
@ensure_fastapi_rtk_tables_exist
|
|
54
53
|
def callback(
|
|
55
54
|
version: typing.Annotated[
|
|
56
55
|
typing.Union[bool, None],
|
|
@@ -67,6 +66,7 @@ def callback(
|
|
|
67
66
|
|
|
68
67
|
|
|
69
68
|
@export_app.command()
|
|
69
|
+
@ensure_fastapi_rtk_tables_exist
|
|
70
70
|
@make_sync
|
|
71
71
|
async def api_schema(
|
|
72
72
|
apis: typing.Annotated[
|
|
@@ -131,6 +131,7 @@ async def api_schema(
|
|
|
131
131
|
|
|
132
132
|
|
|
133
133
|
@export_app.command()
|
|
134
|
+
@ensure_app_loaded
|
|
134
135
|
def api_docs(
|
|
135
136
|
apis: typing.Annotated[
|
|
136
137
|
str | None,
|
|
@@ -261,6 +262,7 @@ def api_docs(
|
|
|
261
262
|
|
|
262
263
|
|
|
263
264
|
@export_app.command()
|
|
265
|
+
@ensure_app_loaded
|
|
264
266
|
def db_docs(
|
|
265
267
|
tables: typing.Annotated[
|
|
266
268
|
str | None,
|
|
@@ -348,6 +350,7 @@ def db_docs(
|
|
|
348
350
|
|
|
349
351
|
|
|
350
352
|
@export_app.command()
|
|
353
|
+
@ensure_app_loaded
|
|
351
354
|
def licenses(
|
|
352
355
|
output_dir: typing.Annotated[
|
|
353
356
|
str | None,
|
|
@@ -17,7 +17,6 @@ app.add_typer(security_app, name="security")
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
@security_app.callback()
|
|
20
|
-
@ensure_fastapi_rtk_tables_exist
|
|
21
20
|
def callback(
|
|
22
21
|
version: Annotated[
|
|
23
22
|
Union[bool, None],
|
|
@@ -34,6 +33,7 @@ def callback(
|
|
|
34
33
|
|
|
35
34
|
|
|
36
35
|
@security_app.command()
|
|
36
|
+
@ensure_fastapi_rtk_tables_exist
|
|
37
37
|
@make_sync
|
|
38
38
|
async def export_users(
|
|
39
39
|
file_path: Annotated[
|
|
@@ -92,6 +92,7 @@ async def export_users(
|
|
|
92
92
|
|
|
93
93
|
|
|
94
94
|
@security_app.command()
|
|
95
|
+
@ensure_fastapi_rtk_tables_exist
|
|
95
96
|
@make_sync
|
|
96
97
|
async def import_users(
|
|
97
98
|
file_path: Annotated[
|
|
@@ -146,6 +147,7 @@ async def import_users(
|
|
|
146
147
|
|
|
147
148
|
|
|
148
149
|
@security_app.command()
|
|
150
|
+
@ensure_fastapi_rtk_tables_exist
|
|
149
151
|
@make_sync
|
|
150
152
|
async def list_users(
|
|
151
153
|
role: Annotated[
|
|
@@ -234,6 +236,7 @@ async def list_users(
|
|
|
234
236
|
|
|
235
237
|
|
|
236
238
|
@security_app.command()
|
|
239
|
+
@ensure_fastapi_rtk_tables_exist
|
|
237
240
|
@make_sync
|
|
238
241
|
async def show_user(
|
|
239
242
|
email_or_username: Annotated[
|
|
@@ -275,6 +278,7 @@ async def show_user(
|
|
|
275
278
|
|
|
276
279
|
|
|
277
280
|
@security_app.command()
|
|
281
|
+
@ensure_fastapi_rtk_tables_exist
|
|
278
282
|
@make_sync
|
|
279
283
|
async def create_admin(
|
|
280
284
|
username: Annotated[
|
|
@@ -328,6 +332,7 @@ async def create_admin(
|
|
|
328
332
|
|
|
329
333
|
|
|
330
334
|
@security_app.command()
|
|
335
|
+
@ensure_fastapi_rtk_tables_exist
|
|
331
336
|
@make_sync
|
|
332
337
|
async def create_user(
|
|
333
338
|
username: Annotated[str, typer.Option(..., help="The username of the user.")] = "",
|
|
@@ -402,6 +407,7 @@ async def create_user(
|
|
|
402
407
|
|
|
403
408
|
|
|
404
409
|
@security_app.command()
|
|
410
|
+
@ensure_fastapi_rtk_tables_exist
|
|
405
411
|
@make_sync
|
|
406
412
|
async def update_user(
|
|
407
413
|
email_or_username: Annotated[
|
|
@@ -461,6 +467,7 @@ async def update_user(
|
|
|
461
467
|
|
|
462
468
|
|
|
463
469
|
@security_app.command()
|
|
470
|
+
@ensure_fastapi_rtk_tables_exist
|
|
464
471
|
@make_sync
|
|
465
472
|
async def activate(
|
|
466
473
|
email_or_username: Annotated[
|
|
@@ -474,6 +481,7 @@ async def activate(
|
|
|
474
481
|
|
|
475
482
|
|
|
476
483
|
@security_app.command()
|
|
484
|
+
@ensure_fastapi_rtk_tables_exist
|
|
477
485
|
@make_sync
|
|
478
486
|
async def deactivate(
|
|
479
487
|
email_or_username: Annotated[
|
|
@@ -487,6 +495,7 @@ async def deactivate(
|
|
|
487
495
|
|
|
488
496
|
|
|
489
497
|
@security_app.command()
|
|
498
|
+
@ensure_fastapi_rtk_tables_exist
|
|
490
499
|
@make_sync
|
|
491
500
|
async def verify_user(
|
|
492
501
|
email_or_username: Annotated[
|
|
@@ -504,6 +513,7 @@ async def verify_user(
|
|
|
504
513
|
|
|
505
514
|
|
|
506
515
|
@security_app.command()
|
|
516
|
+
@ensure_fastapi_rtk_tables_exist
|
|
507
517
|
@make_sync
|
|
508
518
|
async def unverify_user(
|
|
509
519
|
email_or_username: Annotated[
|
|
@@ -521,6 +531,7 @@ async def unverify_user(
|
|
|
521
531
|
|
|
522
532
|
|
|
523
533
|
@security_app.command()
|
|
534
|
+
@ensure_fastapi_rtk_tables_exist
|
|
524
535
|
@make_sync
|
|
525
536
|
async def promote(
|
|
526
537
|
email_or_username: Annotated[
|
|
@@ -549,6 +560,7 @@ async def promote(
|
|
|
549
560
|
|
|
550
561
|
|
|
551
562
|
@security_app.command()
|
|
563
|
+
@ensure_fastapi_rtk_tables_exist
|
|
552
564
|
@make_sync
|
|
553
565
|
async def demote(
|
|
554
566
|
email_or_username: Annotated[
|
|
@@ -576,6 +588,7 @@ async def demote(
|
|
|
576
588
|
|
|
577
589
|
|
|
578
590
|
@security_app.command()
|
|
591
|
+
@ensure_fastapi_rtk_tables_exist
|
|
579
592
|
@make_sync
|
|
580
593
|
async def delete_user(
|
|
581
594
|
email_or_username: Annotated[
|
|
@@ -611,6 +624,7 @@ async def delete_user(
|
|
|
611
624
|
|
|
612
625
|
|
|
613
626
|
@security_app.command()
|
|
627
|
+
@ensure_fastapi_rtk_tables_exist
|
|
614
628
|
@make_sync
|
|
615
629
|
async def export_roles(
|
|
616
630
|
file_path: Annotated[
|
|
@@ -669,6 +683,7 @@ async def export_roles(
|
|
|
669
683
|
|
|
670
684
|
|
|
671
685
|
@security_app.command()
|
|
686
|
+
@ensure_fastapi_rtk_tables_exist
|
|
672
687
|
@make_sync
|
|
673
688
|
async def import_roles(
|
|
674
689
|
file_path: Annotated[
|
|
@@ -714,6 +729,7 @@ async def import_roles(
|
|
|
714
729
|
|
|
715
730
|
|
|
716
731
|
@security_app.command()
|
|
732
|
+
@ensure_fastapi_rtk_tables_exist
|
|
717
733
|
@make_sync
|
|
718
734
|
async def list_roles():
|
|
719
735
|
"""
|
|
@@ -740,6 +756,7 @@ async def list_roles():
|
|
|
740
756
|
|
|
741
757
|
|
|
742
758
|
@security_app.command()
|
|
759
|
+
@ensure_fastapi_rtk_tables_exist
|
|
743
760
|
@make_sync
|
|
744
761
|
async def create_role(
|
|
745
762
|
names: Annotated[
|
|
@@ -778,6 +795,7 @@ async def create_role(
|
|
|
778
795
|
|
|
779
796
|
|
|
780
797
|
@security_app.command()
|
|
798
|
+
@ensure_fastapi_rtk_tables_exist
|
|
781
799
|
@make_sync
|
|
782
800
|
async def rename_role(
|
|
783
801
|
old_name: Annotated[
|
|
@@ -815,6 +833,7 @@ async def rename_role(
|
|
|
815
833
|
|
|
816
834
|
|
|
817
835
|
@security_app.command()
|
|
836
|
+
@ensure_fastapi_rtk_tables_exist
|
|
818
837
|
@make_sync
|
|
819
838
|
async def delete_role(
|
|
820
839
|
name: Annotated[
|
|
@@ -873,6 +892,7 @@ async def delete_role(
|
|
|
873
892
|
|
|
874
893
|
|
|
875
894
|
@security_app.command()
|
|
895
|
+
@ensure_fastapi_rtk_tables_exist
|
|
876
896
|
@make_sync
|
|
877
897
|
async def list_apis():
|
|
878
898
|
"""
|
|
@@ -899,6 +919,7 @@ async def list_apis():
|
|
|
899
919
|
|
|
900
920
|
|
|
901
921
|
@security_app.command()
|
|
922
|
+
@ensure_fastapi_rtk_tables_exist
|
|
902
923
|
@make_sync
|
|
903
924
|
async def list_permissions(
|
|
904
925
|
role: Annotated[
|
|
@@ -953,6 +974,7 @@ async def list_permissions(
|
|
|
953
974
|
|
|
954
975
|
|
|
955
976
|
@security_app.command()
|
|
977
|
+
@ensure_fastapi_rtk_tables_exist
|
|
956
978
|
@make_sync
|
|
957
979
|
async def add_role(
|
|
958
980
|
email_or_username: Annotated[
|
|
@@ -1007,6 +1029,7 @@ async def add_role(
|
|
|
1007
1029
|
|
|
1008
1030
|
|
|
1009
1031
|
@security_app.command()
|
|
1032
|
+
@ensure_fastapi_rtk_tables_exist
|
|
1010
1033
|
@make_sync
|
|
1011
1034
|
async def assign_role(
|
|
1012
1035
|
email_or_username: Annotated[
|
|
@@ -1058,6 +1081,7 @@ async def assign_role(
|
|
|
1058
1081
|
|
|
1059
1082
|
|
|
1060
1083
|
@security_app.command()
|
|
1084
|
+
@ensure_fastapi_rtk_tables_exist
|
|
1061
1085
|
@make_sync
|
|
1062
1086
|
async def revoke_role(
|
|
1063
1087
|
email_or_username: Annotated[
|
|
@@ -1103,6 +1127,7 @@ async def revoke_role(
|
|
|
1103
1127
|
|
|
1104
1128
|
|
|
1105
1129
|
@security_app.command()
|
|
1130
|
+
@ensure_fastapi_rtk_tables_exist
|
|
1106
1131
|
@make_sync
|
|
1107
1132
|
async def check_access(
|
|
1108
1133
|
user: Annotated[
|
|
@@ -1176,6 +1201,7 @@ async def check_access(
|
|
|
1176
1201
|
|
|
1177
1202
|
|
|
1178
1203
|
@security_app.command()
|
|
1204
|
+
@ensure_fastapi_rtk_tables_exist
|
|
1179
1205
|
@make_sync
|
|
1180
1206
|
async def reset_password(
|
|
1181
1207
|
email_or_username: Annotated[
|
|
@@ -1208,6 +1234,7 @@ async def reset_password(
|
|
|
1208
1234
|
|
|
1209
1235
|
|
|
1210
1236
|
@security_app.command()
|
|
1237
|
+
@ensure_fastapi_rtk_tables_exist
|
|
1211
1238
|
@make_sync
|
|
1212
1239
|
async def cleanup():
|
|
1213
1240
|
"""
|
|
@@ -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)
|
|
@@ -85,9 +85,13 @@ class Globals:
|
|
|
85
85
|
"""
|
|
86
86
|
The configuration settings for the FastAPI React Toolkit.
|
|
87
87
|
"""
|
|
88
|
+
is_cli: bool
|
|
89
|
+
"""
|
|
90
|
+
A boolean value to indicate if the application is loaded by the CLI. `True` when you are running a command from `fastapi-rtk` CLI.
|
|
91
|
+
"""
|
|
88
92
|
is_migrate: bool
|
|
89
93
|
"""
|
|
90
|
-
|
|
94
|
+
Deprecated alias of `is_cli`. TODO(next-minor): remove.
|
|
91
95
|
"""
|
|
92
96
|
sensitive_data: dict[str, list[str]]
|
|
93
97
|
"""
|
|
@@ -287,7 +291,9 @@ g.set_default(
|
|
|
287
291
|
"auth", lazy_import("fastapi_rtk.auth", lambda mod: mod.AuthConfigurator())
|
|
288
292
|
)
|
|
289
293
|
g.set_default("config", Config())
|
|
290
|
-
g.set_default("
|
|
294
|
+
g.set_default("is_cli", False)
|
|
295
|
+
# TODO(next-minor): remove. Deprecated alias; resolves to `is_cli`.
|
|
296
|
+
g.set_default("is_migrate", lazy(lambda: g.is_cli))
|
|
291
297
|
g.set_default("sensitive_data", {"User": ["password", "hashed_password"]})
|
|
292
298
|
g.set_default(
|
|
293
299
|
"file_manager",
|
|
@@ -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!!"},
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Shared fixtures for the cli/commands tests.
|
|
2
|
+
|
|
3
|
+
Command callbacks used to carry the `@ensure_fastapi_rtk_tables_exist` /
|
|
4
|
+
`@ensure_app_loaded` app check; it now sits on the individual commands.
|
|
5
|
+
These unit tests call the command functions directly to exercise their bodies,
|
|
6
|
+
so the app-import + table-init side effects are stubbed out here. The fixture
|
|
7
|
+
yields the stub mocks so a test can assert whether a given command triggered
|
|
8
|
+
the check.
|
|
9
|
+
|
|
10
|
+
`ensure_fastapi_rtk_tables_exist` now runs the table-init and the command body
|
|
11
|
+
inside one `run_in_current_event_loop` call, so the mock standing in for it must
|
|
12
|
+
actually execute the coroutine it receives (otherwise async command bodies never
|
|
13
|
+
run). It delegates to the real helper while still recording calls, and
|
|
14
|
+
`init_fastapi_rtk_tables` is an awaitable stub so the in-loop `await` is a no-op.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from types import SimpleNamespace
|
|
18
|
+
from unittest.mock import AsyncMock, MagicMock
|
|
19
|
+
|
|
20
|
+
import pytest
|
|
21
|
+
|
|
22
|
+
from fastapi_rtk.cli import decorators
|
|
23
|
+
from fastapi_rtk.cli.utils import run_in_current_event_loop as _run_loop
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@pytest.fixture(autouse=True)
|
|
27
|
+
def neutralize_app_check(monkeypatch):
|
|
28
|
+
get_import_data = MagicMock(name="get_import_data")
|
|
29
|
+
run_in_current_event_loop = MagicMock(
|
|
30
|
+
name="run_in_current_event_loop", side_effect=_run_loop
|
|
31
|
+
)
|
|
32
|
+
init_fastapi_rtk_tables = AsyncMock(
|
|
33
|
+
name="init_fastapi_rtk_tables", return_value=None
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
monkeypatch.setattr(decorators, "get_import_data", get_import_data)
|
|
37
|
+
monkeypatch.setattr(
|
|
38
|
+
decorators, "run_in_current_event_loop", run_in_current_event_loop
|
|
39
|
+
)
|
|
40
|
+
monkeypatch.setattr(
|
|
41
|
+
decorators.db, "init_fastapi_rtk_tables", init_fastapi_rtk_tables
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
return SimpleNamespace(
|
|
45
|
+
get_import_data=get_import_data,
|
|
46
|
+
run_in_current_event_loop=run_in_current_event_loop,
|
|
47
|
+
init_fastapi_rtk_tables=init_fastapi_rtk_tables,
|
|
48
|
+
)
|
|
@@ -176,3 +176,54 @@ class TestDbCommandWrappers:
|
|
|
176
176
|
)
|
|
177
177
|
# Just smoke - no assertion on output here, command writes to stdout
|
|
178
178
|
list_templates()
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
class TestAppCheckPartition:
|
|
182
|
+
"""Each db command only runs the app check it actually needs."""
|
|
183
|
+
|
|
184
|
+
def _patch_alembic(self, monkeypatch, name):
|
|
185
|
+
from unittest.mock import MagicMock
|
|
186
|
+
|
|
187
|
+
from fastapi_rtk.cli.commands import db as db_mod
|
|
188
|
+
|
|
189
|
+
monkeypatch.setattr(db_mod.alembic.command, name, MagicMock())
|
|
190
|
+
|
|
191
|
+
def test_list_templates_skips_check(self, monkeypatch, neutralize_app_check):
|
|
192
|
+
from fastapi_rtk.cli.commands.db import Config, list_templates
|
|
193
|
+
|
|
194
|
+
monkeypatch.setattr(Config, "get_template_directory", lambda self: ".")
|
|
195
|
+
monkeypatch.setattr("os.listdir", lambda _p: [])
|
|
196
|
+
list_templates()
|
|
197
|
+
neutralize_app_check.get_import_data.assert_not_called()
|
|
198
|
+
|
|
199
|
+
def test_init_skips_check(self, tmp_path, monkeypatch, neutralize_app_check):
|
|
200
|
+
from fastapi_rtk.cli.commands.db import init
|
|
201
|
+
|
|
202
|
+
self._patch_alembic(monkeypatch, "init")
|
|
203
|
+
init(directory=str(tmp_path))
|
|
204
|
+
neutralize_app_check.get_import_data.assert_not_called()
|
|
205
|
+
|
|
206
|
+
def test_history_is_import_only(self, monkeypatch, neutralize_app_check):
|
|
207
|
+
from fastapi_rtk.cli.commands.db import history
|
|
208
|
+
|
|
209
|
+
self._patch_alembic(monkeypatch, "history")
|
|
210
|
+
history()
|
|
211
|
+
neutralize_app_check.get_import_data.assert_called_once()
|
|
212
|
+
neutralize_app_check.run_in_current_event_loop.assert_not_called()
|
|
213
|
+
|
|
214
|
+
def test_upgrade_runs_full_check(self, monkeypatch, neutralize_app_check):
|
|
215
|
+
from fastapi_rtk.cli.commands.db import upgrade
|
|
216
|
+
|
|
217
|
+
self._patch_alembic(monkeypatch, "upgrade")
|
|
218
|
+
upgrade(revision="head")
|
|
219
|
+
neutralize_app_check.get_import_data.assert_called_once()
|
|
220
|
+
neutralize_app_check.run_in_current_event_loop.assert_called_once()
|
|
221
|
+
|
|
222
|
+
def test_migrate_checks_once_via_revision(self, monkeypatch, neutralize_app_check):
|
|
223
|
+
from fastapi_rtk.cli.commands.db import migrate
|
|
224
|
+
|
|
225
|
+
self._patch_alembic(monkeypatch, "revision")
|
|
226
|
+
migrate(message="auto")
|
|
227
|
+
# migrate is undecorated; the single check fires through revision.
|
|
228
|
+
neutralize_app_check.get_import_data.assert_called_once()
|
|
229
|
+
neutralize_app_check.run_in_current_event_loop.assert_called_once()
|
|
@@ -12,6 +12,45 @@ class TestHelpSmoke:
|
|
|
12
12
|
assert result.exit_code == 0
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
class TestAppCheckPartition:
|
|
16
|
+
"""Each export command only runs the app check it actually needs."""
|
|
17
|
+
|
|
18
|
+
def test_licenses_is_import_only(self, tmp_path, monkeypatch, neutralize_app_check):
|
|
19
|
+
# Reads `LICENSE_FOLDER` from config, so the app must be imported; but
|
|
20
|
+
# it never touches the database.
|
|
21
|
+
from fastapi_rtk.cli.commands import export as ex_mod
|
|
22
|
+
|
|
23
|
+
monkeypatch.setattr(
|
|
24
|
+
ex_mod.piplicenses, "create_output_string", lambda args: "[]"
|
|
25
|
+
)
|
|
26
|
+
ex_mod.licenses(
|
|
27
|
+
output_dir=str(tmp_path / "lic"), webapp_dir=str(tmp_path / "ghost")
|
|
28
|
+
)
|
|
29
|
+
neutralize_app_check.get_import_data.assert_called_once()
|
|
30
|
+
neutralize_app_check.run_in_current_event_loop.assert_not_called()
|
|
31
|
+
|
|
32
|
+
def test_api_docs_is_import_only(self, tmp_path, monkeypatch, neutralize_app_check):
|
|
33
|
+
from unittest.mock import MagicMock
|
|
34
|
+
|
|
35
|
+
from fastapi_rtk.cli.commands import export as ex_mod
|
|
36
|
+
from fastapi_rtk.globals import g
|
|
37
|
+
|
|
38
|
+
app_mock = MagicMock()
|
|
39
|
+
app_mock.apis = []
|
|
40
|
+
app_mock.app.openapi.return_value = {"paths": {}, "components": {}}
|
|
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
|
|
48
|
+
|
|
49
|
+
ex_mod.api_docs(filename=str(tmp_path / "out.md"))
|
|
50
|
+
neutralize_app_check.get_import_data.assert_called_once()
|
|
51
|
+
neutralize_app_check.run_in_current_event_loop.assert_not_called()
|
|
52
|
+
|
|
53
|
+
|
|
15
54
|
class TestExportHelpers:
|
|
16
55
|
def test_generate_fastapi_rtk_tables_docs_populates(self):
|
|
17
56
|
from fastapi_rtk.cli.commands.export import (
|