fastapi-rtk 2.12.4__tar.gz → 2.13.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (312) hide show
  1. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/PKG-INFO +1 -1
  2. fastapi_rtk-2.13.0/fastapi_rtk/_version.py +1 -0
  3. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/generic/column.py +87 -18
  4. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/generic/model.py +18 -5
  5. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/backends/generic/test_column.py +94 -0
  6. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/backends/generic/test_model.py +79 -4
  7. fastapi_rtk-2.12.4/fastapi_rtk/_version.py +0 -1
  8. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/.gitignore +0 -0
  9. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/LICENSE +0 -0
  10. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/README.md +0 -0
  11. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/__init__.py +0 -0
  12. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/api/__init__.py +0 -0
  13. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/api/base_api.py +0 -0
  14. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/api/model_rest_api/__init__.py +0 -0
  15. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/api/model_rest_api/_add_mixin.py +0 -0
  16. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/api/model_rest_api/_bulk_mixin.py +0 -0
  17. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/api/model_rest_api/_columns_mixin.py +0 -0
  18. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/api/model_rest_api/_delete_mixin.py +0 -0
  19. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/api/model_rest_api/_download_mixin.py +0 -0
  20. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/api/model_rest_api/_edit_mixin.py +0 -0
  21. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/api/model_rest_api/_file_mixin.py +0 -0
  22. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/api/model_rest_api/_info_mixin.py +0 -0
  23. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/api/model_rest_api/_list_mixin.py +0 -0
  24. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/api/model_rest_api/_params.py +0 -0
  25. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/api/model_rest_api/_show_mixin.py +0 -0
  26. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/api/model_rest_api/_typed_base.py +0 -0
  27. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/api/model_rest_api/_upload_mixin.py +0 -0
  28. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/apis/__init__.py +0 -0
  29. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/apis/info.py +0 -0
  30. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/apis/license.py +0 -0
  31. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/auth/__init__.py +0 -0
  32. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/auth/auth.py +0 -0
  33. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/auth/hashers/__init__.py +0 -0
  34. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/auth/hashers/pbkdf2.py +0 -0
  35. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/auth/hashers/scrypt.py +0 -0
  36. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/auth/ldap.py +0 -0
  37. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/auth/password_helpers/__init__.py +0 -0
  38. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/auth/password_helpers/fab.py +0 -0
  39. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/auth/strategies/__init__.py +0 -0
  40. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/auth/strategies/config.py +0 -0
  41. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/auth/strategies/db.py +0 -0
  42. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/auth/strategies/jwt.py +0 -0
  43. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/__init__.py +0 -0
  44. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/generic/__init__.py +0 -0
  45. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/generic/db.py +0 -0
  46. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/generic/exceptions.py +0 -0
  47. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/generic/filters.py +0 -0
  48. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/generic/interface.py +0 -0
  49. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/generic/session.py +0 -0
  50. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/sqla/__init__.py +0 -0
  51. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/sqla/column.py +0 -0
  52. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/sqla/db.py +0 -0
  53. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/sqla/exceptions.py +0 -0
  54. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/sqla/extensions/__init__.py +0 -0
  55. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/sqla/extensions/audit/__init__.py +0 -0
  56. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/sqla/extensions/audit/_decorators_mixin.py +0 -0
  57. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/sqla/extensions/audit/_lifecycle_mixin.py +0 -0
  58. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/sqla/extensions/audit/_logger.py +0 -0
  59. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/sqla/extensions/audit/_processing_mixin.py +0 -0
  60. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/sqla/extensions/audit/audit.py +0 -0
  61. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/sqla/extensions/audit/types.py +0 -0
  62. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/__init__.py +0 -0
  63. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/filters.py +0 -0
  64. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/geometry_converter.py +0 -0
  65. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/sqla/filters.py +0 -0
  66. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/sqla/interface.py +0 -0
  67. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/sqla/model.py +0 -0
  68. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/backends/sqla/session.py +0 -0
  69. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/bases/__init__.py +0 -0
  70. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/bases/cache.py +0 -0
  71. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/bases/db.py +0 -0
  72. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/bases/file_manager.py +0 -0
  73. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/bases/filter.py +0 -0
  74. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/bases/interface.py +0 -0
  75. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/bases/loop_manager.py +0 -0
  76. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/bases/model.py +0 -0
  77. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/bases/session.py +0 -0
  78. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/bases/user_cache.py +0 -0
  79. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/caches/__init__.py +0 -0
  80. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/caches/cache.py +0 -0
  81. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/caches/serializers.py +0 -0
  82. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/caches/storages.py +0 -0
  83. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/cli/__init__.py +0 -0
  84. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/cli/cli.py +0 -0
  85. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/cli/commands/__init__.py +0 -0
  86. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/cli/commands/_security_crypto.py +0 -0
  87. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/cli/commands/db/__init__.py +0 -0
  88. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/cli/commands/db/templates/fastapi/README +0 -0
  89. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/cli/commands/db/templates/fastapi/alembic.ini.mako +0 -0
  90. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/cli/commands/db/templates/fastapi/env.py +0 -0
  91. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/cli/commands/db/templates/fastapi/script.py.mako +0 -0
  92. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/README +0 -0
  93. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/alembic.ini.mako +0 -0
  94. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/env.py +0 -0
  95. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/script.py.mako +0 -0
  96. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/cli/commands/export.py +0 -0
  97. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/cli/commands/security.py +0 -0
  98. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/cli/commands/translate.py +0 -0
  99. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/cli/const.py +0 -0
  100. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/cli/decorators.py +0 -0
  101. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/cli/types.py +0 -0
  102. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/cli/utils.py +0 -0
  103. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/config.py +0 -0
  104. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/const.py +0 -0
  105. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/db.py +0 -0
  106. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/decorators.py +0 -0
  107. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/dependencies.py +0 -0
  108. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/exceptions.py +0 -0
  109. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/fastapi_react_toolkit.py +0 -0
  110. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/file_managers/__init__.py +0 -0
  111. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/file_managers/file_manager.py +0 -0
  112. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/file_managers/image_manager.py +0 -0
  113. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/file_managers/s3_file_manager.py +0 -0
  114. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/file_managers/s3_image_manager.py +0 -0
  115. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/filters.py +0 -0
  116. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/globals.py +0 -0
  117. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/lang/__init__.py +0 -0
  118. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/lang/babel/__init__.py +0 -0
  119. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/lang/babel/cli.py +0 -0
  120. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/lang/babel/config.py +0 -0
  121. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/lang/babel.cfg +0 -0
  122. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/lang/lazy_text.py +0 -0
  123. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/lang/messages.pot +0 -0
  124. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.mo +0 -0
  125. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.po +0 -0
  126. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.mo +0 -0
  127. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.po +0 -0
  128. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/loop_managers/__init__.py +0 -0
  129. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/loop_managers/loop_manager.py +0 -0
  130. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/manager.py +0 -0
  131. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/middlewares.py +0 -0
  132. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/mixins.py +0 -0
  133. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/models.py +0 -0
  134. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/py.typed +0 -0
  135. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/registry.py +0 -0
  136. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/routers.py +0 -0
  137. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/schemas.py +0 -0
  138. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/security/__init__.py +0 -0
  139. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/security/sqla/__init__.py +0 -0
  140. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/security/sqla/apis.py +0 -0
  141. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/security/sqla/models.py +0 -0
  142. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/security/sqla/security_manager/__init__.py +0 -0
  143. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/security/sqla/security_manager/_association_mixin.py +0 -0
  144. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/security/sqla/security_manager/_builtin_role_mixin.py +0 -0
  145. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/security/sqla/security_manager/_cleanup_mixin.py +0 -0
  146. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/security/sqla/security_manager/_exception_filters.py +0 -0
  147. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/security/sqla/security_manager/_export.py +0 -0
  148. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/security/sqla/security_manager/_import.py +0 -0
  149. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/security/sqla/security_manager/_role_mixin.py +0 -0
  150. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/security/sqla/security_manager/_user_mixin.py +0 -0
  151. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/security/sqla/user_cache.py +0 -0
  152. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/setting.py +0 -0
  153. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/types.py +0 -0
  154. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/utils/__init__.py +0 -0
  155. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/utils/async_task_runner.py +0 -0
  156. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/utils/class_factory.py +0 -0
  157. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/utils/csv_json_converter.py +0 -0
  158. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/utils/deep_merge.py +0 -0
  159. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/utils/extender_mixin.py +0 -0
  160. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/utils/flask_appbuilder_utils.py +0 -0
  161. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/utils/formatter.py +0 -0
  162. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/utils/hooks.py +0 -0
  163. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/utils/lazy.py +0 -0
  164. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/utils/merge_schema.py +0 -0
  165. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/utils/multiple_async_contexts.py +0 -0
  166. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/utils/pydantic.py +0 -0
  167. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/utils/run_utils.py +0 -0
  168. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/utils/self_dependencies.py +0 -0
  169. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/utils/smartdefaultdict.py +0 -0
  170. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/utils/sqla.py +0 -0
  171. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/utils/timezone.py +0 -0
  172. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/utils/update_signature.py +0 -0
  173. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/utils/use_default_when_none.py +0 -0
  174. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/fastapi_rtk/version.py +0 -0
  175. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/pyproject.toml +0 -0
  176. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/conftest.py +0 -0
  177. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/docker-compose.gis.yml +0 -0
  178. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/integration/__init__.py +0 -0
  179. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/integration/api/__init__.py +0 -0
  180. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/integration/api/test_model_rest_api.py +0 -0
  181. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/integration/apis/__init__.py +0 -0
  182. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/integration/apis/test_info_callable_schema.py +0 -0
  183. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/integration/apis/test_info_contract.py +0 -0
  184. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/integration/auth/__init__.py +0 -0
  185. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/integration/auth/test_auth_flow.py +0 -0
  186. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/integration/auth/test_oauth.py +0 -0
  187. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/integration/conftest.py +0 -0
  188. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/integration/file_managers/__init__.py +0 -0
  189. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/integration/file_managers/test_file_routes.py +0 -0
  190. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/integration/security/__init__.py +0 -0
  191. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/integration/security/sqla/__init__.py +0 -0
  192. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/integration/security/sqla/test_security_manager.py +0 -0
  193. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/integration/test_app_smoke.py +0 -0
  194. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/__init__.py +0 -0
  195. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/api/__init__.py +0 -0
  196. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/api/conftest.py +0 -0
  197. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/api/model_rest_api/__init__.py +0 -0
  198. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/api/model_rest_api/test_columns.py +0 -0
  199. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/api/model_rest_api/test_file_mixin.py +0 -0
  200. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/api/model_rest_api/test_init.py +0 -0
  201. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/api/model_rest_api/test_typed_base_consistency.py +0 -0
  202. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/api/test_base_api.py +0 -0
  203. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/apis/__init__.py +0 -0
  204. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/apis/test_info.py +0 -0
  205. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/apis/test_license.py +0 -0
  206. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/auth/__init__.py +0 -0
  207. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/auth/hashers/__init__.py +0 -0
  208. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/auth/hashers/test_pbkdf2.py +0 -0
  209. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/auth/hashers/test_scrypt.py +0 -0
  210. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/auth/password_helpers/__init__.py +0 -0
  211. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/auth/password_helpers/test_fab.py +0 -0
  212. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/auth/strategies/__init__.py +0 -0
  213. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/auth/strategies/test_config.py +0 -0
  214. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/auth/strategies/test_db.py +0 -0
  215. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/auth/strategies/test_jwt.py +0 -0
  216. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/auth/test_auth.py +0 -0
  217. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/backends/__init__.py +0 -0
  218. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/backends/generic/__init__.py +0 -0
  219. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/backends/generic/test_db.py +0 -0
  220. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/backends/generic/test_exceptions.py +0 -0
  221. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/backends/generic/test_filters.py +0 -0
  222. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/backends/generic/test_interface.py +0 -0
  223. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/backends/generic/test_session.py +0 -0
  224. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/backends/sqla/__init__.py +0 -0
  225. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/backends/sqla/conftest.py +0 -0
  226. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/backends/sqla/test_audit.py +0 -0
  227. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/backends/sqla/test_audit_types.py +0 -0
  228. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/backends/sqla/test_column.py +0 -0
  229. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/backends/sqla/test_db.py +0 -0
  230. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/backends/sqla/test_filters.py +0 -0
  231. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/backends/sqla/test_geoalchemy2.py +0 -0
  232. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/backends/sqla/test_interface.py +0 -0
  233. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/backends/sqla/test_model.py +0 -0
  234. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/backends/sqla/test_session.py +0 -0
  235. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/bases/__init__.py +0 -0
  236. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/bases/test_db.py +0 -0
  237. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/bases/test_file_manager.py +0 -0
  238. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/bases/test_filter.py +0 -0
  239. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/bases/test_interface.py +0 -0
  240. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/bases/test_model.py +0 -0
  241. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/bases/test_session.py +0 -0
  242. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/cli/__init__.py +0 -0
  243. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/cli/commands/__init__.py +0 -0
  244. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/cli/commands/conftest.py +0 -0
  245. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/cli/commands/test_db.py +0 -0
  246. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/cli/commands/test_export.py +0 -0
  247. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/cli/commands/test_security.py +0 -0
  248. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/cli/commands/test_security_crypto.py +0 -0
  249. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/cli/commands/test_translate.py +0 -0
  250. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/cli/conftest.py +0 -0
  251. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/cli/test_cli.py +0 -0
  252. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/cli/test_decorators.py +0 -0
  253. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/cli/test_types.py +0 -0
  254. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/cli/test_utils.py +0 -0
  255. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/file_managers/__init__.py +0 -0
  256. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/file_managers/conftest.py +0 -0
  257. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/file_managers/test_file_manager.py +0 -0
  258. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/file_managers/test_image_manager.py +0 -0
  259. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/file_managers/test_s3_file_manager.py +0 -0
  260. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/file_managers/test_s3_image_manager.py +0 -0
  261. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/lang/__init__.py +0 -0
  262. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/lang/test_babel_cli.py +0 -0
  263. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/lang/test_babel_config.py +0 -0
  264. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/lang/test_lazy_text.py +0 -0
  265. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/security/__init__.py +0 -0
  266. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/security/sqla/__init__.py +0 -0
  267. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/security/sqla/conftest.py +0 -0
  268. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/security/sqla/test_apis.py +0 -0
  269. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/security/sqla/test_models.py +0 -0
  270. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/security/sqla/test_security_manager.py +0 -0
  271. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/test_caches.py +0 -0
  272. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/test_config.py +0 -0
  273. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/test_const.py +0 -0
  274. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/test_db.py +0 -0
  275. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/test_decorators.py +0 -0
  276. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/test_dependencies.py +0 -0
  277. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/test_exceptions.py +0 -0
  278. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/test_fastapi_react_toolkit.py +0 -0
  279. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/test_filters.py +0 -0
  280. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/test_globals.py +0 -0
  281. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/test_manager.py +0 -0
  282. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/test_middlewares.py +0 -0
  283. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/test_mixins.py +0 -0
  284. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/test_models.py +0 -0
  285. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/test_registry.py +0 -0
  286. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/test_routers.py +0 -0
  287. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/test_schemas.py +0 -0
  288. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/test_setting.py +0 -0
  289. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/test_types.py +0 -0
  290. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/test_user_cache.py +0 -0
  291. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/test_version.py +0 -0
  292. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/utils/__init__.py +0 -0
  293. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/utils/test_async_task_runner.py +0 -0
  294. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/utils/test_class_factory.py +0 -0
  295. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/utils/test_csv_json_converter.py +0 -0
  296. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/utils/test_deep_merge.py +0 -0
  297. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/utils/test_extender_mixin.py +0 -0
  298. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/utils/test_flask_appbuilder_utils.py +0 -0
  299. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/utils/test_formatter.py +0 -0
  300. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/utils/test_hooks.py +0 -0
  301. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/utils/test_lazy.py +0 -0
  302. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/utils/test_merge_schema.py +0 -0
  303. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/utils/test_multiple_async_contexts.py +0 -0
  304. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/utils/test_pydantic.py +0 -0
  305. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/utils/test_run_utils.py +0 -0
  306. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/utils/test_self_dependencies.py +0 -0
  307. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/utils/test_smartdefaultdict.py +0 -0
  308. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/utils/test_sqla.py +0 -0
  309. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/utils/test_timezone.py +0 -0
  310. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/utils/test_update_signature.py +0 -0
  311. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/tests/unit/utils/test_use_default_when_none.py +0 -0
  312. {fastapi_rtk-2.12.4 → fastapi_rtk-2.13.0}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: fastapi-rtk
