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.
Files changed (300) hide show
  1. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/PKG-INFO +1 -1
  2. fastapi_rtk-2.1.2/fastapi_rtk/_version.py +1 -0
  3. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/__init__.py +15 -2
  4. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/export.py +5 -2
  5. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/security.py +28 -1
  6. fastapi_rtk-2.1.2/fastapi_rtk/cli/decorators.py +80 -0
  7. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/fastapi_react_toolkit.py +1 -1
  8. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/globals.py +8 -2
  9. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/conftest.py +3 -0
  10. fastapi_rtk-2.1.2/tests/unit/cli/commands/conftest.py +48 -0
  11. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/cli/commands/test_db.py +51 -0
  12. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/cli/commands/test_export.py +39 -0
  13. fastapi_rtk-2.1.2/tests/unit/cli/conftest.py +30 -0
  14. fastapi_rtk-2.1.2/tests/unit/cli/test_decorators.py +240 -0
  15. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_fastapi_react_toolkit.py +32 -7
  16. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_globals.py +20 -2
  17. fastapi_rtk-2.1.0/fastapi_rtk/_version.py +0 -1
  18. fastapi_rtk-2.1.0/fastapi_rtk/cli/decorators.py +0 -48
  19. fastapi_rtk-2.1.0/tests/unit/cli/conftest.py +0 -16
  20. fastapi_rtk-2.1.0/tests/unit/cli/test_decorators.py +0 -113
  21. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/.gitignore +0 -0
  22. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/LICENSE +0 -0
  23. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/README.md +0 -0
  24. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/__init__.py +0 -0
  25. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/__init__.py +0 -0
  26. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/base_api.py +0 -0
  27. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/__init__.py +0 -0
  28. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_add_mixin.py +0 -0
  29. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_bulk_mixin.py +0 -0
  30. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_columns.py +0 -0
  31. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_delete_mixin.py +0 -0
  32. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_download_mixin.py +0 -0
  33. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_edit_mixin.py +0 -0
  34. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_file_mixin.py +0 -0
  35. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_info_mixin.py +0 -0
  36. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_list_mixin.py +0 -0
  37. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_params.py +0 -0
  38. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_show_mixin.py +0 -0
  39. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/api/model_rest_api/_upload_mixin.py +0 -0
  40. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/apis/__init__.py +0 -0
  41. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/apis/info.py +0 -0
  42. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/apis/license.py +0 -0
  43. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/__init__.py +0 -0
  44. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/auth.py +0 -0
  45. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/hashers/__init__.py +0 -0
  46. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/hashers/pbkdf2.py +0 -0
  47. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/hashers/scrypt.py +0 -0
  48. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/ldap.py +0 -0
  49. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/password_helpers/__init__.py +0 -0
  50. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/password_helpers/fab.py +0 -0
  51. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/strategies/__init__.py +0 -0
  52. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/strategies/config.py +0 -0
  53. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/strategies/db.py +0 -0
  54. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/auth/strategies/jwt.py +0 -0
  55. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/__init__.py +0 -0
  56. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/__init__.py +0 -0
  57. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/column.py +0 -0
  58. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/db.py +0 -0
  59. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/exceptions.py +0 -0
  60. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/filters.py +0 -0
  61. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/interface.py +0 -0
  62. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/model.py +0 -0
  63. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/generic/session.py +0 -0
  64. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/__init__.py +0 -0
  65. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/column.py +0 -0
  66. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/db.py +0 -0
  67. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/exceptions.py +0 -0
  68. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/__init__.py +0 -0
  69. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/__init__.py +0 -0
  70. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/_decorators_mixin.py +0 -0
  71. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/_lifecycle_mixin.py +0 -0
  72. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/_logger.py +0 -0
  73. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/_processing_mixin.py +0 -0
  74. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/audit.py +0 -0
  75. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/audit/types.py +0 -0
  76. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/__init__.py +0 -0
  77. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/filters.py +0 -0
  78. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/geometry_converter.py +0 -0
  79. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/filters.py +0 -0
  80. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/interface.py +0 -0
  81. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/model.py +0 -0
  82. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/backends/sqla/session.py +0 -0
  83. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/bases/__init__.py +0 -0
  84. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/bases/db.py +0 -0
  85. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/bases/file_manager.py +0 -0
  86. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/bases/filter.py +0 -0
  87. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/bases/interface.py +0 -0
  88. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/bases/model.py +0 -0
  89. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/bases/session.py +0 -0
  90. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/__init__.py +0 -0
  91. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/cli.py +0 -0
  92. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/__init__.py +0 -0
  93. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/_security_crypto.py +0 -0
  94. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi/README +0 -0
  95. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi/alembic.ini.mako +0 -0
  96. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi/env.py +0 -0
  97. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi/script.py.mako +0 -0
  98. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/README +0 -0
  99. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/alembic.ini.mako +0 -0
  100. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/env.py +0 -0
  101. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/script.py.mako +0 -0
  102. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/commands/translate.py +0 -0
  103. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/const.py +0 -0
  104. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/types.py +0 -0
  105. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/cli/utils.py +0 -0
  106. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/config.py +0 -0
  107. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/const.py +0 -0
  108. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/db.py +0 -0
  109. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/decorators.py +0 -0
  110. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/dependencies.py +0 -0
  111. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/exceptions.py +0 -0
  112. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/file_managers/__init__.py +0 -0
  113. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/file_managers/file_manager.py +0 -0
  114. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/file_managers/image_manager.py +0 -0
  115. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/file_managers/s3_file_manager.py +0 -0
  116. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/file_managers/s3_image_manager.py +0 -0
  117. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/filters.py +0 -0
  118. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/__init__.py +0 -0
  119. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/babel/__init__.py +0 -0
  120. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/babel/cli.py +0 -0
  121. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/babel/config.py +0 -0
  122. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/babel.cfg +0 -0
  123. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/lazy_text.py +0 -0
  124. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/messages.pot +0 -0
  125. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.mo +0 -0
  126. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.po +0 -0
  127. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.mo +0 -0
  128. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.po +0 -0
  129. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/manager.py +0 -0
  130. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/middlewares.py +0 -0
  131. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/mixins.py +0 -0
  132. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/models.py +0 -0
  133. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/py.typed +0 -0
  134. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/registry.py +0 -0
  135. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/routers.py +0 -0
  136. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/schemas.py +0 -0
  137. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/__init__.py +0 -0
  138. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/__init__.py +0 -0
  139. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/apis.py +0 -0
  140. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/models.py +0 -0
  141. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/__init__.py +0 -0
  142. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_association_mixin.py +0 -0
  143. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_builtin_role_mixin.py +0 -0
  144. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_cleanup_mixin.py +0 -0
  145. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_exception_filters.py +0 -0
  146. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_export.py +0 -0
  147. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_import.py +0 -0
  148. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_role_mixin.py +0 -0
  149. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/security/sqla/security_manager/_user_mixin.py +0 -0
  150. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/setting.py +0 -0
  151. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/types.py +0 -0
  152. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/__init__.py +0 -0
  153. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/async_task_runner.py +0 -0
  154. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/class_factory.py +0 -0
  155. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/csv_json_converter.py +0 -0
  156. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/deep_merge.py +0 -0
  157. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/extender_mixin.py +0 -0
  158. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/flask_appbuilder_utils.py +0 -0
  159. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/formatter.py +0 -0
  160. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/hooks.py +0 -0
  161. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/lazy.py +0 -0
  162. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/merge_schema.py +0 -0
  163. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/multiple_async_contexts.py +0 -0
  164. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/pydantic.py +0 -0
  165. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/run_utils.py +0 -0
  166. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/self_dependencies.py +0 -0
  167. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/smartdefaultdict.py +0 -0
  168. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/sqla.py +0 -0
  169. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/timezone.py +0 -0
  170. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/update_signature.py +0 -0
  171. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/utils/use_default_when_none.py +0 -0
  172. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/fastapi_rtk/version.py +0 -0
  173. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/pyproject.toml +0 -0
  174. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/docker-compose.gis.yml +0 -0
  175. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/__init__.py +0 -0
  176. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/api/__init__.py +0 -0
  177. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/api/test_model_rest_api.py +0 -0
  178. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/apis/__init__.py +0 -0
  179. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/apis/test_info_contract.py +0 -0
  180. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/auth/__init__.py +0 -0
  181. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/auth/test_auth_flow.py +0 -0
  182. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/auth/test_oauth.py +0 -0
  183. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/conftest.py +0 -0
  184. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/file_managers/__init__.py +0 -0
  185. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/file_managers/test_file_routes.py +0 -0
  186. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/security/__init__.py +0 -0
  187. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/security/sqla/__init__.py +0 -0
  188. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/security/sqla/test_security_manager.py +0 -0
  189. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/integration/test_app_smoke.py +0 -0
  190. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/__init__.py +0 -0
  191. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/api/__init__.py +0 -0
  192. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/api/conftest.py +0 -0
  193. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/api/model_rest_api/__init__.py +0 -0
  194. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/api/model_rest_api/test_columns.py +0 -0
  195. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/api/model_rest_api/test_file_mixin.py +0 -0
  196. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/api/model_rest_api/test_init.py +0 -0
  197. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/api/test_base_api.py +0 -0
  198. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/apis/__init__.py +0 -0
  199. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/apis/test_info.py +0 -0
  200. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/apis/test_license.py +0 -0
  201. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/__init__.py +0 -0
  202. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/hashers/__init__.py +0 -0
  203. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/hashers/test_pbkdf2.py +0 -0
  204. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/hashers/test_scrypt.py +0 -0
  205. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/password_helpers/__init__.py +0 -0
  206. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/password_helpers/test_fab.py +0 -0
  207. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/strategies/__init__.py +0 -0
  208. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/strategies/test_config.py +0 -0
  209. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/strategies/test_db.py +0 -0
  210. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/strategies/test_jwt.py +0 -0
  211. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/auth/test_auth.py +0 -0
  212. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/__init__.py +0 -0
  213. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/__init__.py +0 -0
  214. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/test_column.py +0 -0
  215. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/test_db.py +0 -0
  216. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/test_exceptions.py +0 -0
  217. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/test_filters.py +0 -0
  218. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/test_interface.py +0 -0
  219. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/test_model.py +0 -0
  220. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/generic/test_session.py +0 -0
  221. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/__init__.py +0 -0
  222. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/conftest.py +0 -0
  223. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_audit.py +0 -0
  224. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_audit_types.py +0 -0
  225. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_column.py +0 -0
  226. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_db.py +0 -0
  227. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_filters.py +0 -0
  228. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_geoalchemy2.py +0 -0
  229. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_interface.py +0 -0
  230. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_model.py +0 -0
  231. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/backends/sqla/test_session.py +0 -0
  232. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/bases/__init__.py +0 -0
  233. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/bases/test_db.py +0 -0
  234. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/bases/test_file_manager.py +0 -0
  235. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/bases/test_filter.py +0 -0
  236. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/bases/test_interface.py +0 -0
  237. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/bases/test_model.py +0 -0
  238. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/bases/test_session.py +0 -0
  239. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/cli/__init__.py +0 -0
  240. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/cli/commands/__init__.py +0 -0
  241. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/cli/commands/test_security.py +0 -0
  242. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/cli/commands/test_security_crypto.py +0 -0
  243. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/cli/commands/test_translate.py +0 -0
  244. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/cli/test_cli.py +0 -0
  245. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/cli/test_types.py +0 -0
  246. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/cli/test_utils.py +0 -0
  247. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/file_managers/__init__.py +0 -0
  248. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/file_managers/conftest.py +0 -0
  249. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/file_managers/test_file_manager.py +0 -0
  250. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/file_managers/test_image_manager.py +0 -0
  251. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/file_managers/test_s3_file_manager.py +0 -0
  252. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/file_managers/test_s3_image_manager.py +0 -0
  253. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/lang/__init__.py +0 -0
  254. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/lang/test_babel_cli.py +0 -0
  255. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/lang/test_babel_config.py +0 -0
  256. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/lang/test_lazy_text.py +0 -0
  257. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/security/__init__.py +0 -0
  258. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/security/sqla/__init__.py +0 -0
  259. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/security/sqla/conftest.py +0 -0
  260. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/security/sqla/test_apis.py +0 -0
  261. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/security/sqla/test_models.py +0 -0
  262. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/security/sqla/test_security_manager.py +0 -0
  263. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_config.py +0 -0
  264. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_const.py +0 -0
  265. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_db.py +0 -0
  266. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_decorators.py +0 -0
  267. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_dependencies.py +0 -0
  268. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_exceptions.py +0 -0
  269. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_filters.py +0 -0
  270. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_manager.py +0 -0
  271. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_middlewares.py +0 -0
  272. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_mixins.py +0 -0
  273. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_models.py +0 -0
  274. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_registry.py +0 -0
  275. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_routers.py +0 -0
  276. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_schemas.py +0 -0
  277. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_setting.py +0 -0
  278. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_types.py +0 -0
  279. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/test_version.py +0 -0
  280. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/__init__.py +0 -0
  281. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_async_task_runner.py +0 -0
  282. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_class_factory.py +0 -0
  283. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_csv_json_converter.py +0 -0
  284. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_deep_merge.py +0 -0
  285. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_extender_mixin.py +0 -0
  286. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_flask_appbuilder_utils.py +0 -0
  287. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_formatter.py +0 -0
  288. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_hooks.py +0 -0
  289. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_lazy.py +0 -0
  290. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_merge_schema.py +0 -0
  291. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_multiple_async_contexts.py +0 -0
  292. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_pydantic.py +0 -0
  293. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_run_utils.py +0 -0
  294. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_self_dependencies.py +0 -0
  295. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_smartdefaultdict.py +0 -0
  296. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_sqla.py +0 -0
  297. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_timezone.py +0 -0
  298. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_update_signature.py +0 -0
  299. {fastapi_rtk-2.1.0 → fastapi_rtk-2.1.2}/tests/unit/utils/test_use_default_when_none.py +0 -0
  300. {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.0
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)
@@ -630,7 +630,7 @@ class FastAPIReactToolkit:
630
630
  logger.setLevel(logging.DEBUG)
631
631
 
632
632
  def _init_lifespan(self):
633
- if g.is_migrate:
633
+ if g.is_cli:
634
634
  return
635
635
 
636
636
  @asynccontextmanager
@@ -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
- A boolean value to indicate if the application is in migration mode. `True` when you are running a command from `fastapi-rtk` CLI.
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("is_migrate", False)
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 (