GeneralManager 0.82.0__tar.gz → 0.82.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 (340) hide show
  1. {generalmanager-0.82.0/src/GeneralManager.egg-info → generalmanager-0.82.2}/PKG-INFO +1 -1
  2. {generalmanager-0.82.0 → generalmanager-0.82.2}/pyproject.toml +1 -1
  3. {generalmanager-0.82.0 → generalmanager-0.82.2/src/GeneralManager.egg-info}/PKG-INFO +1 -1
  4. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/GeneralManager.egg-info/SOURCES.txt +1 -0
  5. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/graphql.py +18 -1
  6. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/graphql_identifiers.py +43 -1
  7. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/graphql_search.py +10 -1
  8. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/property.py +18 -1
  9. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/cache/dependency_index.py +122 -10
  10. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/cache/signals.py +19 -2
  11. generalmanager-0.82.2/src/general_manager/cache/transaction_barrier.py +283 -0
  12. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/orm/create_many.py +17 -2
  13. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/utils/testing.py +4 -0
  14. {generalmanager-0.82.0 → generalmanager-0.82.2}/LICENSE +0 -0
  15. {generalmanager-0.82.0 → generalmanager-0.82.2}/README.md +0 -0
  16. {generalmanager-0.82.0 → generalmanager-0.82.2}/setup.cfg +0 -0
  17. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/GeneralManager.egg-info/dependency_links.txt +0 -0
  18. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/GeneralManager.egg-info/requires.txt +0 -0
  19. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/GeneralManager.egg-info/top_level.txt +0 -0
  20. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/__init__.py +0 -0
  21. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/_types/__init__.py +0 -0
  22. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/_types/api.py +0 -0
  23. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/_types/bucket.py +0 -0
  24. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/_types/cache.py +0 -0
  25. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/_types/dataframes.py +0 -0
  26. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/_types/factory.py +0 -0
  27. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/_types/general_manager.py +0 -0
  28. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/_types/interface.py +0 -0
  29. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/_types/manager.py +0 -0
  30. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/_types/measurement.py +0 -0
  31. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/_types/permission.py +0 -0
  32. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/_types/rule.py +0 -0
  33. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/_types/search.py +0 -0
  34. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/_types/utils.py +0 -0
  35. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/__init__.py +0 -0
  36. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/graphql_as_of.py +0 -0
  37. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/graphql_errors.py +0 -0
  38. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/graphql_groups.py +0 -0
  39. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/graphql_mutations.py +0 -0
  40. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/graphql_ordering.py +0 -0
  41. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/graphql_output.py +0 -0
  42. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/graphql_prefetch.py +0 -0
  43. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/graphql_relations.py +0 -0
  44. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/graphql_resolvers.py +0 -0
  45. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/graphql_subscription_consumer.py +0 -0
  46. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/graphql_subscriptions.py +0 -0
  47. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/graphql_type.py +0 -0
  48. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/graphql_view.py +0 -0
  49. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/graphql_warmup.py +0 -0
  50. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/graphql_warmup_registry.py +0 -0
  51. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/graphql_warmup_tasks.py +0 -0
  52. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/mutation.py +0 -0
  53. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/notification_batching.py +0 -0
  54. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/registry.py +0 -0
  55. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/remote_api.py +0 -0
  56. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/remote_invalidation.py +0 -0
  57. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/api/remote_invalidation_client.py +0 -0
  58. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/apps.py +0 -0
  59. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/as_of.py +0 -0
  60. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/bootstrap.py +0 -0
  61. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/bucket/__init__.py +0 -0
  62. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/bucket/_materialized_bucket.py +0 -0
  63. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/bucket/_ordering.py +0 -0
  64. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/bucket/base_bucket.py +0 -0
  65. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/bucket/calculation_bucket.py +0 -0
  66. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/bucket/database_bucket.py +0 -0
  67. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/bucket/excel_bucket.py +0 -0
  68. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/bucket/group_bucket.py +0 -0
  69. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/bucket/indexing.py +0 -0
  70. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/bucket/projection.py +0 -0
  71. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/bucket/request_bucket.py +0 -0
  72. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/cache/__init__.py +0 -0
  73. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/cache/_dependency_graph.py +0 -0
  74. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/cache/batch_refresh.py +0 -0
  75. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/cache/cache_decorator.py +0 -0
  76. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/cache/cache_tracker.py +0 -0
  77. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/cache/data_change_context.py +0 -0
  78. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/cache/dependency_cache.py +0 -0
  79. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/cache/dependency_matching.py +0 -0
  80. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/cache/dependency_publish.py +0 -0
  81. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/cache/dependency_shards.py +0 -0
  82. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/cache/model_dependency_collector.py +0 -0
  83. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/cache/run_context.py +0 -0
  84. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/cache/run_context_lru.py +0 -0
  85. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/__init__.py +0 -0
  86. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/audit.py +0 -0
  87. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/bootstrap.py +0 -0
  88. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/checks.py +0 -0
  89. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/consumer.py +0 -0
  90. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/context.py +0 -0
  91. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/errors.py +0 -0
  92. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/evals/__init__.py +0 -0
  93. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/evals/__main__.py +0 -0
  94. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/evals/baseline.py +0 -0
  95. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/evals/datasets/basic_queries.yaml +0 -0
  96. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/evals/datasets/demo_readiness.yaml +0 -0
  97. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/evals/datasets/edge_cases.yaml +0 -0
  98. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/evals/datasets/follow_ups.yaml +0 -0
  99. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/evals/datasets/large_schema.yaml +0 -0
  100. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/evals/datasets/multi_hop.yaml +0 -0
  101. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/evals/datasets/planned_orchestration.yaml +0 -0
  102. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/evals/diagnostics.py +0 -0
  103. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/evals/fingerprints.py +0 -0
  104. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/evals/fixtures.py +0 -0
  105. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/evals/judges/__init__.py +0 -0
  106. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/evals/judges/answer_quality.py +0 -0
  107. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/evals/judges/contract.py +0 -0
  108. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/evals/judges/result_accuracy.py +0 -0
  109. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/evals/judges/tool_sequence.py +0 -0
  110. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/evals/readiness.py +0 -0
  111. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/evals/runner.py +0 -0
  112. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/evals/traces.py +0 -0
  113. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/grounding.py +0 -0
  114. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/models.py +0 -0
  115. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/planned/__init__.py +0 -0
  116. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/planned/budget.py +0 -0
  117. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/planned/calculations.py +0 -0
  118. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/planned/catalog.py +0 -0
  119. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/planned/config.py +0 -0
  120. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/planned/events.py +0 -0
  121. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/planned/evidence.py +0 -0
  122. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/planned/models.py +0 -0
  123. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/planned/planner.py +0 -0
  124. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/planned/provider_calls.py +0 -0
  125. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/planned/resolver.py +0 -0
  126. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/planned/routing.py +0 -0
  127. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/planned/scheduler.py +0 -0
  128. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/planned/synthesis.py +0 -0
  129. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/planned/validation.py +0 -0
  130. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/providers/__init__.py +0 -0
  131. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/providers/_shared.py +0 -0
  132. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/providers/anthropic.py +0 -0
  133. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/providers/base.py +0 -0
  134. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/providers/google.py +0 -0
  135. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/providers/ollama.py +0 -0
  136. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/providers/openai.py +0 -0
  137. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/rate_limits.py +0 -0
  138. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/routing.py +0 -0
  139. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/schema_index.py +0 -0
  140. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/settings.py +0 -0
  141. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/signals.py +0 -0
  142. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/system_prompt.py +0 -0
  143. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/tool_metadata.py +0 -0
  144. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/tools.py +0 -0
  145. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/turns.py +0 -0
  146. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/chat/views.py +0 -0
  147. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/conf.py +0 -0
  148. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/dataframes/__init__.py +0 -0
  149. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/dataframes/measurements.py +0 -0
  150. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/factory/__init__.py +0 -0
  151. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/factory/auto_factory.py +0 -0
  152. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/factory/factories.py +0 -0
  153. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/factory/factory_methods.py +0 -0
  154. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/__init__.py +0 -0
  155. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/base_interface.py +0 -0
  156. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/bundles/__init__.py +0 -0
  157. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/bundles/calculation.py +0 -0
  158. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/bundles/database.py +0 -0
  159. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/bundles/excel.py +0 -0
  160. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/bundles/remote_manager.py +0 -0
  161. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/bundles/request.py +0 -0
  162. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/__init__.py +0 -0
  163. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/base.py +0 -0
  164. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/builtin.py +0 -0
  165. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/calculation/__init__.py +0 -0
  166. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/calculation/_compat.py +0 -0
  167. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/calculation/input_resolution.py +0 -0
  168. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/calculation/lifecycle.py +0 -0
  169. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/configuration.py +0 -0
  170. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/core/observability.py +0 -0
  171. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/core/utils.py +0 -0
  172. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/excel/__init__.py +0 -0
  173. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/exceptions.py +0 -0
  174. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/existing_model/__init__.py +0 -0
  175. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/existing_model/_compat.py +0 -0
  176. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/existing_model/resolution.py +0 -0
  177. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/factory.py +0 -0
  178. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/orm/__init__.py +0 -0
  179. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/orm/_compat.py +0 -0
  180. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/orm/bulk.py +0 -0
  181. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/orm/history.py +0 -0
  182. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/orm/lifecycle.py +0 -0
  183. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/orm/mutations.py +0 -0
  184. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/orm/support.py +0 -0
  185. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/orm_utils/__init__.py +0 -0
  186. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/orm_utils/django_manager_utils.py +0 -0
  187. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/orm_utils/field_descriptors.py +0 -0
  188. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/orm_utils/payload_normalizer.py +0 -0
  189. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/orm_utils/update_state.py +0 -0
  190. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/read_only/__init__.py +0 -0
  191. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/read_only/_compat.py +0 -0
  192. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/read_only/_types.py +0 -0
  193. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/read_only/lifecycle.py +0 -0
  194. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/read_only/management.py +0 -0
  195. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/registry.py +0 -0
  196. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/remote_manager.py +0 -0
  197. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/capabilities/request/__init__.py +0 -0
  198. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/excel.py +0 -0
  199. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/excel_store.py +0 -0
  200. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/excel_workbook.py +0 -0
  201. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/infrastructure/__init__.py +0 -0
  202. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/infrastructure/startup_hooks.py +0 -0
  203. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/infrastructure/system_checks.py +0 -0
  204. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/interfaces/__init__.py +0 -0
  205. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/interfaces/calculation.py +0 -0
  206. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/interfaces/database.py +0 -0
  207. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/interfaces/excel.py +0 -0
  208. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/interfaces/existing_model.py +0 -0
  209. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/interfaces/read_only.py +0 -0
  210. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/interfaces/remote_manager.py +0 -0
  211. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/interfaces/request.py +0 -0
  212. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/manifests/__init__.py +0 -0
  213. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/manifests/capability_builder.py +0 -0
  214. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/manifests/capability_manifest.py +0 -0
  215. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/manifests/capability_models.py +0 -0
  216. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/orm_interface.py +0 -0
  217. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/requests.py +0 -0
  218. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/utils/__init__.py +0 -0
  219. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/utils/database_interface_protocols.py +0 -0
  220. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/utils/errors.py +0 -0
  221. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/utils/history.py +0 -0
  222. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/interface/utils/models.py +0 -0
  223. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/logging.py +0 -0
  224. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/management/commands/chat_cleanup.py +0 -0
  225. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/management/commands/cleanup_upload_intents.py +0 -0
  226. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/management/commands/graphql_warmup.py +0 -0
  227. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/management/commands/graphql_warmup_refresh_due.py +0 -0
  228. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/management/commands/search_index.py +0 -0
  229. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/management/commands/search_reconcile.py +0 -0
  230. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/management/commands/seed_manager_landscape.py +0 -0
  231. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/management/commands/shell.py +0 -0
  232. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/management/commands/workflow_drain_outbox.py +0 -0
  233. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/management/commands/workflow_replay_dead_letters.py +0 -0
  234. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/manager/__init__.py +0 -0
  235. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/manager/bulk_create.py +0 -0
  236. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/manager/general_manager.py +0 -0
  237. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/manager/group_manager.py +0 -0
  238. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/manager/input.py +0 -0
  239. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/manager/meta.py +0 -0
  240. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/measurement/__init__.py +0 -0
  241. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/measurement/measurement.py +0 -0
  242. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/measurement/measurement_field.py +0 -0
  243. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/metrics/__init__.py +0 -0
  244. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/metrics/graphql.py +0 -0
  245. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/migrations/0001_initial.py +0 -0
  246. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/migrations/0002_workflow_outbox_scaling_indexes.py +0 -0
  247. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/migrations/0003_workflow_execution_correlation_constraint.py +0 -0
  248. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/migrations/0004_chat_persistence_models.py +0 -0
  249. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/migrations/0004_search_index_state.py +0 -0
  250. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/migrations/0005_merge_chat_search.py +0 -0
  251. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/migrations/0006_chat_pending_confirmation_scoped_ids.py +0 -0
  252. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/migrations/0007_upload_intent.py +0 -0
  253. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/migrations/0008_upload_finalization_versions.py +0 -0
  254. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/migrations/0009_upload_cleanup_state.py +0 -0
  255. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/migrations/0010_chat_pending_confirmation_portable_uniqueness.py +0 -0
  256. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/migrations/0011_search_index_state_dirty_generation.py +0 -0
  257. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/migrations/0012_chat_context_watermarks.py +0 -0
  258. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/migrations/__init__.py +0 -0
  259. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/models.py +0 -0
  260. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/permission/__init__.py +0 -0
  261. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/permission/audit.py +0 -0
  262. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/permission/base_permission.py +0 -0
  263. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/permission/graphql_capabilities.py +0 -0
  264. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/permission/manager_based_permission.py +0 -0
  265. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/permission/mutation_permission.py +0 -0
  266. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/permission/permission_checks.py +0 -0
  267. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/permission/permission_data_manager.py +0 -0
  268. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/permission/utils.py +0 -0
  269. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/public_api_registry.py +0 -0
  270. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/py.typed +0 -0
  271. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/rule/__init__.py +0 -0
  272. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/rule/handler.py +0 -0
  273. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/rule/rule.py +0 -0
  274. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/search/__init__.py +0 -0
  275. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/search/async_tasks.py +0 -0
  276. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/search/backend.py +0 -0
  277. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/search/backend_registry.py +0 -0
  278. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/search/backends/__init__.py +0 -0
  279. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/search/backends/dev.py +0 -0
  280. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/search/backends/meilisearch.py +0 -0
  281. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/search/backends/opensearch.py +0 -0
  282. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/search/backends/typesense.py +0 -0
  283. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/search/checks.py +0 -0
  284. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/search/config.py +0 -0
  285. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/search/indexer.py +0 -0
  286. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/search/invalidation.py +0 -0
  287. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/search/m2m_invalidation.py +0 -0
  288. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/search/models.py +0 -0
  289. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/search/reconciliation.py +0 -0
  290. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/search/registry.py +0 -0
  291. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/search/tasks.py +0 -0
  292. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/search/utils.py +0 -0
  293. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/seeding/__init__.py +0 -0
  294. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/seeding/manager_landscape.py +0 -0
  295. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/uploads/__init__.py +0 -0
  296. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/uploads/adapters.py +0 -0
  297. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/uploads/checks.py +0 -0
  298. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/uploads/config.py +0 -0
  299. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/uploads/errors.py +0 -0
  300. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/uploads/finalization.py +0 -0
  301. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/uploads/graphql.py +0 -0
  302. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/uploads/graphql_types.py +0 -0
  303. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/uploads/metrics.py +0 -0
  304. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/uploads/models.py +0 -0
  305. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/uploads/public.py +0 -0
  306. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/uploads/s3.py +0 -0
  307. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/uploads/services.py +0 -0
  308. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/uploads/tokens.py +0 -0
  309. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/uploads/types.py +0 -0
  310. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/uploads/urls.py +0 -0
  311. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/uploads/views.py +0 -0
  312. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/utils/__init__.py +0 -0
  313. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/utils/_args_to_kwargs.py +0 -0
  314. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/utils/_cache_key_encoder.py +0 -0
  315. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/utils/_make_cache_key.py +0 -0
  316. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/utils/_none_to_zero.py +0 -0
  317. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/utils/filter_parser.py +0 -0
  318. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/utils/format_string.py +0 -0
  319. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/utils/json_encoder.py +0 -0
  320. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/utils/path_mapping.py +0 -0
  321. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/utils/public_api.py +0 -0
  322. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/utils/type_checks.py +0 -0
  323. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/workflow/__init__.py +0 -0
  324. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/workflow/actions.py +0 -0
  325. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/workflow/backend_registry.py +0 -0
  326. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/workflow/backends/__init__.py +0 -0
  327. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/workflow/backends/celery.py +0 -0
  328. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/workflow/backends/local.py +0 -0
  329. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/workflow/backends/n8n.py +0 -0
  330. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/workflow/config.py +0 -0
  331. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/workflow/engine.py +0 -0
  332. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/workflow/event_registry.py +0 -0
  333. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/workflow/events.py +0 -0
  334. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/workflow/models.py +0 -0
  335. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/workflow/signal_bridge.py +0 -0
  336. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/workflow/tasks.py +0 -0
  337. {generalmanager-0.82.0 → generalmanager-0.82.2}/src/general_manager/workflow/telemetry.py +0 -0
  338. {generalmanager-0.82.0 → generalmanager-0.82.2}/tests/test_settings.py +0 -0
  339. {generalmanager-0.82.0 → generalmanager-0.82.2}/tests/test_urls.py +0 -0
  340. {generalmanager-0.82.0 → generalmanager-0.82.2}/tests/testing_asgi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.82.0
