GeneralManager 0.60.6__tar.gz → 0.62.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 (280) hide show
  1. {generalmanager-0.60.6/src/GeneralManager.egg-info → generalmanager-0.62.0}/PKG-INFO +6 -1
  2. {generalmanager-0.60.6 → generalmanager-0.62.0}/pyproject.toml +3 -1
  3. {generalmanager-0.60.6 → generalmanager-0.62.0/src/GeneralManager.egg-info}/PKG-INFO +6 -1
  4. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/GeneralManager.egg-info/SOURCES.txt +21 -0
  5. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/GeneralManager.egg-info/requires.txt +7 -0
  6. generalmanager-0.62.0/src/general_manager/_types/api.py +117 -0
  7. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/api/graphql.py +70 -5
  8. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/api/graphql_errors.py +83 -21
  9. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/api/graphql_mutations.py +147 -9
  10. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/api/mutation.py +4 -1
  11. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/apps.py +4 -1
  12. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/bootstrap.py +4 -0
  13. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/base_interface.py +3 -0
  14. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/orm/mutations.py +108 -1
  15. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/orm_utils/field_descriptors.py +39 -7
  16. generalmanager-0.62.0/src/general_manager/management/commands/cleanup_upload_intents.py +69 -0
  17. generalmanager-0.62.0/src/general_manager/migrations/0007_upload_intent.py +179 -0
  18. generalmanager-0.62.0/src/general_manager/migrations/0008_upload_finalization_versions.py +52 -0
  19. generalmanager-0.62.0/src/general_manager/migrations/0009_upload_cleanup_state.py +32 -0
  20. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/models.py +4 -2
  21. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/public_api_registry.py +151 -0
  22. generalmanager-0.62.0/src/general_manager/uploads/__init__.py +1 -0
  23. generalmanager-0.62.0/src/general_manager/uploads/adapters.py +1445 -0
  24. generalmanager-0.62.0/src/general_manager/uploads/checks.py +463 -0
  25. generalmanager-0.62.0/src/general_manager/uploads/config.py +491 -0
  26. generalmanager-0.62.0/src/general_manager/uploads/errors.py +181 -0
  27. generalmanager-0.62.0/src/general_manager/uploads/finalization.py +2287 -0
  28. generalmanager-0.62.0/src/general_manager/uploads/graphql.py +180 -0
  29. generalmanager-0.62.0/src/general_manager/uploads/graphql_types.py +779 -0
  30. generalmanager-0.62.0/src/general_manager/uploads/metrics.py +407 -0
  31. generalmanager-0.62.0/src/general_manager/uploads/models.py +245 -0
  32. generalmanager-0.62.0/src/general_manager/uploads/public.py +42 -0
  33. generalmanager-0.62.0/src/general_manager/uploads/s3.py +1551 -0
  34. generalmanager-0.62.0/src/general_manager/uploads/services.py +1432 -0
  35. generalmanager-0.62.0/src/general_manager/uploads/tokens.py +31 -0
  36. generalmanager-0.62.0/src/general_manager/uploads/types.py +99 -0
  37. generalmanager-0.62.0/src/general_manager/uploads/urls.py +134 -0
  38. generalmanager-0.62.0/src/general_manager/uploads/views.py +1032 -0
  39. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/utils/testing.py +2 -0
  40. generalmanager-0.60.6/src/general_manager/_types/api.py +0 -25
  41. {generalmanager-0.60.6 → generalmanager-0.62.0}/LICENSE +0 -0
  42. {generalmanager-0.60.6 → generalmanager-0.62.0}/README.md +0 -0
  43. {generalmanager-0.60.6 → generalmanager-0.62.0}/setup.cfg +0 -0
  44. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/GeneralManager.egg-info/dependency_links.txt +0 -0
  45. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/GeneralManager.egg-info/top_level.txt +0 -0
  46. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/__init__.py +0 -0
  47. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/_types/__init__.py +0 -0
  48. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/_types/bucket.py +0 -0
  49. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/_types/cache.py +0 -0
  50. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/_types/dataframes.py +0 -0
  51. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/_types/factory.py +0 -0
  52. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/_types/general_manager.py +0 -0
  53. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/_types/interface.py +0 -0
  54. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/_types/manager.py +0 -0
  55. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/_types/measurement.py +0 -0
  56. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/_types/permission.py +0 -0
  57. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/_types/rule.py +0 -0
  58. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/_types/search.py +0 -0
  59. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/_types/utils.py +0 -0
  60. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/api/__init__.py +0 -0
  61. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/api/graphql_prefetch.py +0 -0
  62. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/api/graphql_resolvers.py +0 -0
  63. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/api/graphql_search.py +0 -0
  64. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/api/graphql_subscription_consumer.py +0 -0
  65. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/api/graphql_subscriptions.py +0 -0
  66. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/api/graphql_view.py +0 -0
  67. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/api/graphql_warmup.py +0 -0
  68. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/api/graphql_warmup_registry.py +0 -0
  69. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/api/graphql_warmup_tasks.py +0 -0
  70. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/api/property.py +0 -0
  71. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/api/registry.py +0 -0
  72. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/api/remote_api.py +0 -0
  73. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/api/remote_invalidation.py +0 -0
  74. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/api/remote_invalidation_client.py +0 -0
  75. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/bucket/__init__.py +0 -0
  76. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/bucket/base_bucket.py +0 -0
  77. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/bucket/calculation_bucket.py +0 -0
  78. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/bucket/database_bucket.py +0 -0
  79. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/bucket/group_bucket.py +0 -0
  80. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/bucket/indexing.py +0 -0
  81. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/bucket/request_bucket.py +0 -0
  82. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/cache/__init__.py +0 -0
  83. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/cache/cache_decorator.py +0 -0
  84. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/cache/cache_tracker.py +0 -0
  85. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/cache/dependency_cache.py +0 -0
  86. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/cache/dependency_index.py +0 -0
  87. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/cache/dependency_matching.py +0 -0
  88. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/cache/dependency_publish.py +0 -0
  89. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/cache/dependency_shards.py +0 -0
  90. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/cache/model_dependency_collector.py +0 -0
  91. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/cache/run_context.py +0 -0
  92. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/cache/signals.py +0 -0
  93. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/__init__.py +0 -0
  94. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/audit.py +0 -0
  95. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/bootstrap.py +0 -0
  96. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/checks.py +0 -0
  97. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/consumer.py +0 -0
  98. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/errors.py +0 -0
  99. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/evals/__init__.py +0 -0
  100. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/evals/__main__.py +0 -0
  101. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/evals/baseline.py +0 -0
  102. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/evals/diagnostics.py +0 -0
  103. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/evals/fingerprints.py +0 -0
  104. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/evals/fixtures.py +0 -0
  105. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/evals/judges/__init__.py +0 -0
  106. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/evals/judges/answer_quality.py +0 -0
  107. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/evals/judges/contract.py +0 -0
  108. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/evals/judges/result_accuracy.py +0 -0
  109. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/evals/judges/tool_sequence.py +0 -0
  110. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/evals/readiness.py +0 -0
  111. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/evals/runner.py +0 -0
  112. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/evals/traces.py +0 -0
  113. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/grounding.py +0 -0
  114. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/models.py +0 -0
  115. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/providers/__init__.py +0 -0
  116. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/providers/_shared.py +0 -0
  117. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/providers/anthropic.py +0 -0
  118. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/providers/base.py +0 -0
  119. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/providers/google.py +0 -0
  120. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/providers/ollama.py +0 -0
  121. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/providers/openai.py +0 -0
  122. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/rate_limits.py +0 -0
  123. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/routing.py +0 -0
  124. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/schema_index.py +0 -0
  125. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/settings.py +0 -0
  126. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/signals.py +0 -0
  127. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/system_prompt.py +0 -0
  128. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/tool_metadata.py +0 -0
  129. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/tools.py +0 -0
  130. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/chat/views.py +0 -0
  131. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/conf.py +0 -0
  132. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/dataframes/__init__.py +0 -0
  133. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/dataframes/measurements.py +0 -0
  134. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/factory/__init__.py +0 -0
  135. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/factory/auto_factory.py +0 -0
  136. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/factory/factories.py +0 -0
  137. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/factory/factory_methods.py +0 -0
  138. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/__init__.py +0 -0
  139. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/bundles/__init__.py +0 -0
  140. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/bundles/calculation.py +0 -0
  141. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/bundles/database.py +0 -0
  142. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/bundles/remote_manager.py +0 -0
  143. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/bundles/request.py +0 -0
  144. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/__init__.py +0 -0
  145. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/base.py +0 -0
  146. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/builtin.py +0 -0
  147. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/calculation/__init__.py +0 -0
  148. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/calculation/_compat.py +0 -0
  149. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/calculation/lifecycle.py +0 -0
  150. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/configuration.py +0 -0
  151. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/core/observability.py +0 -0
  152. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/core/utils.py +0 -0
  153. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/exceptions.py +0 -0
  154. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/existing_model/__init__.py +0 -0
  155. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/existing_model/_compat.py +0 -0
  156. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/existing_model/resolution.py +0 -0
  157. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/factory.py +0 -0
  158. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/orm/__init__.py +0 -0
  159. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/orm/_compat.py +0 -0
  160. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/orm/history.py +0 -0
  161. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/orm/lifecycle.py +0 -0
  162. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/orm/support.py +0 -0
  163. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/orm_utils/__init__.py +0 -0
  164. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/orm_utils/django_manager_utils.py +0 -0
  165. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/orm_utils/payload_normalizer.py +0 -0
  166. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/read_only/__init__.py +0 -0
  167. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/read_only/_compat.py +0 -0
  168. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/read_only/_types.py +0 -0
  169. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/read_only/lifecycle.py +0 -0
  170. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/read_only/management.py +0 -0
  171. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/registry.py +0 -0
  172. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/remote_manager.py +0 -0
  173. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/capabilities/request/__init__.py +0 -0
  174. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/infrastructure/__init__.py +0 -0
  175. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/infrastructure/startup_hooks.py +0 -0
  176. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/infrastructure/system_checks.py +0 -0
  177. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/interfaces/__init__.py +0 -0
  178. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/interfaces/calculation.py +0 -0
  179. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/interfaces/database.py +0 -0
  180. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/interfaces/existing_model.py +0 -0
  181. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/interfaces/read_only.py +0 -0
  182. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/interfaces/remote_manager.py +0 -0
  183. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/interfaces/request.py +0 -0
  184. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/manifests/__init__.py +0 -0
  185. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/manifests/capability_builder.py +0 -0
  186. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/manifests/capability_manifest.py +0 -0
  187. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/manifests/capability_models.py +0 -0
  188. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/orm_interface.py +0 -0
  189. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/requests.py +0 -0
  190. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/utils/__init__.py +0 -0
  191. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/utils/database_interface_protocols.py +0 -0
  192. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/utils/errors.py +0 -0
  193. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/interface/utils/models.py +0 -0
  194. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/logging.py +0 -0
  195. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/management/commands/chat_cleanup.py +0 -0
  196. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/management/commands/graphql_warmup.py +0 -0
  197. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/management/commands/graphql_warmup_refresh_due.py +0 -0
  198. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/management/commands/search_index.py +0 -0
  199. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/management/commands/search_reconcile.py +0 -0
  200. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/management/commands/seed_manager_landscape.py +0 -0
  201. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/management/commands/shell.py +0 -0
  202. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/management/commands/workflow_drain_outbox.py +0 -0
  203. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/management/commands/workflow_replay_dead_letters.py +0 -0
  204. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/manager/__init__.py +0 -0
  205. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/manager/general_manager.py +0 -0
  206. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/manager/group_manager.py +0 -0
  207. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/manager/input.py +0 -0
  208. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/manager/meta.py +0 -0
  209. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/measurement/__init__.py +0 -0
  210. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/measurement/measurement.py +0 -0
  211. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/measurement/measurement_field.py +0 -0
  212. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/metrics/__init__.py +0 -0
  213. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/metrics/graphql.py +0 -0
  214. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/migrations/0001_initial.py +0 -0
  215. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/migrations/0002_workflow_outbox_scaling_indexes.py +0 -0
  216. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/migrations/0003_workflow_execution_correlation_constraint.py +0 -0
  217. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/migrations/0004_chat_persistence_models.py +0 -0
  218. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/migrations/0004_search_index_state.py +0 -0
  219. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/migrations/0005_merge_chat_search.py +0 -0
  220. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/migrations/0006_chat_pending_confirmation_scoped_ids.py +0 -0
  221. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/migrations/__init__.py +0 -0
  222. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/permission/__init__.py +0 -0
  223. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/permission/audit.py +0 -0
  224. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/permission/base_permission.py +0 -0
  225. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/permission/graphql_capabilities.py +0 -0
  226. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/permission/manager_based_permission.py +0 -0
  227. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/permission/mutation_permission.py +0 -0
  228. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/permission/permission_checks.py +0 -0
  229. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/permission/permission_data_manager.py +0 -0
  230. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/permission/utils.py +0 -0
  231. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/py.typed +0 -0
  232. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/rule/__init__.py +0 -0
  233. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/rule/handler.py +0 -0
  234. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/rule/rule.py +0 -0
  235. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/search/__init__.py +0 -0
  236. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/search/async_tasks.py +0 -0
  237. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/search/backend.py +0 -0
  238. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/search/backend_registry.py +0 -0
  239. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/search/backends/__init__.py +0 -0
  240. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/search/backends/dev.py +0 -0
  241. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/search/backends/meilisearch.py +0 -0
  242. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/search/backends/opensearch.py +0 -0
  243. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/search/backends/typesense.py +0 -0
  244. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/search/config.py +0 -0
  245. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/search/indexer.py +0 -0
  246. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/search/models.py +0 -0
  247. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/search/reconciliation.py +0 -0
  248. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/search/registry.py +0 -0
  249. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/search/tasks.py +0 -0
  250. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/search/utils.py +0 -0
  251. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/seeding/__init__.py +0 -0
  252. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/seeding/manager_landscape.py +0 -0
  253. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/utils/__init__.py +0 -0
  254. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/utils/args_to_kwargs.py +0 -0
  255. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/utils/filter_parser.py +0 -0
  256. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/utils/format_string.py +0 -0
  257. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/utils/json_encoder.py +0 -0
  258. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/utils/make_cache_key.py +0 -0
  259. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/utils/none_to_zero.py +0 -0
  260. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/utils/path_mapping.py +0 -0
  261. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/utils/public_api.py +0 -0
  262. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/utils/type_checks.py +0 -0
  263. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/workflow/__init__.py +0 -0
  264. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/workflow/actions.py +0 -0
  265. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/workflow/backend_registry.py +0 -0
  266. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/workflow/backends/__init__.py +0 -0
  267. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/workflow/backends/celery.py +0 -0
  268. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/workflow/backends/local.py +0 -0
  269. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/workflow/backends/n8n.py +0 -0
  270. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/workflow/config.py +0 -0
  271. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/workflow/engine.py +0 -0
  272. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/workflow/event_registry.py +0 -0
  273. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/workflow/events.py +0 -0
  274. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/workflow/models.py +0 -0
  275. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/workflow/signal_bridge.py +0 -0
  276. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/workflow/tasks.py +0 -0
  277. {generalmanager-0.60.6 → generalmanager-0.62.0}/src/general_manager/workflow/telemetry.py +0 -0
  278. {generalmanager-0.60.6 → generalmanager-0.62.0}/tests/test_settings.py +0 -0
  279. {generalmanager-0.60.6 → generalmanager-0.62.0}/tests/test_urls.py +0 -0
  280. {generalmanager-0.60.6 → generalmanager-0.62.0}/tests/testing_asgi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.60.6
