GeneralManager 0.37.1__tar.gz → 0.37.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. {generalmanager-0.37.1/src/GeneralManager.egg-info → generalmanager-0.37.2}/PKG-INFO +1 -1
  2. {generalmanager-0.37.1 → generalmanager-0.37.2}/pyproject.toml +1 -1
  3. {generalmanager-0.37.1 → generalmanager-0.37.2/src/GeneralManager.egg-info}/PKG-INFO +1 -1
  4. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/orm/support.py +168 -1
  5. {generalmanager-0.37.1 → generalmanager-0.37.2}/LICENSE +0 -0
  6. {generalmanager-0.37.1 → generalmanager-0.37.2}/README.md +0 -0
  7. {generalmanager-0.37.1 → generalmanager-0.37.2}/setup.cfg +0 -0
  8. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/GeneralManager.egg-info/SOURCES.txt +0 -0
  9. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/GeneralManager.egg-info/dependency_links.txt +0 -0
  10. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/GeneralManager.egg-info/requires.txt +0 -0
  11. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/GeneralManager.egg-info/top_level.txt +0 -0
  12. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/__init__.py +0 -0
  13. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/_types/__init__.py +0 -0
  14. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/_types/api.py +0 -0
  15. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/_types/bucket.py +0 -0
  16. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/_types/cache.py +0 -0
  17. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/_types/factory.py +0 -0
  18. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/_types/general_manager.py +0 -0
  19. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/_types/interface.py +0 -0
  20. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/_types/manager.py +0 -0
  21. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/_types/measurement.py +0 -0
  22. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/_types/permission.py +0 -0
  23. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/_types/rule.py +0 -0
  24. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/_types/utils.py +0 -0
  25. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/api/__init__.py +0 -0
  26. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/api/graphql.py +0 -0
  27. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/api/graphql_errors.py +0 -0
  28. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/api/graphql_mutations.py +0 -0
  29. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/api/graphql_resolvers.py +0 -0
  30. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/api/graphql_search.py +0 -0
  31. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/api/graphql_subscription_consumer.py +0 -0
  32. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/api/graphql_subscriptions.py +0 -0
  33. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/api/graphql_view.py +0 -0
  34. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/api/mutation.py +0 -0
  35. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/api/property.py +0 -0
  36. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/api/registry.py +0 -0
  37. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/api/remote_api.py +0 -0
  38. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/api/remote_invalidation.py +0 -0
  39. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/api/remote_invalidation_client.py +0 -0
  40. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/apps.py +0 -0
  41. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/bootstrap.py +0 -0
  42. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/bucket/__init__.py +0 -0
  43. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/bucket/base_bucket.py +0 -0
  44. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/bucket/calculation_bucket.py +0 -0
  45. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/bucket/database_bucket.py +0 -0
  46. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/bucket/group_bucket.py +0 -0
  47. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/bucket/request_bucket.py +0 -0
  48. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/cache/__init__.py +0 -0
  49. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/cache/cache_decorator.py +0 -0
  50. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/cache/cache_tracker.py +0 -0
  51. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/cache/dependency_index.py +0 -0
  52. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/cache/model_dependency_collector.py +0 -0
  53. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/cache/signals.py +0 -0
  54. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/conf.py +0 -0
  55. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/factory/__init__.py +0 -0
  56. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/factory/auto_factory.py +0 -0
  57. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/factory/factories.py +0 -0
  58. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/factory/factory_methods.py +0 -0
  59. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/__init__.py +0 -0
  60. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/base_interface.py +0 -0
  61. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/bundles/__init__.py +0 -0
  62. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/bundles/calculation.py +0 -0
  63. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/bundles/database.py +0 -0
  64. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/bundles/remote_manager.py +0 -0
  65. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/bundles/request.py +0 -0
  66. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/__init__.py +0 -0
  67. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/base.py +0 -0
  68. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/builtin.py +0 -0
  69. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/calculation/__init__.py +0 -0
  70. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/calculation/_compat.py +0 -0
  71. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/calculation/lifecycle.py +0 -0
  72. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/configuration.py +0 -0
  73. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/core/observability.py +0 -0
  74. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/core/utils.py +0 -0
  75. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/exceptions.py +0 -0
  76. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/existing_model/__init__.py +0 -0
  77. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/existing_model/_compat.py +0 -0
  78. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/existing_model/resolution.py +0 -0
  79. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/factory.py +0 -0
  80. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/orm/__init__.py +0 -0
  81. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/orm/_compat.py +0 -0
  82. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/orm/history.py +0 -0
  83. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/orm/lifecycle.py +0 -0
  84. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/orm/mutations.py +0 -0
  85. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/orm_utils/__init__.py +0 -0
  86. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/orm_utils/django_manager_utils.py +0 -0
  87. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/orm_utils/field_descriptors.py +0 -0
  88. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/orm_utils/payload_normalizer.py +0 -0
  89. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/read_only/__init__.py +0 -0
  90. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/read_only/_compat.py +0 -0
  91. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/read_only/lifecycle.py +0 -0
  92. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/read_only/management.py +0 -0
  93. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/registry.py +0 -0
  94. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/remote_manager.py +0 -0
  95. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/capabilities/request/__init__.py +0 -0
  96. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/infrastructure/startup_hooks.py +0 -0
  97. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/infrastructure/system_checks.py +0 -0
  98. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/interfaces/__init__.py +0 -0
  99. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/interfaces/calculation.py +0 -0
  100. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/interfaces/database.py +0 -0
  101. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/interfaces/existing_model.py +0 -0
  102. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/interfaces/read_only.py +0 -0
  103. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/interfaces/remote_manager.py +0 -0
  104. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/interfaces/request.py +0 -0
  105. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/manifests/__init__.py +0 -0
  106. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/manifests/capability_builder.py +0 -0
  107. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/manifests/capability_manifest.py +0 -0
  108. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/manifests/capability_models.py +0 -0
  109. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/orm_interface.py +0 -0
  110. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/requests.py +0 -0
  111. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/utils/__init__.py +0 -0
  112. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/utils/database_interface_protocols.py +0 -0
  113. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/utils/errors.py +0 -0
  114. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/interface/utils/models.py +0 -0
  115. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/logging.py +0 -0
  116. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/management/commands/search_index.py +0 -0
  117. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/management/commands/shell.py +0 -0
  118. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/management/commands/workflow_drain_outbox.py +0 -0
  119. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/management/commands/workflow_replay_dead_letters.py +0 -0
  120. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/manager/__init__.py +0 -0
  121. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/manager/general_manager.py +0 -0
  122. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/manager/group_manager.py +0 -0
  123. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/manager/input.py +0 -0
  124. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/manager/meta.py +0 -0
  125. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/measurement/__init__.py +0 -0
  126. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/measurement/measurement.py +0 -0
  127. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/measurement/measurement_field.py +0 -0
  128. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/metrics/__init__.py +0 -0
  129. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/metrics/graphql.py +0 -0
  130. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/migrations/0001_initial.py +0 -0
  131. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/migrations/0002_workflow_outbox_scaling_indexes.py +0 -0
  132. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/migrations/0003_workflow_execution_correlation_constraint.py +0 -0
  133. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/migrations/__init__.py +0 -0
  134. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/models.py +0 -0
  135. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/permission/__init__.py +0 -0
  136. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/permission/audit.py +0 -0
  137. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/permission/base_permission.py +0 -0
  138. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/permission/manager_based_permission.py +0 -0
  139. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/permission/mutation_permission.py +0 -0
  140. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/permission/permission_checks.py +0 -0
  141. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/permission/permission_data_manager.py +0 -0
  142. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/permission/utils.py +0 -0
  143. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/public_api_registry.py +0 -0
  144. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/py.typed +0 -0
  145. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/rule/__init__.py +0 -0
  146. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/rule/handler.py +0 -0
  147. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/rule/rule.py +0 -0
  148. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/search/__init__.py +0 -0
  149. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/search/async_tasks.py +0 -0
  150. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/search/backend.py +0 -0
  151. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/search/backend_registry.py +0 -0
  152. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/search/backends/__init__.py +0 -0
  153. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/search/backends/dev.py +0 -0
  154. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/search/backends/meilisearch.py +0 -0
  155. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/search/backends/opensearch.py +0 -0
  156. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/search/backends/typesense.py +0 -0
  157. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/search/config.py +0 -0
  158. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/search/indexer.py +0 -0
  159. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/search/registry.py +0 -0
  160. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/search/utils.py +0 -0
  161. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/utils/__init__.py +0 -0
  162. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/utils/args_to_kwargs.py +0 -0
  163. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/utils/filter_parser.py +0 -0
  164. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/utils/format_string.py +0 -0
  165. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/utils/json_encoder.py +0 -0
  166. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/utils/make_cache_key.py +0 -0
  167. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/utils/none_to_zero.py +0 -0
  168. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/utils/path_mapping.py +0 -0
  169. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/utils/public_api.py +0 -0
  170. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/utils/testing.py +0 -0
  171. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/workflow/__init__.py +0 -0
  172. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/workflow/actions.py +0 -0
  173. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/workflow/backend_registry.py +0 -0
  174. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/workflow/backends/__init__.py +0 -0
  175. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/workflow/backends/celery.py +0 -0
  176. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/workflow/backends/local.py +0 -0
  177. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/workflow/backends/n8n.py +0 -0
  178. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/workflow/config.py +0 -0
  179. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/workflow/engine.py +0 -0
  180. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/workflow/event_registry.py +0 -0
  181. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/workflow/events.py +0 -0
  182. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/workflow/models.py +0 -0
  183. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/workflow/signal_bridge.py +0 -0
  184. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/workflow/tasks.py +0 -0
  185. {generalmanager-0.37.1 → generalmanager-0.37.2}/src/general_manager/workflow/telemetry.py +0 -0
  186. {generalmanager-0.37.1 → generalmanager-0.37.2}/tests/test_settings.py +0 -0
  187. {generalmanager-0.37.1 → generalmanager-0.37.2}/tests/test_urls.py +0 -0
  188. {generalmanager-0.37.1 → generalmanager-0.37.2}/tests/testing_asgi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.37.1