3
+ Version: 0.82.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.82.0"
7
+ version = "0.82.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.82.0
3
+ Version: 0.82.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
@@ -82,6 +82,7 @@ src/general_manager/cache/model_dependency_collector.py
82
82
  src/general_manager/cache/run_context.py
83
83
  src/general_manager/cache/run_context_lru.py
84
84
  src/general_manager/cache/signals.py
85
+ src/general_manager/cache/transaction_barrier.py
85
86
  src/general_manager/chat/__init__.py
86
87
  src/general_manager/chat/audit.py
87
88
  src/general_manager/chat/bootstrap.py
@@ -38,7 +38,10 @@ from django.core.exceptions import ObjectDoesNotExist
38
38
  from django.db import DEFAULT_DB_ALIAS, models, transaction
39
39
  from django.utils.module_loading import import_string
40
40
 
41
- from general_manager.api.graphql_identifiers import build_identification_arguments
41
+ from general_manager.api.graphql_identifiers import (
42
+ build_identification_arguments,
43
+ property_identifier_type,
44
+ )
42
45
  from general_manager.bucket.base_bucket import Bucket
43
46
  from general_manager.bucket.group_bucket import GroupBucket
44
47
  from general_manager.cache.dependency_index import (
@@ -929,6 +932,20 @@ class GraphQL:
929
932
  ) in generalManagerClass.Interface.get_graph_ql_properties().items():