3
+ Version: 0.62.0
4
4
  Summary: Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching.
5
5
  Author-email: Tim Kleindick <tkleindick@yahoo.de>
6
6
  License: MIT License
@@ -80,6 +80,11 @@ Provides-Extra: chat-anthropic
80
80
  Requires-Dist: anthropic>=0.34.0; extra == "chat-anthropic"
81
81
  Provides-Extra: chat-google
82
82
  Requires-Dist: google-genai>=1.0.0; extra == "chat-google"
83
+ Provides-Extra: file-upload-image
84
+ Requires-Dist: Pillow>=12.2.0; extra == "file-upload-image"
85
+ Provides-Extra: file-upload-s3
86
+ Requires-Dist: boto3>=1.42.0; extra == "file-upload-s3"
87
+ Requires-Dist: django-storages[s3]>=1.14; extra == "file-upload-s3"
83
88
  Dynamic: license-file
84
89
 
85
90
  # GeneralManager
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "GeneralManager"
7
- version = "0.60.6"
7
+ version = "0.62.0"
8
8
  description = "Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching."
9
9
  readme = "README.md"
10
10
  authors = [{ name = "Tim Kleindick", email = "tkleindick@yahoo.de" }]
@@ -74,6 +74,8 @@ chat-ollama = ["ollama>=0.6.0"]
74
74
  chat-openai = ["openai>=1.0.0"]
