fastapi-rtk 2.3.5__tar.gz → 2.4.1__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.3.5 → fastapi_rtk-2.4.1}/PKG-INFO +1 -1
  2. fastapi_rtk-2.4.1/fastapi_rtk/_version.py +1 -0
  3. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/api/model_rest_api/__init__.py +56 -0
  4. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/api/model_rest_api/_columns_mixin.py +27 -4
  5. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/api/model_rest_api/_info_mixin.py +5 -1
  6. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/api/model_rest_api/_typed_base.py +37 -0
  7. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/api/model_rest_api/test_columns.py +67 -4
  8. fastapi_rtk-2.3.5/fastapi_rtk/_version.py +0 -1
  9. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/.gitignore +0 -0
  10. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/LICENSE +0 -0
  11. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/README.md +0 -0
  12. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/__init__.py +0 -0
  13. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/api/__init__.py +0 -0
  14. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/api/base_api.py +0 -0
  15. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/api/model_rest_api/_add_mixin.py +0 -0
  16. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/api/model_rest_api/_bulk_mixin.py +0 -0
  17. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/api/model_rest_api/_delete_mixin.py +0 -0
  18. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/api/model_rest_api/_download_mixin.py +0 -0
  19. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/api/model_rest_api/_edit_mixin.py +0 -0
  20. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/api/model_rest_api/_file_mixin.py +0 -0
  21. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/api/model_rest_api/_list_mixin.py +0 -0
  22. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/api/model_rest_api/_params.py +0 -0
  23. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/api/model_rest_api/_show_mixin.py +0 -0
  24. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/api/model_rest_api/_upload_mixin.py +0 -0
  25. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/apis/__init__.py +0 -0
  26. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/apis/info.py +0 -0
  27. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/apis/license.py +0 -0
  28. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/auth/__init__.py +0 -0
  29. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/auth/auth.py +0 -0
  30. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/auth/hashers/__init__.py +0 -0
  31. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/auth/hashers/pbkdf2.py +0 -0
  32. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/auth/hashers/scrypt.py +0 -0
  33. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/auth/ldap.py +0 -0
  34. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/auth/password_helpers/__init__.py +0 -0
  35. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/auth/password_helpers/fab.py +0 -0
  36. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/auth/strategies/__init__.py +0 -0
  37. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/auth/strategies/config.py +0 -0
  38. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/auth/strategies/db.py +0 -0
  39. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/auth/strategies/jwt.py +0 -0
  40. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/__init__.py +0 -0
  41. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/generic/__init__.py +0 -0
  42. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/generic/column.py +0 -0
  43. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/generic/db.py +0 -0
  44. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/generic/exceptions.py +0 -0
  45. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/generic/filters.py +0 -0
  46. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/generic/interface.py +0 -0
  47. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/generic/model.py +0 -0
  48. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/generic/session.py +0 -0
  49. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/sqla/__init__.py +0 -0
  50. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/sqla/column.py +0 -0
  51. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/sqla/db.py +0 -0
  52. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/sqla/exceptions.py +0 -0
  53. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/sqla/extensions/__init__.py +0 -0
  54. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/sqla/extensions/audit/__init__.py +0 -0
  55. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/sqla/extensions/audit/_decorators_mixin.py +0 -0
  56. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/sqla/extensions/audit/_lifecycle_mixin.py +0 -0
  57. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/sqla/extensions/audit/_logger.py +0 -0
  58. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/sqla/extensions/audit/_processing_mixin.py +0 -0
  59. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/sqla/extensions/audit/audit.py +0 -0
  60. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/sqla/extensions/audit/types.py +0 -0
  61. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/__init__.py +0 -0
  62. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/filters.py +0 -0
  63. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/geometry_converter.py +0 -0
  64. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/sqla/filters.py +0 -0
  65. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/sqla/interface.py +0 -0
  66. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/sqla/model.py +0 -0
  67. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/backends/sqla/session.py +0 -0
  68. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/bases/__init__.py +0 -0
  69. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/bases/db.py +0 -0
  70. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/bases/file_manager.py +0 -0
  71. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/bases/filter.py +0 -0
  72. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/bases/interface.py +0 -0
  73. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/bases/model.py +0 -0
  74. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/bases/session.py +0 -0
  75. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/cli/__init__.py +0 -0
  76. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/cli/cli.py +0 -0
  77. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/cli/commands/__init__.py +0 -0
  78. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/cli/commands/_security_crypto.py +0 -0
  79. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/cli/commands/db/__init__.py +0 -0
  80. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/cli/commands/db/templates/fastapi/README +0 -0
  81. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/cli/commands/db/templates/fastapi/alembic.ini.mako +0 -0
  82. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/cli/commands/db/templates/fastapi/env.py +0 -0
  83. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/cli/commands/db/templates/fastapi/script.py.mako +0 -0
  84. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/README +0 -0
  85. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/alembic.ini.mako +0 -0
  86. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/env.py +0 -0
  87. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/script.py.mako +0 -0
  88. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/cli/commands/export.py +0 -0
  89. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/cli/commands/security.py +0 -0
  90. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/cli/commands/translate.py +0 -0
  91. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/cli/const.py +0 -0
  92. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/cli/decorators.py +0 -0
  93. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/cli/types.py +0 -0
  94. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/cli/utils.py +0 -0
  95. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/config.py +0 -0
  96. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/const.py +0 -0
  97. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/db.py +0 -0
  98. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/decorators.py +0 -0
  99. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/dependencies.py +0 -0
  100. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/exceptions.py +0 -0
  101. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/fastapi_react_toolkit.py +0 -0
  102. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/file_managers/__init__.py +0 -0
  103. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/file_managers/file_manager.py +0 -0
  104. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/file_managers/image_manager.py +0 -0
  105. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/file_managers/s3_file_manager.py +0 -0
  106. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/file_managers/s3_image_manager.py +0 -0
  107. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/filters.py +0 -0
  108. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/globals.py +0 -0
  109. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/lang/__init__.py +0 -0
  110. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/lang/babel/__init__.py +0 -0
  111. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/lang/babel/cli.py +0 -0
  112. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/lang/babel/config.py +0 -0
  113. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/lang/babel.cfg +0 -0
  114. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/lang/lazy_text.py +0 -0
  115. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/lang/messages.pot +0 -0
  116. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.mo +0 -0
  117. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.po +0 -0
  118. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.mo +0 -0
  119. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.po +0 -0
  120. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/manager.py +0 -0
  121. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/middlewares.py +0 -0
  122. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/mixins.py +0 -0
  123. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/models.py +0 -0
  124. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/py.typed +0 -0
  125. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/registry.py +0 -0
  126. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/routers.py +0 -0
  127. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/schemas.py +0 -0
  128. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/security/__init__.py +0 -0
  129. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/security/sqla/__init__.py +0 -0
  130. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/security/sqla/apis.py +0 -0
  131. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/security/sqla/models.py +0 -0
  132. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/security/sqla/security_manager/__init__.py +0 -0
  133. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/security/sqla/security_manager/_association_mixin.py +0 -0
  134. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/security/sqla/security_manager/_builtin_role_mixin.py +0 -0
  135. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/security/sqla/security_manager/_cleanup_mixin.py +0 -0
  136. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/security/sqla/security_manager/_exception_filters.py +0 -0
  137. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/security/sqla/security_manager/_export.py +0 -0
  138. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/security/sqla/security_manager/_import.py +0 -0
  139. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/security/sqla/security_manager/_role_mixin.py +0 -0
  140. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/security/sqla/security_manager/_user_mixin.py +0 -0
  141. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/setting.py +0 -0
  142. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/types.py +0 -0
  143. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/utils/__init__.py +0 -0
  144. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/utils/async_task_runner.py +0 -0
  145. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/utils/class_factory.py +0 -0
  146. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/utils/csv_json_converter.py +0 -0
  147. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/utils/deep_merge.py +0 -0
  148. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/utils/extender_mixin.py +0 -0
  149. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/utils/flask_appbuilder_utils.py +0 -0
  150. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/utils/formatter.py +0 -0
  151. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/utils/hooks.py +0 -0
  152. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/utils/lazy.py +0 -0
  153. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/utils/merge_schema.py +0 -0
  154. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/utils/multiple_async_contexts.py +0 -0
  155. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/utils/pydantic.py +0 -0
  156. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/utils/run_utils.py +0 -0
  157. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/utils/self_dependencies.py +0 -0
  158. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/utils/smartdefaultdict.py +0 -0
  159. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/utils/sqla.py +0 -0
  160. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/utils/timezone.py +0 -0
  161. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/utils/update_signature.py +0 -0
  162. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/utils/use_default_when_none.py +0 -0
  163. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/fastapi_rtk/version.py +0 -0
  164. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/pyproject.toml +0 -0
  165. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/conftest.py +0 -0
  166. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/docker-compose.gis.yml +0 -0
  167. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/integration/__init__.py +0 -0
  168. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/integration/api/__init__.py +0 -0
  169. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/integration/api/test_model_rest_api.py +0 -0
  170. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/integration/apis/__init__.py +0 -0
  171. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/integration/apis/test_info_callable_schema.py +0 -0
  172. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/integration/apis/test_info_contract.py +0 -0
  173. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/integration/auth/__init__.py +0 -0
  174. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/integration/auth/test_auth_flow.py +0 -0
  175. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/integration/auth/test_oauth.py +0 -0
  176. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/integration/conftest.py +0 -0
  177. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/integration/file_managers/__init__.py +0 -0
  178. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/integration/file_managers/test_file_routes.py +0 -0
  179. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/integration/security/__init__.py +0 -0
  180. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/integration/security/sqla/__init__.py +0 -0
  181. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/integration/security/sqla/test_security_manager.py +0 -0
  182. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/integration/test_app_smoke.py +0 -0
  183. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/__init__.py +0 -0
  184. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/api/__init__.py +0 -0
  185. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/api/conftest.py +0 -0
  186. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/api/model_rest_api/__init__.py +0 -0
  187. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/api/model_rest_api/test_file_mixin.py +0 -0
  188. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/api/model_rest_api/test_init.py +0 -0
  189. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/api/model_rest_api/test_typed_base_consistency.py +0 -0
  190. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/api/test_base_api.py +0 -0
  191. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/apis/__init__.py +0 -0
  192. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/apis/test_info.py +0 -0
  193. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/apis/test_license.py +0 -0
  194. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/auth/__init__.py +0 -0
  195. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/auth/hashers/__init__.py +0 -0
  196. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/auth/hashers/test_pbkdf2.py +0 -0
  197. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/auth/hashers/test_scrypt.py +0 -0
  198. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/auth/password_helpers/__init__.py +0 -0
  199. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/auth/password_helpers/test_fab.py +0 -0
  200. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/auth/strategies/__init__.py +0 -0
  201. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/auth/strategies/test_config.py +0 -0
  202. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/auth/strategies/test_db.py +0 -0
  203. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/auth/strategies/test_jwt.py +0 -0
  204. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/auth/test_auth.py +0 -0
  205. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/backends/__init__.py +0 -0
  206. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/backends/generic/__init__.py +0 -0
  207. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/backends/generic/test_column.py +0 -0
  208. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/backends/generic/test_db.py +0 -0
  209. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/backends/generic/test_exceptions.py +0 -0
  210. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/backends/generic/test_filters.py +0 -0
  211. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/backends/generic/test_interface.py +0 -0
  212. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/backends/generic/test_model.py +0 -0
  213. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/backends/generic/test_session.py +0 -0
  214. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/backends/sqla/__init__.py +0 -0
  215. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/backends/sqla/conftest.py +0 -0
  216. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/backends/sqla/test_audit.py +0 -0
  217. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/backends/sqla/test_audit_types.py +0 -0
  218. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/backends/sqla/test_column.py +0 -0
  219. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/backends/sqla/test_db.py +0 -0
  220. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/backends/sqla/test_filters.py +0 -0
  221. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/backends/sqla/test_geoalchemy2.py +0 -0
  222. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/backends/sqla/test_interface.py +0 -0
  223. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/backends/sqla/test_model.py +0 -0
  224. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/backends/sqla/test_session.py +0 -0
  225. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/bases/__init__.py +0 -0
  226. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/bases/test_db.py +0 -0
  227. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/bases/test_file_manager.py +0 -0
  228. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/bases/test_filter.py +0 -0
  229. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/bases/test_interface.py +0 -0
  230. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/bases/test_model.py +0 -0
  231. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/bases/test_session.py +0 -0
  232. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/cli/__init__.py +0 -0
  233. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/cli/commands/__init__.py +0 -0
  234. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/cli/commands/conftest.py +0 -0
  235. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/cli/commands/test_db.py +0 -0
  236. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/cli/commands/test_export.py +0 -0
  237. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/cli/commands/test_security.py +0 -0
  238. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/cli/commands/test_security_crypto.py +0 -0
  239. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/cli/commands/test_translate.py +0 -0
  240. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/cli/conftest.py +0 -0
  241. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/cli/test_cli.py +0 -0
  242. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/cli/test_decorators.py +0 -0
  243. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/cli/test_types.py +0 -0
  244. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/cli/test_utils.py +0 -0
  245. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/file_managers/__init__.py +0 -0
  246. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/file_managers/conftest.py +0 -0
  247. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/file_managers/test_file_manager.py +0 -0
  248. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/file_managers/test_image_manager.py +0 -0
  249. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/file_managers/test_s3_file_manager.py +0 -0
  250. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/file_managers/test_s3_image_manager.py +0 -0
  251. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/lang/__init__.py +0 -0
  252. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/lang/test_babel_cli.py +0 -0
  253. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/lang/test_babel_config.py +0 -0
  254. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/lang/test_lazy_text.py +0 -0
  255. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/security/__init__.py +0 -0
  256. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/security/sqla/__init__.py +0 -0
  257. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/security/sqla/conftest.py +0 -0
  258. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/security/sqla/test_apis.py +0 -0
  259. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/security/sqla/test_models.py +0 -0
  260. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/security/sqla/test_security_manager.py +0 -0
  261. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/test_config.py +0 -0
  262. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/test_const.py +0 -0
  263. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/test_db.py +0 -0
  264. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/test_decorators.py +0 -0
  265. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/test_dependencies.py +0 -0
  266. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/test_exceptions.py +0 -0
  267. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/test_fastapi_react_toolkit.py +0 -0
  268. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/test_filters.py +0 -0
  269. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/test_globals.py +0 -0
  270. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/test_manager.py +0 -0
  271. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/test_middlewares.py +0 -0
  272. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/test_mixins.py +0 -0
  273. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/test_models.py +0 -0
  274. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/test_registry.py +0 -0
  275. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/test_routers.py +0 -0
  276. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/test_schemas.py +0 -0
  277. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/test_setting.py +0 -0
  278. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/test_types.py +0 -0
  279. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/test_version.py +0 -0
  280. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/utils/__init__.py +0 -0
  281. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/utils/test_async_task_runner.py +0 -0
  282. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/utils/test_class_factory.py +0 -0
  283. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/utils/test_csv_json_converter.py +0 -0
  284. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/utils/test_deep_merge.py +0 -0
  285. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/utils/test_extender_mixin.py +0 -0
  286. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/utils/test_flask_appbuilder_utils.py +0 -0
  287. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/utils/test_formatter.py +0 -0
  288. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/utils/test_hooks.py +0 -0
  289. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/utils/test_lazy.py +0 -0
  290. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/utils/test_merge_schema.py +0 -0
  291. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/utils/test_multiple_async_contexts.py +0 -0
  292. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/utils/test_pydantic.py +0 -0
  293. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/utils/test_run_utils.py +0 -0
  294. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/utils/test_self_dependencies.py +0 -0
  295. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/utils/test_smartdefaultdict.py +0 -0
  296. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/utils/test_sqla.py +0 -0
  297. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/utils/test_timezone.py +0 -0
  298. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/utils/test_update_signature.py +0 -0
  299. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/tests/unit/utils/test_use_default_when_none.py +0 -0
  300. {fastapi_rtk-2.3.5 → fastapi_rtk-2.4.1}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-rtk