930
933
  raw_hint = attr_value.graphql_type_hint
931
934
 
935
+ if attr_value.is_identifier:
936
+ native_type, is_collection = property_identifier_type(
937
+ raw_hint,
938
+ owner_name=generalManagerClass.__name__,
939
+ field_name=attr_name,
940
+ )
941
+ fields[attr_name] = (
942
+ graphene.List(graphene.ID) if is_collection else graphene.ID()
943
+ )
944
+ fields[f"resolve_{attr_name}"] = cls._create_resolver(
945
+ attr_name, native_type
946
+ )
947
+ continue
948
+
932
949
  if _contains_measurement(raw_hint):
933
950
  mapped = map_graphql_output_annotation(
934
951
  raw_hint,
@@ -3,7 +3,9 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from collections.abc import Mapping
6
- from typing import cast
6
+ from types import UnionType
7
+ from typing import Annotated, Union, cast, get_args, get_origin
8
+ from uuid import UUID
7
9
 
8
10
  import graphene
9
11
  from django.db import models
@@ -16,9 +18,49 @@ from general_manager.api.graphql_relations import (
16
18
  get_graphql_manager_registry,
17
19
  resolve_general_manager_type,
18
20
  )
21
+ from general_manager.api.graphql_output import GraphQLOutputAnnotationError
19
22
  from general_manager.manager.general_manager import GeneralManager
20
23
 
21
24
 
25
+ def property_identifier_type(
26
+ annotation: object, *, owner_name: str, field_name: str
27
+ ) -> tuple[type, bool]:
28
+ """Validate an explicit native identity hint and return its type and shape.
29
+
30
+ This shared interpretation lets output and filter builders consume the
31
+ descriptor's public ``is_identifier`` flag without changing its annotation
32
+ or the native resolver value. Optional wrappers do not add non-null output
33
+ constraints to legacy manager properties.
34
+ """
35
+ original_annotation = annotation
36
+
37
+ def unwrap(hint: object) -> object:
38
+ while get_origin(hint) is Annotated:
39
+ hint = get_args(hint)[0]
40
+ if get_origin(hint) in (Union, UnionType):
41
+ members = get_args(hint)
42
+ if len(members) == 2 and type(None) in members:
43
+ return unwrap(next(t for t in members if t is not type(None)))
44
+ return hint
45
+
46
+ annotation = unwrap(annotation)
47
+ origin = get_origin(annotation)
48
+ is_collection = origin in (list, tuple, set)
49
+ if is_collection:
50
+ elements = get_args(annotation)
51
+ if origin is tuple and len(elements) == 2 and elements[1] is Ellipsis:
52
+ elements = elements[:1]
53
+ if elements and (origin is tuple or len(elements) == 1):
54
+ native_type = unwrap(elements[0])
55
+ if native_type in (int, str, UUID) and all(
56
+ unwrap(element) is native_type for element in elements
57
+ ):
58
+ return cast(type, native_type), True
59
+ elif annotation in (int, str, UUID):
60
+ return cast(type, annotation), False
61
+ raise GraphQLOutputAnnotationError(owner_name, field_name, original_annotation)
62
+
63
+
22
64
  def is_orm_identifier_input(manager_class: type[GeneralManager], name: str) -> bool:
23
65
  """Identify the ORM constructor alias addressing the actual model PK."""
24
66
  model = getattr(manager_class.Interface, "_model", None)
@@ -25,6 +25,7 @@ from django.core.exceptions import FieldDoesNotExist
25
25
  from django.db import models
26
26
 
27
27
  from general_manager.conf import get_setting
28
+ from general_manager.api.graphql_identifiers import property_identifier_type
28
29
  from general_manager.api.graphql_ordering import (
29
30
  GraphQLOrderingInputError,
30
31
  create_ordering_types,
@@ -842,12 +843,20 @@ def create_filter_options(
842
843
  continue
843
844
  hints = [t for t in get_args(prop.graphql_type_hint) if t is not type(None)]
844
845
  prop_type = hints[0] if hints else cast(type, prop.graphql_type_hint)
846
+ prop_info: dict[str, object] = {}
847
+ if prop.is_identifier:
848
+ prop_type, _ = property_identifier_type(
849
+ prop.graphql_type_hint,
850
+ owner_name=field_type.__name__,
851
+ field_name=prop_name,
852
+ )
853
+ prop_info["is_identifier"] = True
845
854
  filter_fields = {
846
855
  **filter_fields,
847
856
  **{
848
857
  k: v
849
858
  for k, v in get_filter_options(
850
- prop_type, prop_name, map_field_to_graphene_read
859
+ prop_type, prop_name, map_field_to_graphene_read, prop_info
851
860
  )
852
861
  if v is not None
853
862
  },
@@ -55,7 +55,7 @@ class GraphQLPropertyTimeoutConfigurationError(ValueError):
55
55
  class GraphQLProperty(property):
56
56
  """Descriptor that exposes a resolver with GraphQL metadata and caching.
57
57
 
58
- Stable inspection attributes are `sortable`, `filterable`,
58
+ Stable inspection attributes are `sortable`, `filterable`, `is_identifier`,
59
59
  `query_annotation`, `cache`, `timeout`, `warm_up`, and `graphql_type_hint`.
60
60
  The descriptor preserves normal `property` behavior such as `fget` and
61
61
  `__doc__`, but those values follow Python's property/wraps mechanics rather
@@ -66,6 +66,7 @@ class GraphQLProperty(property):
66
66
 
67
67
  sortable: bool
68
68
  filterable: bool
69
+ is_identifier: bool
69
70
  warm_up: bool
70
71
  query_annotation: object | None
71
72
  timeout: int | None
@@ -77,6 +78,7 @@ class GraphQLProperty(property):
77
78
  *,
78
79
  sortable: bool = False,
79
80
  filterable: bool = False,
81
+ is_identifier: bool = False,
80
82
  query_annotation: object | None = None,
81
83
  cache: GraphQLPropertyCache = "none",
82
84
  timeout: int | None = None,
@@ -101,6 +103,10 @@ class GraphQLProperty(property):
101
103
  filterable: Whether generated GraphQL fields may expose filtering
102
104
  for this property. Stored as supplied; runtime truthiness is not
103
105
  coerced or validated.
106
+ is_identifier: Declare native integer, string, or UUID identities,
107
+ either scalar or a homogeneous list, tuple, or set. Generates
108
+ GraphQL ID output without changing Python values. Unsupported
109
+ annotations raise TypeError during schema generation.
104
110
  query_annotation: Opaque ORM annotation object or callable consumed
105
111
  by database bucket query construction.
106
112
  cache: Resolver cache scope. `"none"` evaluates every access,
@@ -160,6 +166,7 @@ class GraphQLProperty(property):
160
166
 
161
167
  self.sortable = sortable
162
168
  self.filterable = filterable
169
+ self.is_identifier = is_identifier
163
170
  self.query_annotation = query_annotation
164
171
  self.cache = cache
165
172
  self.timeout = timeout
@@ -276,6 +283,7 @@ def graph_ql_property(
276
283
  *,
277
284
  sortable: bool = False,
278
285
  filterable: bool = False,
286
+ is_identifier: bool = False,
279
287
  query_annotation: object | None = None,
280
288
  cache: GraphQLPropertyCache = "run",
281
289
  timeout: int | None = None,
@@ -290,6 +298,7 @@ def graph_ql_property(
290
298
  *,
291
299
  sortable: bool = False,
292
300
  filterable: bool = False,
301
+ is_identifier: bool = False,
293
302
  query_annotation: object | None = None,
294
303
  cache: GraphQLPropertyCache = "run",
295
304
  timeout: int | None = None,
@@ -307,6 +316,13 @@ def graph_ql_property(
307
316
  property.
308
317
  filterable: Whether generated GraphQL fields may expose filtering for
309
318
  this property.
319
+ is_identifier: Explicitly declare native integer, string, or UUID
320
+ identities. Scalars map to ID and homogeneous list, tuple, or set
321
+ collections to [ID], preserving nullable property output and native
322
+ Python values. Optional annotations and optional elements are
323
+ supported. Manager objects, nested collections, ambiguous unions,
324
+ and other scalar types raise TypeError during schema generation.
325
+ Names and query_annotation never infer this flag. Defaults to False.
310
326
  query_annotation: Opaque ORM annotation object or callable consumed by
311
327
  database bucket query construction.
312
328
  cache: Cache scope. `"run"` is the default and memoizes only within the
@@ -354,6 +370,7 @@ def graph_ql_property(
354
370
  sortable=sortable,
355
371
  query_annotation=query_annotation,
356
372
  filterable=filterable,
373
+ is_identifier=is_identifier,
357
374
  cache=cache,
358
375
  timeout=timeout,
359
376
  warm_up=warm_up,
@@ -7,7 +7,8 @@ import random
7
7
  from threading import Event, Thread
8
8
  import time
9
9
  import uuid
10
- from collections.abc import Mapping
10
+ from collections.abc import Iterator, Mapping
11
+ from contextlib import contextmanager
11
12
  from contextvars import ContextVar
12
13
  from datetime import date, datetime
13
14
  from time import perf_counter
@@ -73,6 +74,9 @@ _pending_graphql_rewarm_cache_keys: ContextVar[frozenset[str]] = ContextVar(
73
74
  "general_manager_pending_graphql_rewarm_cache_keys",
74
75
  default=frozenset(),
75
76
  )
77
+ _dependency_rewarm_scope_depth: ContextVar[int] = ContextVar(
78
+ "general_manager_dependency_rewarm_scope_depth", default=0
79
+ )
76
80
 
77
81
 
78
82
  class DependencyLockTimeoutError(TimeoutError):
@@ -118,6 +122,8 @@ DEPENDENCY_GENERATION_KEY = "dependency_index_generation"
118
122
  DATA_CHANGE_LOCK_KEY = "dependency_index_data_change_lock"
119
123
  DATA_CHANGE_COUNT_KEY = "dependency_index_data_change_count"
120
124
  DATA_CHANGE_RECOVERY_KEY = "dependency_index_data_change_recovery"
125
+ DATA_CHANGE_OWNERS_KEY = "dependency_index_data_change_owners"
126
+ COMMITTED_GRAPHQL_REWARM_KEY = "dependency_index_committed_graphql_rewarm"
121
127
  LOCK_TIMEOUT = 5 # Lock TTL in seconds
122
128
  UNDEFINED = object() # Sentinel for undefined values
123
129
  ACTIONS: tuple[Literal["filter"], Literal["exclude"]] = ("filter", "exclude")
@@ -241,6 +247,15 @@ def _set_dependency_data_change_count(count: int) -> int:
241
247
  return count
242
248
 
243
249
 
250
+ def _get_dependency_data_change_owners() -> frozenset[str]:
251
+ owners = cache.get(DATA_CHANGE_OWNERS_KEY, frozenset())
252
+ if not isinstance(owners, frozenset) or not all(
253
+ isinstance(owner, str) for owner in owners
254
+ ):
255
+ raise DependencyBarrierStateError("journal")
256
+ return owners
257
+
258
+
244
259
  def _discard_active_context_dependency_cache_state() -> None:
245
260
  from general_manager.cache.run_context import current_calculation_run_context
246
261
 
@@ -304,10 +319,21 @@ def _clear_data_change_recovery(
304
319
 
305
320
 
306
321
  def _prepare_data_change_recovery(
307
- token: DependencyLockToken, count: int, flag: object
322
+ token: DependencyLockToken,
323
+ count: int,
324
+ flag: object,
325
+ owners: frozenset[str],
326
+ generation: int | None = None,
308
327
  ) -> dict[str, object]:
309
328
  _require_data_change_lock_owner(token)
310
- recovery: dict[str, object] = {"owner": token, "count": count, "flag": flag}
329
+ recovery: dict[str, object] = {
330
+ "owner": token,
331
+ "count": count,
332
+ "flag": flag,
333
+ "owners": owners,
334
+ }
335
+ if generation is not None:
336
+ recovery["generation"] = generation
311
337
  cache.set(DATA_CHANGE_RECOVERY_KEY, recovery, None)
312
338
  _verify_data_change_cache_value(DATA_CHANGE_RECOVERY_KEY, recovery)
313
339
  return recovery
@@ -321,6 +347,24 @@ def _recover_data_change_barrier(token: DependencyLockToken) -> None:
321
347
  # previous snapshot never overwrites a later operation's active barrier.
322
348
  if not isinstance(recovery, dict) or not isinstance(recovery.get("count"), int):
323
349
  raise DependencyBarrierStateError("journal")
350
+ generation = recovery.get("generation")
351
+ if generation is not None:
352
+ if not isinstance(generation, int):
353
+ raise DependencyBarrierStateError("journal")
354
+ _require_data_change_lock_owner(token)
355
+ generation = max(get_dependency_generation(), generation)
356
+ _set_dependency_generation(generation)
357
+ _verify_data_change_cache_value(DEPENDENCY_GENERATION_KEY, generation)
358
+ # Older journals have no owner set. Retain compatibility with #519 recovery.
359
+ if "owners" in recovery:
360
+ owners = recovery["owners"]
361
+ if not isinstance(owners, frozenset) or not all(
362
+ isinstance(owner, str) for owner in owners
363
+ ):
364
+ raise DependencyBarrierStateError("journal")
365
+ _require_data_change_lock_owner(token)
366
+ cache.set(DATA_CHANGE_OWNERS_KEY, owners, None)
367
+ _verify_data_change_cache_value(DATA_CHANGE_OWNERS_KEY, owners)
324
368
  _require_data_change_lock_owner(token)
325
369
  count = recovery["count"]
326
370
  _set_dependency_data_change_count(count)
@@ -359,7 +403,7 @@ def _release_data_change_lock(token: DependencyLockToken) -> None:
359
403
  logger.exception("dependency data-change mutex release failed")
360
404
 
361
405
 
362
- def begin_dependency_data_change() -> int:
406
+ def begin_dependency_data_change(*, owner: str | None = None) -> int:
363
407
  """Open a publish barrier, preserving a recoverable pre-begin snapshot.
364
408
 
365
409
  Failed starts restore only their own count/flag under the mutex. If cleanup
@@ -375,8 +419,11 @@ def begin_dependency_data_change() -> int:
375
419
  _recover_data_change_barrier(lock_token)
376
420
  count = _get_dependency_data_change_count()
377
421
  flag = cache.get(DATA_CHANGE_LOCK_KEY)
378
- recovery = {"owner": lock_token, "count": count, "flag": flag}
379
- _prepare_data_change_recovery(lock_token, count, flag)
422
+ owners = _get_dependency_data_change_owners()
423
+ if owner is not None and owner in owners:
424
+ return get_dependency_generation()
425
+ recovery = {"owner": lock_token, "count": count, "flag": flag, "owners": owners}
426
+ _prepare_data_change_recovery(lock_token, count, flag, owners)
380
427
  _require_data_change_lock_owner(lock_token)
381
428
  generation = _set_dependency_generation(get_dependency_generation() + 1)
382
429
  _verify_data_change_cache_value(DEPENDENCY_GENERATION_KEY, generation)
@@ -386,6 +433,10 @@ def begin_dependency_data_change() -> int:
386
433
  _require_data_change_lock_owner(lock_token)
387
434
  cache.set(DATA_CHANGE_LOCK_KEY, "1", None)
388
435
  _verify_data_change_cache_value(DATA_CHANGE_LOCK_KEY, "1")
436
+ if owner is not None:
437
+ _require_data_change_lock_owner(lock_token)
438
+ cache.set(DATA_CHANGE_OWNERS_KEY, owners | {owner}, None)
439
+ _verify_data_change_cache_value(DATA_CHANGE_OWNERS_KEY, owners | {owner})
389
440
  _discard_active_context_dependency_cache_state()
390
441
  _clear_data_change_recovery(lock_token, recovery)
391
442
  except Exception:
@@ -400,18 +451,35 @@ def begin_dependency_data_change() -> int:
400
451
  return generation
401
452
 
402
453
 
403
- def end_dependency_data_change() -> None:
404
- """Close one barrier, journaling its completed operation for forward recovery."""
454
+ def end_dependency_data_change(*, owner: str | None = None) -> None:
455
+ """Fence in-flight calculations and close one barrier with forward recovery.
456
+
457
+ Owned ends are idempotent, including when cache writes applied then raised.
458
+ A retry completes the journal before checking ownership, so it cannot
459
+ decrement another transaction's barrier.
460
+ """
405
461
  if isinstance(caches["default"], DummyCache):
406
462
  return
407
463
  lock_token = acquire_lock_with_retry("end_dependency_data_change")
408
464
  recovery: dict[str, object] | None = None
409
465
  try:
410
466
  _recover_data_change_barrier(lock_token)
467
+ owners = _get_dependency_data_change_owners()
468
+ if owner is not None and owner not in owners:
469
+ return
470
+ if owner is not None:
471
+ owners = owners - {owner}
411
472
  count = max(_get_dependency_data_change_count() - 1, 0)
412
473
  flag = "1" if count else None
413
- recovery = {"owner": lock_token, "count": count, "flag": flag}
414
- _prepare_data_change_recovery(lock_token, count, flag)
474
+ generation = get_dependency_generation() + 1
475
+ recovery = {
476
+ "owner": lock_token,
477
+ "count": count,
478
+ "flag": flag,
479
+ "owners": owners,
480
+ "generation": generation,
481
+ }
482
+ _prepare_data_change_recovery(lock_token, count, flag, owners, generation)
415
483
  _recover_data_change_barrier(lock_token)
416
484
  except Exception:
417
485
  if recovery is not None:
@@ -449,6 +517,50 @@ def drain_invalidated_cache_keys_for_graphql_rewarm() -> tuple[str, ...]:
449
517
  return cache_keys
450
518
 
451
519
 
520
+ def record_committed_graphql_rewarm_keys(cache_keys: Iterable[str]) -> None:
521
+ """Share committed work with the process that closes the final barrier."""
522
+ keys = frozenset(cache_keys)
523
+ if not keys:
524
+ return
525
+ token = acquire_lock_with_retry("record_committed_graphql_rewarm_keys")
526
+ try:
527
+ existing = cache.get(COMMITTED_GRAPHQL_REWARM_KEY, frozenset())
528
+ cache.set(COMMITTED_GRAPHQL_REWARM_KEY, existing | keys, None)
529
+ finally:
530
+ release_lock(token)
531
+
532
+
533
+ def drain_committed_graphql_rewarm_keys() -> tuple[str, ...]:
534
+ """Claim committed keys only when no writer is pausing publication."""
535
+ if not cache.get(COMMITTED_GRAPHQL_REWARM_KEY):
536
+ return ()
537
+ token = acquire_lock_with_retry("drain_committed_graphql_rewarm_keys")
538
+ try:
539
+ if is_dependency_data_change_active():
540
+ return ()
541
+ keys = tuple(sorted(cache.get(COMMITTED_GRAPHQL_REWARM_KEY, frozenset())))
542
+ cache.delete(COMMITTED_GRAPHQL_REWARM_KEY)
543
+ return keys
544
+ finally:
545
+ release_lock(token)
546
+
547
+
548
+ @contextmanager
549
+ def dependency_rewarm_scope() -> Iterator[None]:
550
+ """Isolate a mutation's keys from enclosing writes on other connections."""
551
+ depth = _dependency_rewarm_scope_depth.get()
552
+ scope_token = _dependency_rewarm_scope_depth.set(depth + 1)
553
+ token = _pending_graphql_rewarm_cache_keys.set(frozenset()) if depth else None
554
+ try:
555
+ yield
556
+ finally:
557
+ if token is not None:
558
+ remaining = _pending_graphql_rewarm_cache_keys.get()
559
+ _pending_graphql_rewarm_cache_keys.reset(token)
560
+ record_invalidated_cache_keys_for_graphql_rewarm(remaining)
561
+ _dependency_rewarm_scope_depth.reset(scope_token)
562
+
563
+
452
564
  def acquire_lock_with_retry(operation: str) -> DependencyLockToken:
453
565
  """
454
566
  Acquire the dependency index lock, retrying with exponential backoff.
@@ -123,6 +123,11 @@ def data_change(
123
123
  is_dependency_data_change_active,
124
124
  )
125
125
  from general_manager.cache.run_context import current_calculation_run_context
126
+ from general_manager.cache.transaction_barrier import (
127
+ collect_transaction_rewarm_keys,
128
+ flush_transaction_rewarm_keys,
129
+ hold_dependency_transaction_barrier,
130
+ )
126
131
  from general_manager.interface.orm_interface import OrmInterfaceBase
127
132
  from general_manager.manager.bulk_create import (
128
133
  CreateManyUnsupportedError,
@@ -179,6 +184,8 @@ def data_change(
179
184
  transaction_outcome = "rolled_back"
180
185
  begin_dependency_data_change()
181
186
  try:
187
+ if is_orm_backed:
188
+ hold_dependency_transaction_barrier(database_alias)
182
189
  context = current_calculation_run_context()
183
190
  if context is not None:
184
191
  context.clear_orm_bucket_results()
@@ -294,6 +301,8 @@ def data_change(
294
301
  sender=sender,
295
302
  **lifecycle_kwargs,
296
303
  )
304
+ if is_orm_backed:
305
+ collect_transaction_rewarm_keys(database_alias, completed=True)
297
306
  if transaction_scope is not None and transaction_scope.is_outermost:
298
307
  transaction_outcome = "committed"
299
308
  completed = True
@@ -333,8 +342,15 @@ def data_change(
333
342
  raise
334
343
  finally:
335
344
  try:
345
+ collected = is_orm_backed and collect_transaction_rewarm_keys(
346
+ database_alias, completed=completed
347
+ )
336
348
  if not is_dependency_data_change_active():
337
- cache_keys = drain_invalidated_cache_keys_for_graphql_rewarm()
349
+ if not collected:
350
+ cache_keys = (
351
+ drain_invalidated_cache_keys_for_graphql_rewarm()
352
+ )
353
+ flush_transaction_rewarm_keys()
338
354
  except Exception:
339
355
  if primary_exc is not None:
340
356
  logger.exception(
@@ -355,9 +371,10 @@ def data_change(
355
371
 
356
372
  @wraps(decorator_source)
357
373
  def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
374
+ from general_manager.cache.dependency_index import dependency_rewarm_scope
358
375
  from general_manager.manager.bulk_create import create_many_signal_scope
359
376
 
360
- with create_many_signal_scope():
377
+ with create_many_signal_scope(), dependency_rewarm_scope():
361
378
  return perform_change(*args, **kwargs)
362
379
 
363
380
  return wrapper