75
75
  chat-anthropic = ["anthropic>=0.34.0"]
76
76
  chat-google = ["google-genai>=1.0.0"]
77
+ file-upload-image = ["Pillow>=12.2.0"]
78
+ file-upload-s3 = ["boto3>=1.42.0", "django-storages[s3]>=1.14"]
77
79
 
78
80
  [tool.setuptools]
79
81
  include-package-data = true
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.60.6
3
+ Version: 0.62.0
4
4
  Summary: Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching.
5
5
  Author-email: Tim Kleindick <tkleindick@yahoo.de>
6
6
  License: MIT License
@@ -80,6 +80,11 @@ Provides-Extra: chat-anthropic
80
80
  Requires-Dist: anthropic>=0.34.0; extra == "chat-anthropic"
81
81
  Provides-Extra: chat-google
82
82
  Requires-Dist: google-genai>=1.0.0; extra == "chat-google"
83
+ Provides-Extra: file-upload-image
84
+ Requires-Dist: Pillow>=12.2.0; extra == "file-upload-image"
85
+ Provides-Extra: file-upload-s3
86
+ Requires-Dist: boto3>=1.42.0; extra == "file-upload-s3"
87
+ Requires-Dist: django-storages[s3]>=1.14; extra == "file-upload-s3"
83
88
  Dynamic: license-file