3
- Version: 2.3.5
3
+ Version: 2.4.1
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.4.1"
@@ -705,6 +705,34 @@ class ModelRestApi(
705
705
 
706
706
  A workaround for issue https://github.com/eclipsesource/jsonforms/issues/2271
707
707
  """
708
+ add_jsonforms_list_as_object: (
709
+ bool
710
+ | collections.abc.Callable[
711
+ [ColumnInfo | ColumnEnumInfo | ColumnRelationInfo | None], bool
712
+ ]
713
+ | dict[
714
+ str,
715
+ bool
716
+ | collections.abc.Callable[
717
+ [ColumnInfo | ColumnEnumInfo | ColumnRelationInfo | None], bool
718
+ ],
719
+ ]
720
+ ) = False
721
+ """
722
+ A flag or a callable or a dictionary to determine whether a list column (e.g. `ListColumn` / `JSONBListColumn`) is rendered as a single `object` control in the JSONForms schema for the add endpoint, instead of the default per-item `array` table. The callable receives the column's `ColumnInfo` when available, else `None`. Defaults to False (array).
723
+
724
+ Use this when a per-field `component` override should receive the whole list value once, rather than being re-applied per array item.
725
+
726
+ Example:
727
+ ```python
728
+ # Can be a simple boolean (applies to every list column)
729
+ add_jsonforms_list_as_object = True
730
+ # Can be a callable that takes the column info and returns a boolean
731
+ add_jsonforms_list_as_object = lambda info: info.name == "tags"
732
+ # Can be a dictionary that maps column names to booleans or callables
733
+ add_jsonforms_list_as_object = {"tags": True}
734
+ ```
735
+ """
708
736
 
709
737
  edit_jsonforms_schema: (
710
738
  dict[str, typing.Any]
@@ -755,6 +783,34 @@ class ModelRestApi(
755
783
 
756
784
  A workaround for issue https://github.com/eclipsesource/jsonforms/issues/2271
757
785
  """
786
+ edit_jsonforms_list_as_object: (
787
+ bool
788
+ | collections.abc.Callable[
789
+ [ColumnInfo | ColumnEnumInfo | ColumnRelationInfo | None], bool
790
+ ]
791
+ | dict[
792
+ str,
793
+ bool
794
+ | collections.abc.Callable[
795
+ [ColumnInfo | ColumnEnumInfo | ColumnRelationInfo | None], bool
796
+ ],
797
+ ]
798
+ ) = False
799
+ """
800
+ A flag or a callable or a dictionary to determine whether a list column (e.g. `ListColumn` / `JSONBListColumn`) is rendered as a single `object` control in the JSONForms schema for the edit endpoint, instead of the default per-item `array` table. The callable receives the column's `ColumnInfo` when available, else `None`. Defaults to False (array).
801
+
802
+ Use this when a per-field `component` override should receive the whole list value once, rather than being re-applied per array item.
803
+
804
+ Example:
805
+ ```python
806
+ # Can be a simple boolean (applies to every list column)
807
+ edit_jsonforms_list_as_object = True
808
+ # Can be a callable that takes the column info and returns a boolean
809
+ edit_jsonforms_list_as_object = lambda info: info.name == "tags"
810
+ # Can be a dictionary that maps column names to booleans or callables
811
+ edit_jsonforms_list_as_object = {"tags": True}
812
+ ```
813
+ """
758
814
 
759
815
  """
760
816
  -------------
@@ -247,8 +247,8 @@ class ColumnsMixin(_TypedModelRestApi):
247
247
  name or new_schema_name,
248
248
  **rel_schema,
249
249
  __base__=schema,
250
+ __config__=pydantic.ConfigDict(extra="forbid"),
250
251
  )
251
- new_schema.model_config["extra"] = "forbid"
252
252
  return new_schema
253
253
 
254
254
  async def _process_body(
@@ -535,6 +535,17 @@ class ColumnsMixin(_TypedModelRestApi):
535
535
  [ColumnInfo | ColumnEnumInfo | ColumnRelationInfo], bool
536
536
  ],
537
537
  ] = False,
538
+ list_as_object: bool
539
+ | collections.abc.Callable[
540
+ [ColumnInfo | ColumnEnumInfo | ColumnRelationInfo | None], bool
541
+ ]
542
+ | dict[
543
+ str,
544
+ bool
545
+ | collections.abc.Callable[
546
+ [ColumnInfo | ColumnEnumInfo | ColumnRelationInfo | None], bool
547
+ ],
548
+ ] = False,
538
549
  ):
539
550
  """
540
551
  Generate the JSONForms schema for the API.
@@ -543,6 +554,7 @@ class ColumnsMixin(_TypedModelRestApi):
543
554
  schema (type[BaseModel]): The schema to generate the JSONForms schema from.
544
555
  info_columns (list[ColumnInfo | ColumnEnumInfo | ColumnRelationInfo]): The list of columns to include in the JSONForms schema.
545
556
  use_enum (bool | Callable[[ColumnInfo | ColumnEnumInfo | ColumnRelationInfo], bool] | dict[str, bool | Callable[[ColumnInfo | ColumnEnumInfo | ColumnRelationInfo], bool]], optional): A flag or a callable or a dictionary to determine whether to use enum instead of oneOf. Defaults to False.
557
+ list_as_object (bool | Callable[[ColumnInfo | ColumnEnumInfo | ColumnRelationInfo | None], bool] | dict[str, bool | Callable[[ColumnInfo | ColumnEnumInfo | ColumnRelationInfo | None], bool]], optional): A flag or a callable or a dictionary to determine whether to render a list column as a single `object` control instead of the per-item `array` table. The callable receives the column's `ColumnInfo` when available, else `None`. Defaults to False.
546
558
 
547
559
  Returns:
548
560
  dict[str, typing.Any]: The generated JSONForms schema.
@@ -595,10 +607,21 @@ class ColumnsMixin(_TypedModelRestApi):
595
607
  enum_val = [str(item.value) for item in enum_val]
596
608
  value["enum"] = enum_val
597
609
  elif self.datamodel.is_list(key):
598
- value["type"] = "array"
599
- value["items"] = self._jsonforms_list_items_schema(
600
- self.datamodel.get_list_col_type(key)
610
+ col_list_as_object = list_as_object
611
+ if isinstance(col_list_as_object, dict):
612
+ col_list_as_object = col_list_as_object.get(key, False)
613
+ list_info = next((x for x in info_columns if x.name == key), None)
614
+ col_list_as_object = parse_from_values_or_func(
615
+ col_list_as_object, list_info
601
616
  )
617
+ if col_list_as_object:
618
+ value["type"] = "object"
619
+ value.pop("items", None)
620
+ else:
621
+ value["type"] = "array"
622
+ value["items"] = self._jsonforms_list_items_schema(
623
+ self.datamodel.get_list_col_type(key)
624
+ )
602
625
  elif self.datamodel.is_json(key) or self.datamodel.is_jsonb(key):
603
626
  value["type"] = "object"
604
627
  elif self.datamodel.is_relation(key):
@@ -146,7 +146,10 @@ class InfoMixin(_TypedModelRestApi):
146
146
  if callable(add_jsonforms_schema):
147
147
  add_jsonforms_schema = await smart_run(add_jsonforms_schema)
148
148
  schema.add_schema = add_jsonforms_schema or self._generate_jsonforms_schema(
149
- self.add_obj_schema, schema.add_columns, self.add_jsonforms_use_enum
149
+ self.add_obj_schema,
150
+ schema.add_columns,
151
+ self.add_jsonforms_use_enum,
152
+ self.add_jsonforms_list_as_object,
150
153
  )
151
154
  schema.add_uischema = self.add_jsonforms_uischema
152
155
 
@@ -190,6 +193,7 @@ class InfoMixin(_TypedModelRestApi):
190
193
  self.edit_obj_schema,
191
194
  schema.edit_columns,
192
195
  self.edit_jsonforms_use_enum,
196
+ self.edit_jsonforms_list_as_object,
193
197
  )
194
198
  )