3
+ Version: 0.37.2
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "GeneralManager"
7
- version = "0.37.1"
7
+ version = "0.37.2"
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" }]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.37.1
3
+ Version: 0.37.2
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
@@ -2,9 +2,12 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import re
5
6
  from datetime import date, datetime, time, timedelta
7
+ from functools import lru_cache
6
8
  from typing import Any, TYPE_CHECKING, Callable, ClassVar, Type, cast
7
9
 
10
+ from django.core.exceptions import FieldDoesNotExist
8
11
  from django.db import models
9
12
  from django.db.models import Subquery
10
13
  from django.utils import timezone
@@ -17,6 +20,7 @@ from general_manager.interface.capabilities.orm_utils.django_manager_utils impor
17
20
  )
18
21
  from general_manager.interface.capabilities.orm_utils.field_descriptors import (
19
22
  FieldDescriptor,
23
+ _iter_reverse_relations,
20
24
  build_field_descriptors,
21
25
  )
22
26
  from general_manager.interface.capabilities.orm_utils.payload_normalizer import (
@@ -357,6 +361,165 @@ class SearchDateInputError(TypeError):
357
361
  super().__init__("search_date must be a datetime or date instance.")
358
362
 
359
363
 
364
+ class AmbiguousReverseFilterAliasError(ValueError):
365
+ """Raised when a snake_case reverse filter alias resolves to multiple relations."""
366
+
367
+ def __init__(self, alias: str, targets: tuple[str, str]) -> None:
368
+ left, right = targets
369
+ super().__init__(
370
+ "Ambiguous reverse filter alias "
371
+ f"'{alias}' resolves to both '{left}' and '{right}'."
372
+ )
373
+
374
+
375
+ def _to_snake_case(name: str) -> str:
376
+ """Convert a CamelCase class name into snake_case."""
377
+ snake = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name)
378
+ snake = re.sub("([a-z0-9])([A-Z])", r"\1_\2", snake)
379
+ return snake.lower()
380
+
381
+
382
+ @lru_cache(maxsize=None)
383
+ def _build_reverse_filter_alias_metadata(
384
+ model: type[models.Model],
385
+ ) -> tuple[dict[str, str], dict[str, tuple[str, str]]]:
386
+ """Build cached alias and ambiguity metadata for reverse filter roots."""
387
+ meta = getattr(model, "_meta", None)
388
+ get_fields = getattr(meta, "get_fields", None)
389
+ if not callable(get_fields):
390
+ return {}, {}
391
+ try:
392
+ all_fields = tuple(get_fields())
393
+ except TypeError:
394
+ return {}, {}
395
+
396
+ alias_map: dict[str, str] = {}
397
+ ambiguous_aliases: dict[str, tuple[str, str]] = {}
398
+ # Only include forward field names (not reverse relations) to avoid masking
399
+ # ambiguity when an explicit related_name coincidentally matches an alias.
400
+ model_field_names = {
401
+ field.name
402
+ for field in all_fields
403
+ if not (
404
+ getattr(field, "is_relation", False)
405
+ and getattr(field, "one_to_many", False)
406
+ )
407
+ }
408
+
409
+ for reverse_relation in _iter_reverse_relations(model):
410
+ related_model = getattr(reverse_relation, "related_model", None)
411
+ if related_model is None:
412
+ continue
413
+
414
+ target_root = reverse_relation.name
415
+ relation_field = getattr(reverse_relation, "field", None)
416
+ explicit_query_root = getattr(relation_field, "_related_query_name", None)
417
+ explicit_accessor = getattr(relation_field, "_related_name", None)
418
+ alias = (
419
+ target_root
420
+ if (
421
+ isinstance(target_root, str)
422
+ and target_root
423
+ and target_root != "+"
424
+ and (explicit_query_root is not None or explicit_accessor is not None)
425
+ )
426
+ else _to_snake_case(related_model.__name__)
427
+ )
428
+
429
+ if alias in model_field_names:
430
+ continue
431
+
432
+ if alias in ambiguous_aliases:
433
+ continue
434
+
435
+ existing = alias_map.get(alias)
436
+ if existing is not None and existing != target_root:
437
+ ambiguous_aliases[alias] = (existing, target_root)
438
+ alias_map.pop(alias, None)
439
+ continue
440
+ alias_map[alias] = target_root
441
+
442
+ return alias_map, ambiguous_aliases
443
+
444
+
445
+ def _build_reverse_filter_alias_map(
446
+ model: type[models.Model],
447
+ ) -> dict[str, str]:
448
+ """Build a cached map of snake_case reverse filter roots to Django lookup roots."""
449
+ alias_map, _ = _build_reverse_filter_alias_metadata(model)
450
+ return alias_map
451
+
452
+
453
+ def _translate_reverse_filter_aliases(
454
+ model: type[models.Model],
455
+ kwargs: dict[str, Any],
456
+ ) -> dict[str, Any]:
457
+ """Rewrite snake_case reverse-relation filter segments to Django's native lookup roots."""
458
+ translated: dict[str, Any] = {}
459
+
460
+ for key, value in kwargs.items():
461
+ translated[_translate_reverse_filter_key(model, key)] = value
462
+
463
+ return translated
464
+
465
+
466
+ def _translate_reverse_filter_key(model: type[models.Model], key: str) -> str:
467
+ """Rewrite only relation-path segments that are known reverse aliases."""
468
+ parts = key.split("__")
469
+ translated_parts: list[str] = []
470
+ current_model: type[models.Model] | None = model
471
+
472
+ for index, part in enumerate(parts):
473
+ if current_model is None:
474
+ translated_parts.extend(parts[index:])
475
+ break
476
+
477
+ resolved_name, field = _resolve_filter_segment(current_model, part)
478
+ if field is None:
479
+ translated_parts.extend(parts[index:])
480
+ break
481
+
482
+ translated_parts.append(resolved_name)
483
+ if not getattr(field, "is_relation", False):
484
+ translated_parts.extend(parts[index + 1 :])
485
+ break
486
+
487
+ current_model = cast(
488
+ type[models.Model] | None, getattr(field, "related_model", None)
489
+ )
490
+ else:
491
+ return "__".join(translated_parts)
492
+
493
+ return "__".join(translated_parts)
494
+
495
+
496
+ def _resolve_filter_segment(
497
+ model: type[models.Model],
498
+ segment: str,
499
+ ) -> tuple[str, models.Field | models.ForeignObjectRel | None]:
500
+ """Resolve a lookup segment to a real Django field or reverse relation."""
501
+ meta = getattr(model, "_meta", None)
502
+ get_field = getattr(meta, "get_field", None)
503
+ if not callable(get_field):
504
+ return segment, None
505
+
506
+ alias_map, ambiguous_aliases = _build_reverse_filter_alias_metadata(model)
507
+ targets = ambiguous_aliases.get(segment)
508
+ if targets is not None:
509
+ raise AmbiguousReverseFilterAliasError(segment, targets)
510
+
511
+ try:
512
+ field = cast(models.Field | models.ForeignObjectRel, get_field(segment))
513
+ except FieldDoesNotExist:
514
+ actual_name = alias_map.get(segment)
515
+ if actual_name is None:
516
+ return segment, None
517
+ field = cast(models.Field | models.ForeignObjectRel, get_field(actual_name))
518
+ return actual_name, field
519
+ else:
520
+ return segment, field
521
+
522
+
360
523
  class OrmQueryCapability(BaseCapability):
361
524
  """Expose DatabaseBucket operations via the capability configuration."""
362
525
 
@@ -486,7 +649,11 @@ class OrmQueryCapability(BaseCapability):
486
649
  self._ensure_search_date_normalized(search_date)
487
650
  support = get_support_capability(interface_cls)
488
651
  normalizer = support.get_payload_normalizer(interface_cls)
489
- normalized_kwargs = normalizer.normalize_filter_kwargs(payload)
652
+ translated_payload = _translate_reverse_filter_aliases(
653
+ interface_cls._model,
654
+ payload,
655
+ )
656
+ normalized_kwargs = normalizer.normalize_filter_kwargs(translated_payload)
490
657
  return include_inactive, normalized_kwargs, search_date
491
658
 
492
659
  def _build_bucket(
File without changes