84
89
 
85
90
  # GeneralManager
@@ -169,6 +169,7 @@ src/general_manager/interface/utils/database_interface_protocols.py
169
169
  src/general_manager/interface/utils/errors.py
170
170
  src/general_manager/interface/utils/models.py
171
171
  src/general_manager/management/commands/chat_cleanup.py
172
+ src/general_manager/management/commands/cleanup_upload_intents.py
172
173
  src/general_manager/management/commands/graphql_warmup.py
173
174
  src/general_manager/management/commands/graphql_warmup_refresh_due.py
174
175
  src/general_manager/management/commands/search_index.py
@@ -194,6 +195,9 @@ src/general_manager/migrations/0004_chat_persistence_models.py
194
195
  src/general_manager/migrations/0004_search_index_state.py
195
196
  src/general_manager/migrations/0005_merge_chat_search.py
196
197
  src/general_manager/migrations/0006_chat_pending_confirmation_scoped_ids.py
198
+ src/general_manager/migrations/0007_upload_intent.py
199
+ src/general_manager/migrations/0008_upload_finalization_versions.py
200
+ src/general_manager/migrations/0009_upload_cleanup_state.py
197
201
  src/general_manager/migrations/__init__.py
198
202
  src/general_manager/permission/__init__.py
199
203
  src/general_manager/permission/audit.py
@@ -225,6 +229,23 @@ src/general_manager/search/backends/opensearch.py
225
229
  src/general_manager/search/backends/typesense.py
226
230
  src/general_manager/seeding/__init__.py
227
231
  src/general_manager/seeding/manager_landscape.py