195
199
  schema.edit_uischema = self.edit_jsonforms_uischema
@@ -100,6 +100,19 @@ class _TypedModelRestApi:
100
100
  ],
101
101
  ]
102
102
  )
103
+ add_jsonforms_list_as_object: (
104
+ bool
105
+ | collections.abc.Callable[
106
+ [ColumnInfo | ColumnEnumInfo | ColumnRelationInfo | None], bool
107
+ ]
108
+ | dict[
109
+ str,
110
+ bool
111
+ | collections.abc.Callable[
112
+ [ColumnInfo | ColumnEnumInfo | ColumnRelationInfo | None], bool
113
+ ],
114
+ ]
115
+ )
103
116
  add_jsonforms_uischema: dict[str, typing.Any] | None
104
117
 
105
118
  # -- edit --
@@ -129,6 +142,19 @@ class _TypedModelRestApi:
129
142
  ],
130
143
  ]
131
144
  )
145
+ edit_jsonforms_list_as_object: (
146
+ bool
147
+ | collections.abc.Callable[
148
+ [ColumnInfo | ColumnEnumInfo | ColumnRelationInfo | None], bool
149
+ ]
150
+ | dict[
151
+ str,
152
+ bool
153
+ | collections.abc.Callable[
154
+ [ColumnInfo | ColumnEnumInfo | ColumnRelationInfo | None], bool
155
+ ],
156
+ ]
157
+ )
132
158
  edit_jsonforms_uischema: dict[str, typing.Any] | None