3
- Version: 2.12.4
3
+ Version: 2.13.0
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.13.0"
@@ -1,4 +1,5 @@
1
1
  import collections.abc
2
+ import copy
2
3
  import inspect
3
4
  import typing
4
5
 
@@ -6,7 +7,11 @@ import pydantic
6
7
 
7
8
  from ...mixins import LoggerMixin
8
9
  from ...utils import T
9
- from .exceptions import ColumnInvalidTypeException, GenericColumnException
10
+ from .exceptions import (
11
+ ColumnInvalidTypeException,
12
+ ColumnNotSetException,
13
+ GenericColumnException,
14
+ )
10
15
 
11
16
  if typing.TYPE_CHECKING:
12
17
  from .model import GenericModel
@@ -45,7 +50,7 @@ class GenericColumn(typing.Generic[T], LoggerMixin):
45
50
  auto_increment (bool, optional): Whether the column is auto incremented. Only works if the column is a primary key. Defaults to False.
46
51
  unique (bool, optional): Whether the column is unique. Defaults to False.
47
52
  nullable (bool, optional): Whether the column is nullable. Defaults to True.
48
- default (T | collections.abc.Callable[[], T] | collections.abc.Callable[[GenericModel], T] | NoDefault, optional): The default value of the column. Will be used if the column is not set by the user. Defaults to NoDefault (no default value).
53
+ default (T | collections.abc.Callable[[], T] | collections.abc.Callable[[GenericModel], T] | NoDefault, optional): The default value of the column. Will be used if the column is not set by the user. It is resolved once, when the model is initialized: a callable taking no argument is called, and a mutable value is copied. Defaults to NoDefault (no default value).
49
54
  """
50
55
 
51
56
  col_type: type[T]
@@ -78,7 +83,7 @@ class GenericColumn(typing.Generic[T], LoggerMixin):
78
83
  auto_increment (bool, optional): Whether the column is auto incremented. Only works if the column is a primary key. Defaults to False.
79
84
  unique (bool, optional): Whether the column is unique. Defaults to False.
80
85
  nullable (bool, optional): Whether the column is nullable. Defaults to True.
81
- default (T | collections.abc.Callable[[], T] | collections.abc.Callable[["GenericModel"], T] | _NoDefaultValue, optional): The default value of the column. Will be used if the column is not set by the user. Defaults to UNSET (no default value).
86
+ default (T | collections.abc.Callable[[], T] | collections.abc.Callable[["GenericModel"], T] | _NoDefaultValue, optional): The default value of the column. Will be used if the column is not set by the user. It is resolved once, when the model is initialized: a callable taking no argument is called, and a mutable value is copied. Defaults to UNSET (no default value).
82
87
 
83
88
  Raises:
84
89
  GenericColumnException: If auto increment is set on a non-primary key column or if the column type is not int when auto increment is set.
@@ -95,10 +100,8 @@ class GenericColumn(typing.Generic[T], LoggerMixin):
95
100
  self.unique = True
96
101
  self.nullable = False
97
102
 
98
- if inspect.isfunction(self.default):
99
- # If the function takes no parameters, convert it to a function that needs the instance
100
- if inspect.signature(self.default).parameters == {}:
101
- self.default = lambda instance, func=self.default: func()
103
+ if self.default is not UNSET:
104
+ self.default = self._normalize_default(self.default)
102
105
 
103
106
  if not self.primary_key and self.auto_increment:
104
107
  raise GenericColumnException(
@@ -125,22 +128,30 @@ class GenericColumn(typing.Generic[T], LoggerMixin):
125
128
  instance: "GenericModel | None",
126
129
  owner: type["GenericModel"],
127
130
  ):
131
+ """
132
+ Read the column value of the instance, or the descriptor itself when read on the class.
133
+
134
+ Args:
135
+ instance (GenericModel | None): The instance to read from, or None when read on the class.
136
+ owner (type[GenericModel]): The model class owning the column.
137
+
138
+ Raises:
139
+ ColumnNotSetException: If a column that is neither nullable nor an auto incrementing primary key was never set.
140
+
141
+ Returns:
142
+ GenericColumn | T | None: The descriptor on class access, else the value, None for an unset nullable column, or PK_AUTO_INCREMENT for an unset auto incrementing primary key.
143
+ """
128
144
  if not instance:
129
145
  return self
130
146
 
131
- default_value = self.default
132
- if callable(default_value):
133
- default_value = default_value(instance)
134
-
135
- value: T | GenericUnset = instance.__dict__.get(
136
- f"_{self._col_name}", default_value
137
- )
147
+ value: T | GenericUnset = instance.__dict__.get(f"_{self._col_name}", UNSET)
138
148
 
139
- if value is default_value:
140
- if self.nullable and value is UNSET:
149
+ if value is UNSET:
150
+ if self.nullable:
141
151
  return None
142
- elif self.primary_key and self.auto_increment:
152
+ if self.primary_key and self.auto_increment:
143
153
  return PK_AUTO_INCREMENT
154
+ raise ColumnNotSetException(instance, f"Column {self._col_name} is not set")
144
155
 
145
156
  return value
146
157
 
@@ -161,7 +172,8 @@ class GenericColumn(typing.Generic[T], LoggerMixin):
161
172
  if self.nullable:
162
173
  validation_type = validation_type | None
163
174
  if self.default is not UNSET:
164
- validation_type = validation_type | type(self.default)
175
+ if not callable(self.default):
176
+ validation_type = validation_type | type(self.default)
165
177
  validation_field = pydantic.Field(default=self.default)
166
178
  else:
167
179
  validation_field = pydantic.Field
@@ -194,3 +206,60 @@ class GenericColumn(typing.Generic[T], LoggerMixin):
194
206
  f"_{self._col_name}" in instance.__dict__
195
207
  and getattr(instance, f"_{self._col_name}") is not UNSET
196
208
  )
209
+
210
+ def apply_default(self, instance: "GenericModel") -> None:
211
+ """
212
+ Write the column default into the instance, leaving an already set column untouched.
213
+
214
+ A default resolving to a sentinel is skipped, so a default reading a not yet assigned primary key leaves the column unset.
215
+
216
+ Args:
217
+ instance (GenericModel): The instance to write the default into.
218
+ """
219
+ if self.default is UNSET or self.is_column_set(instance):
220
+ return
221
+
222
+ value = self.default(instance) if callable(self.default) else self.default
223
+ if isinstance(value, (GenericUnset, GenericPKAutoIncrement)):
224
+ return
225
+
226
+ instance.__dict__[f"_{self._col_name}"] = value
227
+
228
+ def _normalize_default(
229
+ self,
230
+ default: T | collections.abc.Callable[..., T],
231
+ ) -> T | collections.abc.Callable[["GenericModel"], T]:
232
+ """
233
+ Normalize a column default into either a plain value or a callable taking the model instance.
234
+
235
+ A mutable value becomes a copying callable, so one instance cannot mutate the default of every other instance.
236
+
237
+ Args:
238
+ default (T | collections.abc.Callable[..., T]): The default given to the column.
239
+
240
+ Returns:
241
+ T | collections.abc.Callable[[GenericModel], T]: The value itself, or a callable taking the instance.
242
+ """
243
+ if not callable(default):
244
+ if isinstance(default, collections.abc.Hashable):
245
+ return default
246
+ return lambda instance, value=default: copy.deepcopy(value)
247
+
248
+ try:
249
+ parameters = inspect.signature(default).parameters.values()
250
+ except (TypeError, ValueError):
251
+ # A builtin without an introspectable signature (dict, str, ...) can only be a zero argument factory.
252
+ return lambda instance, func=default: func()
253
+
254
+ if any(
255
+ parameter.default is inspect.Parameter.empty
256
+ and parameter.kind
257
+ in (
258
+ inspect.Parameter.POSITIONAL_ONLY,
259
+ inspect.Parameter.POSITIONAL_OR_KEYWORD,
260
+ )
261
+ for parameter in parameters
262
+ ):
263
+ return default
264
+
265
+ return lambda instance, func=default: func()
@@ -117,15 +117,20 @@ class GenericModel(BasicModel):
117
117
  """