232
+ src/general_manager/uploads/__init__.py
233
+ src/general_manager/uploads/adapters.py
234
+ src/general_manager/uploads/checks.py
235
+ src/general_manager/uploads/config.py
236
+ src/general_manager/uploads/errors.py
237
+ src/general_manager/uploads/finalization.py
238
+ src/general_manager/uploads/graphql.py
239
+ src/general_manager/uploads/graphql_types.py
240
+ src/general_manager/uploads/metrics.py
241
+ src/general_manager/uploads/models.py
242
+ src/general_manager/uploads/public.py
243
+ src/general_manager/uploads/s3.py
244
+ src/general_manager/uploads/services.py
245
+ src/general_manager/uploads/tokens.py
246
+ src/general_manager/uploads/types.py
247
+ src/general_manager/uploads/urls.py
248
+ src/general_manager/uploads/views.py
228
249
  src/general_manager/utils/__init__.py
229
250
  src/general_manager/utils/args_to_kwargs.py
230
251
  src/general_manager/utils/filter_parser.py
@@ -38,3 +38,10 @@ ollama>=0.6.0
38
38
 
39
39
  [chat-openai]
40
40
  openai>=1.0.0
41
+
42
+ [file-upload-image]
43
+ Pillow>=12.2.0
44
+
45
+ [file-upload-s3]
46
+ boto3>=1.42.0
47
+ django-storages[s3]>=1.14
@@ -0,0 +1,117 @@
1
+ from __future__ import annotations
2
+
3
+ """Type-only imports for public API re-exports."""
4
+
5
+ __all__ = [
6
+ "ClaimedObject",
7
+ "ExactPublicDownloadAdapter",
8
+ "FileContentInspector",
9
+ "FileInspection",
10
+ "FileUploadConfigurationError",
11
+ "FileUploadPolicy",
12
+ "GraphQL",
13
+ "GraphQLPropertyReturnAnnotationError",
14
+ "GraphQLPropertyTimeoutConfigurationError",
15
+ "GraphQLPropertyWarmUpConfigurationError",
16
+ "InvalidFileTypeError",
17
+ "InvalidImageError",
18
+ "InvalidUploadChecksumError",
19
+ "InvalidUploadFilenameError",
20
+ "InvalidUploadSizeError",
21
+ "MeasurementScalar",
22
+ "MeasurementType",
23
+ "ObjectVersion",
24
+ "ProxyUploadSink",
25
+ "RemoteInvalidationClient",
26
+ "StoredFile",
27
+ "StoredFileStatus",
28
+ "StoredImage",
29
+ "UploadAdapter",
30
+ "UploadAdapterFactory",
31
+ "UploadAlreadyConsumedError",
32
+ "UploadAuthenticationError",
33
+ "UploadBackendUnsupportedError",
34
+ "UploadBindingMismatchError",
35
+ "UploadChecksumMismatchError",
36
+ "UploadDatabaseMismatchError",
37
+ "UploadError",
38
+ "UploadExpiredError",
39
+ "UploadFieldInvalidError",
40
+ "UploadFinalizationAdapter",
41
+ "UploadFinalizationFailedError",
42
+ "UploadIncompleteError",
43
+ "UploadInstructions",
44
+ "UploadManagerInvalidError",
45
+ "UploadObjectMissingError",
46
+ "UploadOperationInvalidError",
47
+ "UploadQuotaExceededError",
48
+ "UploadRateLimitExceededError",
49
+ "UploadSizeMismatchError",
50
+ "UploadStorageChangedError",
51
+ "UploadStorageError",
52
+ "UploadSupersededError",
53
+ "UploadTargetUnavailableError",
54
+ "UploadToken",
55
+ "UploadTokenInvalidError",
56
+ "UploadTransferConflictError",
57
+ "UploadTransport",
58
+ "graph_ql_mutation",
59
+ "graph_ql_property",
60
+ "register_upload_adapter",
61
+ ]
62
+
63
+ from general_manager.uploads.adapters import ClaimedObject
64
+ from general_manager.uploads.adapters import ExactPublicDownloadAdapter
65
+ from general_manager.uploads.config import FileContentInspector
66
+ from general_manager.uploads.config import FileInspection
67
+ from general_manager.uploads.config import FileUploadConfigurationError
68
+ from general_manager.uploads.config import FileUploadPolicy
69
+ from general_manager.api.graphql import GraphQL
70
+ from general_manager.api.property import GraphQLPropertyReturnAnnotationError
71
+ from general_manager.api.property import GraphQLPropertyTimeoutConfigurationError
72
+ from general_manager.api.property import GraphQLPropertyWarmUpConfigurationError
73
+ from general_manager.uploads.errors import InvalidFileTypeError
74
+ from general_manager.uploads.errors import InvalidImageError
75
+ from general_manager.uploads.errors import InvalidUploadChecksumError
76
+ from general_manager.uploads.errors import InvalidUploadFilenameError
77
+ from general_manager.uploads.errors import InvalidUploadSizeError
78
+ from general_manager.api.graphql import MeasurementScalar
79
+ from general_manager.api.graphql import MeasurementType
80
+ from general_manager.uploads.types import ObjectVersion
81
+ from general_manager.uploads.adapters import ProxyUploadSink
82
+ from general_manager.api.remote_invalidation_client import RemoteInvalidationClient
83
+ from general_manager.uploads.graphql_types import StoredFile
84
+ from general_manager.uploads.types import StoredFileStatus
85
+ from general_manager.uploads.graphql_types import StoredImage
86
+ from general_manager.uploads.adapters import UploadAdapter
87
+ from general_manager.uploads.adapters import UploadAdapterFactory
88
+ from general_manager.uploads.errors import UploadAlreadyConsumedError
89
+ from general_manager.uploads.errors import UploadAuthenticationError
90
+ from general_manager.uploads.errors import UploadBackendUnsupportedError
91
+ from general_manager.uploads.errors import UploadBindingMismatchError
92
+ from general_manager.uploads.errors import UploadChecksumMismatchError
93
+ from general_manager.uploads.errors import UploadDatabaseMismatchError
94
+ from general_manager.uploads.errors import UploadError
95
+ from general_manager.uploads.errors import UploadExpiredError
96
+ from general_manager.uploads.errors import UploadFieldInvalidError
97
+ from general_manager.uploads.adapters import UploadFinalizationAdapter
98
+ from general_manager.uploads.errors import UploadFinalizationFailedError
99
+ from general_manager.uploads.errors import UploadIncompleteError
100
+ from general_manager.uploads.adapters import UploadInstructions
101
+ from general_manager.uploads.errors import UploadManagerInvalidError
102
+ from general_manager.uploads.errors import UploadObjectMissingError
103
+ from general_manager.uploads.errors import UploadOperationInvalidError
104
+ from general_manager.uploads.errors import UploadQuotaExceededError
105
+ from general_manager.uploads.errors import UploadRateLimitExceededError
106
+ from general_manager.uploads.errors import UploadSizeMismatchError
107
+ from general_manager.uploads.errors import UploadStorageChangedError
108
+ from general_manager.uploads.errors import UploadStorageError
109
+ from general_manager.uploads.errors import UploadSupersededError
110
+ from general_manager.uploads.errors import UploadTargetUnavailableError
111
+ from general_manager.uploads.graphql_types import UploadToken
112
+ from general_manager.uploads.errors import UploadTokenInvalidError
113
+ from general_manager.uploads.errors import UploadTransferConflictError
114
+ from general_manager.uploads.types import UploadTransport
115
+ from general_manager.api.mutation import graph_ql_mutation
116
+ from general_manager.api.property import graph_ql_property
117
+ from general_manager.uploads.public import register_upload_adapter
@@ -49,6 +49,11 @@ from general_manager.permission.graphql_capabilities import (
49
49
  get_capability_context,
50
50
  get_graphql_capabilities,
51
51
  )