133
159
 
134
160
  # -- search --
@@ -167,6 +193,17 @@ class _TypedModelRestApi:
167
193
  [ColumnInfo | ColumnEnumInfo | ColumnRelationInfo], bool
168
194
  ],
169
195
  ] = False,
196
+ list_as_object: bool
197
+ | collections.abc.Callable[
198
+ [ColumnInfo | ColumnEnumInfo | ColumnRelationInfo | None], bool
199
+ ]
200
+ | dict[
201
+ str,
202
+ bool
203
+ | collections.abc.Callable[
204
+ [ColumnInfo | ColumnEnumInfo | ColumnRelationInfo | None], bool
205
+ ],
206
+ ] = False,
170
207
  ) -> dict[str, typing.Any]: ...
171
208
 
172
209
  def _get_datamodel_and_column(self, col: str) -> tuple[SQLAInterface, str]: ...
@@ -10,7 +10,6 @@ import typing
10
10
 
11
11
  import pydantic
12
12
  import pytest
13
-
14
13
  from fastapi_rtk.api.model_rest_api import ModelRestApi
15
14
  from fastapi_rtk.backends.sqla.interface import SQLAInterface
16
15
 
@@ -120,7 +119,6 @@ class TestGetDatamodelAndColumn:
120
119
  @pytest.fixture