118
118
  Initialize the model with the given keyword arguments.
119
119
 
120
+ A column without a given value takes its default, like a dataclass mapped SQLAlchemy model does.
121
+
120
122
  Args:
121
123
  __check_on_init__ (bool, optional): Whether to check the model's validity on initialization. Defaults to True.
122
124
  """
123
- if not kwargs:
124
- return
125
125
  for key, value in kwargs.items():
126
126
  if key not in self.__mapper__.properties.keys():
127
127
  continue
128
128
  setattr(self, key, value)
129
+
130
+ # After the given values, so a default reading another column sees it.
131
+ for column in self.__mapper__.properties.values():
132
+ column.apply_default(self)
133
+
129
134
  if __check_on_init__:
130
135
  self.is_model_valid()
131
136
 
@@ -166,8 +171,10 @@ class GenericModel(BasicModel):
166
171
  """
167
172
  errors: list[Exception] = []
168
173
  for key in self.__mapper__.properties.keys():
169
- if getattr(self, key) is UNSET:
170
- errors.append(ColumnNotSetException(self, f"Column {key} is not set"))
174
+ try:
175
+ getattr(self, key)
176
+ except ColumnNotSetException as e:
177
+ errors.append(e)
171
178
 
172
179
  if errors:
173
180
  # Rollback to last valid state