52
+ from general_manager.uploads.graphql_types import (
53
+ StoredFile,
54
+ StoredImage,
55
+ create_stored_file_value,
56
+ )
52
57
  from general_manager.utils.format_string import pascal_to_snake
53
58
  from general_manager.utils.type_checks import safe_issubclass
54
59
 
@@ -69,6 +74,7 @@ from general_manager.api.graphql_errors import (
69
74
  EXPECTED_MANAGER_ERRORS, # noqa: F401 # re-exported
70
75
  SUSPICIOUS_MANAGER_ERRORS, # noqa: F401 # re-exported
71
76
  HANDLED_MANAGER_ERRORS as HANDLED_MANAGER_ERRORS,
77
+ ValidationFieldNameMapper,
72
78
  MeasurementType as MeasurementType,
73
79
  MeasurementScalar as MeasurementScalar,
74
80
  PageInfo,
@@ -220,6 +226,14 @@ class GraphQL:
220
226
 
221
227
  clear_schema_index_cache()
222
228
 
229
+ @classmethod
230
+ def register_file_upload_mutation(cls) -> None:
231
+ """Register the generic begin-upload mutation when the feature is enabled."""
232
+
233
+ from general_manager.uploads.graphql import register_file_upload_mutation
234
+
235
+ register_file_upload_mutation(cls._mutations)
236
+
223
237
  @classmethod
224
238
  def get_registry_snapshot(cls) -> GraphQLRegistry:
225
239
  """
@@ -431,7 +445,31 @@ class GraphQL:
431
445
  field_info,
432
446
  )
433
447
  resolver_name = f"resolve_{field_name}"
434
- fields[resolver_name] = cls._create_resolver(field_name, field_type)
448
+ if field_info.get("orm_field_kind") in {"file", "image"}:
449
+
450
+ def resolve_stored_file(
451
+ manager_instance: GeneralManager,
452
+ info: GraphQLResolveInfo,
453
+ *,
454
+ _field_name: str = field_name,
455
+ _manager_name: str = generalManagerClass.__name__,
456
+ ) -> object:
457
+ if not cls._check_read_permission(
458
+ manager_instance,
459
+ info,
460
+ _field_name,
461
+ ):
462
+ return None
463
+ return create_stored_file_value(
464
+ manager_instance,
465
+ info,
466
+ field_name=_field_name,
467
+ manager_name=_manager_name,
468
+ )
469
+
470
+ fields[resolver_name] = resolve_stored_file
471
+ else:
472
+ fields[resolver_name] = cls._create_resolver(field_name, field_type)
435
473
 
436
474
  # handle GraphQLProperty attributes
437
475
  for (
@@ -788,7 +826,9 @@ class GraphQL:
788
826
  ]:
789
827
  """Yield filter variants for *attribute_type*. See ``graphql_search.get_filter_options``."""
790
828
  return _get_filter_options_fn(
791
- attribute_type, attribute_name, GraphQL._map_field_to_graphene_read
829
+ attribute_type,
830
+ attribute_name,
831
+ GraphQL._map_field_to_graphene_filter_input,
792
832
  )
793
833
 
794
834
  @staticmethod
@@ -801,10 +841,26 @@ class GraphQL:
801
841
  return _create_filter_options_fn(
802
842
  field_type,
803
843
  GraphQL.graphql_filter_type_registry,
804
- GraphQL._map_field_to_graphene_read,
844
+ GraphQL._map_field_to_graphene_filter_input,
805
845
  relation_depth=relation_depth,
806
846
  )
807
847
 
848
+ @staticmethod
849
+ def _map_field_to_graphene_filter_input(
850
+ field_type: type,
851
+ field_name: str,
852
+ field_info: Mapping[str, object] | None = None,
853
+ ) -> object:
854
+ """Map file metadata to legacy string filters and delegate other fields."""
855
+ orm_field_kind = field_info.get("orm_field_kind") if field_info else None
856
+ if orm_field_kind in {"file", "image"}:
857
+ return graphene.String()
858
+ return GraphQL._map_field_to_graphene_read(
859
+ field_type,
860
+ field_name,
861
+ field_info,
862
+ )
863
+
808
864
  @staticmethod
809
865
  def _map_field_to_graphene_read(
810
866
  field_type: type,
@@ -864,6 +920,11 @@ class GraphQL:
864
920
  lambda: GraphQL.graphql_type_registry[field_type.__name__]
865
921
  )
866
922
  else:
923
+ orm_field_kind = field_info.get("orm_field_kind") if field_info else None
924
+ if orm_field_kind == "file":
925
+ return graphene.Field(StoredFile)
926
+ if orm_field_kind == "image":
927
+ return graphene.Field(StoredImage)
867
928
  return GraphQL._map_field_to_graphene_base_type(
868
929
  field_type,
869
930
  field_info,
@@ -1512,9 +1573,13 @@ class GraphQL:
1512
1573
  )
1513
1574
 
1514
1575
  @staticmethod
1515
- def _handle_graph_ql_error(error: Exception) -> GraphQLError:
1576
+ def _handle_graph_ql_error(
1577
+ error: Exception,
1578
+ *,
1579
+ field_name_mapper: ValidationFieldNameMapper | None = None,
1580
+ ) -> GraphQLError:
1516
1581
  """Thin wrapper - see :func:`general_manager.api.graphql_errors.handle_graph_ql_error`."""
1517
- return _handle_graph_ql_error_fn(error)
1582
+ return _handle_graph_ql_error_fn(error, field_name_mapper=field_name_mapper)
1518
1583
 
1519
1584
  @classmethod
1520
1585
  def _handle_data_change(
@@ -9,7 +9,7 @@ without introducing circular dependencies.
9
9
 
10
10
  from __future__ import annotations
11
11
 
12
- from collections.abc import Callable
12
+ from collections.abc import Callable, Iterable, Mapping
13
13
  from dataclasses import dataclass
14
14
  from datetime import date, datetime
15
15
  from decimal import Decimal
@@ -17,7 +17,7 @@ from typing import TYPE_CHECKING, Protocol, TypeAlias, TypedDict, cast
17
17
 
18
18
  from graphql import GraphQLError
19
19
  from graphql.language import ast
20
- from django.core.exceptions import ValidationError
20
+ from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
21
21
 
22
22
  from general_manager.logging import get_logger
23
23
  from general_manager.measurement.measurement import Measurement
@@ -83,6 +83,8 @@ PermissionFilterPlan: TypeAlias = list[PermissionConstraint]
83
83
  ReadPermissionPlanMethod: TypeAlias = Callable[[], object]
84
84
  BigIntCoercible: TypeAlias = str | bytes | bytearray | int | float | Decimal
85
85
  GraphQLSubscriptionAction: TypeAlias = str
86
+ ValidationFieldNameMapper: TypeAlias = Callable[[str], str]
87
+ ValidationFieldErrors: TypeAlias = dict[str, list[str]]
86
88
 
87
89
 
88
90
  class _ReadPermissionProvider(Protocol):
@@ -438,30 +440,76 @@ def map_field_to_graphene_base_type(
438
440
  return String
439
441
 
440
442
 
441
- def handle_graph_ql_error(error: Exception) -> GraphQLError:
442
- """Convert an exception into a GraphQL error with an extensions code.
443
+ def _validation_messages_to_strings(messages: object) -> list[str]:
444
+ """Convert Django validation message values to plain strings."""
445
+ if isinstance(messages, ValidationError):
446
+ return [str(message) for message in messages.messages]
447
+ if isinstance(messages, str):
448
+ return [messages]
449
+ if isinstance(messages, bytes):
450
+ return [messages.decode()]
451
+ if isinstance(messages, Iterable):
452
+ return [str(message) for message in messages]
453
+ return [str(messages)]
454
+
455
+
456
+ def _build_validation_error_extensions(
457
+ message_dict: Mapping[str, object],
458
+ *,
459
+ field_name_mapper: ValidationFieldNameMapper | None,
460
+ ) -> dict[str, object]:
461
+ """Convert validation messages into GraphQL BAD_USER_INPUT extensions.
462
+
463
+ Per-field keys are remapped with ``field_name_mapper`` when provided.
464
+ ``NON_FIELD_ERRORS`` messages are separated into ``nonFieldErrors`` and are
465
+ not remapped. The returned mapping always includes ``code``,
466
+ ``fieldErrors``, and ``nonFieldErrors`` keys.
467
+ """
468
+ field_errors: ValidationFieldErrors = {}
469
+ non_field_errors: list[str] = []
470
+
471
+ for field_name, messages in message_dict.items():
472
+ message_list = _validation_messages_to_strings(messages)
473
+ if field_name == NON_FIELD_ERRORS:
474
+ non_field_errors.extend(message_list)
475
+ continue
476
+
477
+ schema_field_name = (
478
+ field_name_mapper(field_name)
479
+ if field_name_mapper is not None
480
+ else field_name
481
+ )
482
+ field_errors.setdefault(schema_field_name, []).extend(message_list)
483
+
484
+ return {
485
+ "code": "BAD_USER_INPUT",
486
+ "fieldErrors": field_errors,
487
+ "nonFieldErrors": non_field_errors,
488
+ }
489
+
490
+
491
+ def handle_graph_ql_error(
492
+ error: Exception,
493
+ *,
494
+ field_name_mapper: ValidationFieldNameMapper | None = None,
495
+ ) -> GraphQLError:
496
+ """Convert a handled exception into a GraphQL error.
443
497
 
444
498
  This private extracted helper is used by the canonical GraphQL module and is
445
499
  not a stable import path. The behavior documented here is a
446
500
  generated-resolver compatibility note, not a stable direct-import guarantee.
447
501
 
448
502
  Explicit ``GraphQLError`` instances are returned as the same object,
449
- preserving their message and entire existing ``extensions`` mapping. For
450
- converted exceptions, the returned ``GraphQLError.extensions`` mapping
451
- contains a single ``"code"`` key. The original exception message is
452
- intentionally exposed as the GraphQL error message; this is a stable
453
- generated-response compatibility guarantee for
454
- ``{"code": "INTERNAL_SERVER_ERROR"}`` responses as well as user-error
455
- responses, even though the helper itself remains a private import.
456
- ``PermissionError`` uses ``{"code": "PERMISSION_DENIED"}`` and is
457
- logged at info level. ``ValueError`` and Django ``ValidationError`` use
458
- ``{"code": "BAD_USER_INPUT"}`` and are logged as warnings. ``TypeError``,
459
- ``AttributeError``, and ``RuntimeError`` are treated as suspicious handled
460
- errors, logged with traceback information, and returned as
461
- ``{"code": "INTERNAL_SERVER_ERROR"}``. Exceptions outside those explicit
462
- branches are logged as unexpected internal errors and also returned as
463
- ``INTERNAL_SERVER_ERROR``. Logging level/category is diagnostic behavior of
464
- the internal ``api.graphql`` logger and is not a public API contract.
503
+ preserving their message and existing ``extensions`` mapping. Converted
504
+ exceptions always include an ``extensions["code"]`` value. Django
505
+ ``ValidationError`` instances with ``message_dict`` use
506
+ ``"Validation failed."`` with ``BAD_USER_INPUT`` plus ``fieldErrors`` and
507
+ ``nonFieldErrors``. When ``field_name_mapper`` is provided, it maps
508
+ ``message_dict`` field keys before they are emitted in ``fieldErrors``;
509
+ non-field errors are not mapped. Other converted exceptions keep their
510
+ original message and category-specific code. Logging level/category is
511
+ diagnostic behavior of the internal ``api.graphql`` logger and is not a
512
+ public API contract.
465
513
  """
466
514
  message = str(error)
467
515
  error_name = type(error).__name__
@@ -477,7 +525,21 @@ def handle_graph_ql_error(error: Exception) -> GraphQLError:
477
525
  context={"error": error_name, "message": message},
478
526
  )
479
527
  return GraphQLError(message, extensions={"code": "PERMISSION_DENIED"})
480
- elif isinstance(error, (ValueError, ValidationError)):
528
+ elif isinstance(error, ValidationError):
529
+ logger.warning(
530
+ "graphql user error",
531
+ context={"error": error_name, "message": message},
532
+ )
533
+ if hasattr(error, "error_dict"):
534
+ return GraphQLError(
535
+ "Validation failed.",
536
+ extensions=_build_validation_error_extensions(
537
+ error.message_dict,
538
+ field_name_mapper=field_name_mapper,
539
+ ),
540
+ )
541
+ return GraphQLError(message, extensions={"code": "BAD_USER_INPUT"})
542
+ elif isinstance(error, ValueError):
481
543
  logger.warning(
482
544
  "graphql user error",
483
545
  context={"error": error_name, "message": message},