121
120
  def Country_cls():
122
121
  import sqlalchemy
123
-
124
122
  from fastapi_rtk.backends.sqla.model import Model
125
123
 
126
124
  if "tier12_country" in Model.metadata.tables:
@@ -139,7 +137,6 @@ def Country_cls():
139
137
  @pytest.fixture
140
138
  def WidgetWithCountry_cls(Country_cls):
141
139
  import sqlalchemy.orm
142
-
143
140
  from fastapi_rtk.backends.sqla.model import Model
144
141
 
145
142
  if "tier12_widget_country" in Model.metadata.tables:
@@ -227,6 +224,40 @@ class TestSchemaExtraFieldsColumnCollision:
227
224
  Api()
228
225
 
229
226
 
227
+ class TestCreateRequestSchemaForbidsExtra:
228
+ """``_create_request_schema`` must bake ``extra="forbid"`` into the model's
229
+ validation core (not merely set ``model_config["extra"]``, a no-op on an
230
+ already-built model until a rebuild) while preserving the base schema's
231
+ own config.
232
+ """
233
+
234
+ def test_standalone_schema_rejects_unknown_field(self, Widget_cls):
235
+ class Api(ModelRestApi):
236
+ datamodel = SQLAInterface(Widget_cls)
237
+
238
+ api = Api()
239
+ request_schema = api._create_request_schema(api.add_obj_schema)
240
+ with pytest.raises(pydantic.ValidationError):
241
+ request_schema.model_validate({"name": "ok", "totally_unknown": "x"})
242
+
243
+ def test_carries_base_config_plus_forbid(self, Widget_cls):
244
+ class Api(ModelRestApi):
245
+ datamodel = SQLAInterface(Widget_cls)
246
+
247
+ class CustomBase(pydantic.BaseModel):
248
+ model_config = pydantic.ConfigDict(str_strip_whitespace=True)
249
+ name: str
250
+
251
+ request_schema = Api()._create_request_schema(CustomBase, name="CustomReq")
252
+ # Base config carried through AND `extra=forbid` added, both baked into
253
+ # the validation core: whitespace stripped (base) + extras rejected.
254
+ assert request_schema.model_config.get("str_strip_whitespace") is True
255
+ assert request_schema.model_config.get("extra") == "forbid"
256
+ assert request_schema.model_validate({"name": " x "}).name == "x"
257
+ with pytest.raises(pydantic.ValidationError):
258
+ request_schema.model_validate({"name": "x", "nope": 1})
259
+
260
+
230
261
  class TestJsonformsListItemsSchema:
231
262
  @pytest.mark.parametrize(
232
263
  "col_type,expected",
@@ -251,7 +282,6 @@ class TestGenerateJsonformsSchemaListBranch:
251
282
  @pytest.fixture(scope="class")
252
283
  def list_api(self):
253
284
  import sqlalchemy
254
-
255
285
  from fastapi_rtk import (
256
286
  JSONBListColumn,
257
287
  ListColumn,
@@ -313,3 +343,36 @@ class TestGenerateJsonformsSchemaListBranch:
313
343
  result = list_api._generate_jsonforms_schema(schema, [], False)
314
344
  # Plain `sqlalchemy.JSON` (not a ListColumn) keeps the original behavior.
315
345
  assert result["properties"]["payload"]["type"] == ["object", "null"]
346
+
347
+ def test_list_as_object_bool_true(self, list_api):
348
+ schema = list_api.add_obj_schema
349
+ result = list_api._generate_jsonforms_schema(
350
+ schema, [], False, list_as_object=True
351
+ )
352
+ assert result["properties"]["tags"]["type"] == ["object", "null"]
353
+ assert "items" not in result["properties"]["tags"]
354
+
355
+ def test_list_as_object_dict_targets_one_column(self, list_api):
356
+ schema = list_api.add_obj_schema
357
+ result = list_api._generate_jsonforms_schema(
358
+ schema, [], False, list_as_object={"tags": True}
359
+ )
360
+ assert result["properties"]["tags"]["type"] == ["object", "null"]
361
+ assert "items" not in result["properties"]["tags"]
362
+ # A column absent from the dict keeps the array rendering.
363
+ assert result["properties"]["nums"]["type"] == ["array", "null"]
364
+ assert result["properties"]["nums"]["items"] == {"type": "integer"}
365
+
366
+ def test_list_as_object_callable(self, list_api):
367
+ schema = list_api.add_obj_schema
368
+ result = list_api._generate_jsonforms_schema(
369
+ schema, [], False, list_as_object=lambda info: True
370
+ )
371
+ assert result["properties"]["tags"]["type"] == ["object", "null"]
372
+ assert "items" not in result["properties"]["tags"]
373
+
374
+ def test_list_as_object_default_keeps_array(self, list_api):
375
+ schema = list_api.add_obj_schema
376
+ result = list_api._generate_jsonforms_schema(schema, [], False)
377
+ assert result["properties"]["tags"]["type"] == ["array", "null"]
378
+ assert result["properties"]["tags"]["items"] == {"type": "string"}
@@ -1 +0,0 @@
1
- __version__ = "2.3.5"
File without changes
File without changes
File without changes