@@ -186,4 +193,10 @@ class GenericModel(BasicModel):
186
193
  return [cls.__mapper__.pk]
187
194
 
188
195
  def __repr__(self):
189
- return f"{self.__class__.__name__}({';'.join([f'{col}={getattr(self, col)}' for col in self.__mapper__.properties.keys()])})"
196
+ values = []
197
+ for col in self.__mapper__.properties.keys():
198
+ try:
199
+ values.append(f"{col}={getattr(self, col)}")
200
+ except ColumnNotSetException:
201
+ values.append(f"{col}={UNSET}")
202
+ return f"{self.__class__.__name__}({';'.join(values)})"
@@ -1,4 +1,7 @@
1
+ import datetime
2
+
1
3
  import pytest
4
+
2
5
  from fastapi_rtk.backends.generic.column import (
3
6
  PK_AUTO_INCREMENT,
4
7
  UNSET,
@@ -8,6 +11,7 @@ from fastapi_rtk.backends.generic.column import (
8
11
  )
9
12
  from fastapi_rtk.backends.generic.exceptions import (
10
13
  ColumnInvalidTypeException,
14
+ ColumnNotSetException,
11
15
  GenericColumnException,
12
16
  )
13
17
  from fastapi_rtk.backends.generic.model import GenericModel
@@ -54,6 +58,28 @@ class TestColumnInit:
54
58
  col = GenericColumn(int, default=with_instance)
55
59
  assert col.default is with_instance
56
60
 
61
+ def test_default_hashable_value_kept_as_is(self):
62
+ col = GenericColumn(int, default=99)
63
+ assert col.default == 99
64
+
65
+ def test_default_builtin_with_optional_arg_wrapped(self):
66
+ col = GenericColumn(list, default=list)
67
+ assert col.default(None) == []
68
+
69
+ def test_default_builtin_without_signature_wrapped(self):
70
+ col = GenericColumn(dict, default=dict)
71
+ assert col.default(None) == {}
72
+
73
+ def test_default_builtin_method_wrapped(self):
74
+ col = GenericColumn(datetime.datetime, default=datetime.datetime.now)
75
+ assert isinstance(col.default(None), datetime.datetime)
76
+
77
+ def test_default_mutable_value_wrapped(self):
78
+ col = GenericColumn(list, default=[])
79
+ first = col.default(None)
80
+ assert first == []
81
+ assert first is not col.default(None)
82
+
57
83
 
58
84
  class TestColumnDescriptorAccess:
59
85
  def _make_model(self, **column_kwargs):
@@ -94,6 +120,12 @@ class TestColumnDescriptorAccess:
94
120
  m.x = 7
95
121
  assert m.x == 7
96
122
 
123
+ def test_get_unset_not_nullable_raises(self):
124
+ M = self._make_model(nullable=False)
125
+ m = M(__check_on_init__=False)
126
+ with pytest.raises(ColumnNotSetException, match="is not set"):
127
+ m.x
128
+
97
129
  def test_pk_auto_increment_returns_sentinel_when_not_set(self):
98
130
  M = self._make_model()
99
131
  m = M(__check_on_init__=False)
@@ -101,6 +133,40 @@ class TestColumnDescriptorAccess:
101
133
  assert m.id is PK_AUTO_INCREMENT
102
134
 
103
135
 
136
+ class TestMutableDefault:
137
+ def _make_model(self, **column_kwargs):
138
+ class M(GenericModel):
139
+ id = GenericColumn(int, primary_key=True, auto_increment=True)
140
+ x = GenericColumn(list, **column_kwargs)
141
+
142
+ return M
143
+
144
+ def test_mutation_does_not_leak_between_instances(self):
145
+ M = self._make_model(default=[])
146
+ first = M(__check_on_init__=False)
147
+ second = M(__check_on_init__=False)
148
+ first.x.append("leak")
149
+ assert second.x == []
150
+
151
+ def test_nested_mutation_does_not_leak_between_instances(self):
152
+ M = self._make_model(default=[[]])
153
+ first = M(__check_on_init__=False)
154
+ second = M(__check_on_init__=False)
155
+ first.x[0].append("leak")
156
+ assert second.x == [[]]
157
+
158
+ def test_builtin_factory_default_is_read(self):
159
+ M = self._make_model(default=list)
160
+ m = M(__check_on_init__=False)
161
+ assert m.x == []
162
+
163
+ def test_callable_default_rejected_as_value(self):
164
+ M = self._make_model(default=[])
165
+ m = M(__check_on_init__=False)
166
+ with pytest.raises(ColumnInvalidTypeException):
167
+ m.x = list
168
+
169
+
104
170
  class TestIsColumnSet:
105
171
  def test_unset_returns_false(self):
106
172
  class M(GenericModel):
@@ -120,6 +186,34 @@ class TestIsColumnSet:
120
186
  assert M.x.is_column_set(m) is True
121
187
 
122
188
 
189
+ class TestApplyDefault:
190
+ def _make_model(self, **column_kwargs):
191
+ class M(GenericModel):
192
+ id = GenericColumn(int, primary_key=True, auto_increment=True)
193
+ x = GenericColumn(int, **column_kwargs)
194
+
195
+ return M
196
+
197
+ def test_no_default_writes_nothing(self):
198
+ M = self._make_model()
199
+ m = M(__check_on_init__=False)
200
+ M.x.apply_default(m)
201
+ assert M.x.is_column_set(m) is False
202
+
203
+ def test_set_column_is_not_overwritten(self):
204
+ M = self._make_model(default=99)
205
+ m = M(__check_on_init__=False)
206
+ m.x = 1
207
+ M.x.apply_default(m)
208
+ assert m.x == 1
209
+
210
+ def test_sentinel_result_is_not_written(self):
211
+ M = self._make_model(default=lambda instance: instance.id)
212
+ m = M(__check_on_init__=False)
213
+ M.x.apply_default(m)
214
+ assert M.x.is_column_set(m) is False
215
+
216
+
123
217
  class TestRepr:
124
218
  def test_repr_includes_attrs(self):
125
219
  col = GenericColumn(int, primary_key=True)
@@ -1,3 +1,5 @@
1
+ import datetime
2
+
1
3
  import pytest
2
4
  from fastapi_rtk.backends.generic.column import GenericColumn
3
5
  from fastapi_rtk.backends.generic.exceptions import (
@@ -73,10 +75,83 @@ class TestModelInit:
73
75
 
74
76
  return M
75
77
 
76
- def test_empty_kwargs_no_validation(self):
77
- M = self._model()
78
- m = M() # bypass validation entirely
79
- assert m is not None
78
+ def test_empty_kwargs_still_validates(self):
79
+ class M(GenericModel):
80
+ id = GenericColumn(int, primary_key=True)
81
+ required = GenericColumn(str, nullable=False)
82
+
83
+ with pytest.raises(MultipleColumnsException):
84
+ M()
85
+
86
+ def test_default_applied_on_init(self):
87
+ class M(GenericModel):
88
+ id = GenericColumn(int, primary_key=True, auto_increment=True)
89
+ name = GenericColumn(str, nullable=False, default="anon")
90
+
91
+ m = M()
92
+ assert m.name == "anon"
93
+ assert M.name.is_column_set(m) is True
94
+
95
+ def test_default_not_applied_when_value_given(self):
96
+ class M(GenericModel):
97
+ id = GenericColumn(int, primary_key=True, auto_increment=True)
98
+ name = GenericColumn(str, nullable=False, default="anon")
99
+
100
+ assert M(name="given").name == "given"
101
+
102
+ def test_callable_default_frozen_on_init(self):
103
+ class M(GenericModel):
104
+ id = GenericColumn(int, primary_key=True, auto_increment=True)
105
+ created = GenericColumn(datetime.datetime, default=datetime.datetime.now)
106
+
107
+ m = M()
108
+ assert m.created == m.created
109
+
110
+ def test_mutable_default_persists_mutation_per_instance(self):
111
+ class M(GenericModel):
112
+ id = GenericColumn(int, primary_key=True, auto_increment=True)
113
+ tags = GenericColumn(list, default=[])
114
+
115
+ m = M()
116
+ m.tags.append("x")
117
+ assert m.tags == ["x"]
118
+ assert M().tags == []
119
+
120
+ def test_default_reads_column_given_in_kwargs(self):
121
+ class M(GenericModel):
122
+ id = GenericColumn(int, primary_key=True, auto_increment=True)
123
+ first = GenericColumn(str, nullable=False)
124
+ slug = GenericColumn(str, default=lambda instance: instance.first.lower())
125
+
126
+ assert M(first="Ada").slug == "ada"
127
+
128
+ def test_default_reads_column_defaulted_earlier_in_class_body(self):
129
+ class M(GenericModel):
130
+ id = GenericColumn(int, primary_key=True, auto_increment=True)
131
+ first = GenericColumn(str, nullable=False, default="Ada")
132
+ slug = GenericColumn(str, default=lambda instance: instance.first.lower())
133
+
134
+ assert M().slug == "ada"
135
+
136
+ def test_default_reading_unassigned_pk_leaves_column_unset(self):
137
+ class M(GenericModel):
138
+ id = GenericColumn(int, primary_key=True, auto_increment=True)
139
+ from_pk = GenericColumn(int, default=lambda instance: instance.id)
140
+
141
+ m = M()
142
+ assert M.from_pk.is_column_set(m) is False
143
+ assert m.from_pk is None
144
+ m.id = 5
145
+ assert m.from_pk is None
146
+
147
+ def test_default_is_not_reapplied_after_init(self):
148
+ class M(GenericModel):
149
+ id = GenericColumn(int, primary_key=True, auto_increment=True)
150
+ name = GenericColumn(str, default="anon")
151
+
152
+ m = M()
153
+ del m.__dict__["_name"]
154
+ assert m.name is None
80
155
 
81
156
  def test_kwargs_unknown_keys_skipped(self):
82
157
  M = self._model()
@@ -1 +0,0 @@
1
- __version__ = "2.12.4"
File without changes
File without changes
File without changes