GeneralManager 0.64.0__tar.gz → 0.64.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 (288) hide show
  1. {generalmanager-0.64.0/src/GeneralManager.egg-info → generalmanager-0.64.2}/PKG-INFO +1 -1
  2. {generalmanager-0.64.0 → generalmanager-0.64.2}/pyproject.toml +1 -1
  3. {generalmanager-0.64.0 → generalmanager-0.64.2/src/GeneralManager.egg-info}/PKG-INFO +1 -1
  4. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/GeneralManager.egg-info/SOURCES.txt +1 -0
  5. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/api/graphql.py +42 -9
  6. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/api/graphql_mutations.py +47 -10
  7. generalmanager-0.64.2/src/general_manager/api/graphql_relations.py +180 -0
  8. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/api/graphql_resolvers.py +10 -3
  9. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/api/graphql_search.py +34 -12
  10. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/bootstrap.py +7 -0
  11. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/rule/rule.py +7 -2
  12. {generalmanager-0.64.0 → generalmanager-0.64.2}/LICENSE +0 -0
  13. {generalmanager-0.64.0 → generalmanager-0.64.2}/README.md +0 -0
  14. {generalmanager-0.64.0 → generalmanager-0.64.2}/setup.cfg +0 -0
  15. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/GeneralManager.egg-info/dependency_links.txt +0 -0
  16. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/GeneralManager.egg-info/requires.txt +0 -0
  17. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/GeneralManager.egg-info/top_level.txt +0 -0
  18. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/__init__.py +0 -0
  19. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/_types/__init__.py +0 -0
  20. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/_types/api.py +0 -0
  21. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/_types/bucket.py +0 -0
  22. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/_types/cache.py +0 -0
  23. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/_types/dataframes.py +0 -0
  24. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/_types/factory.py +0 -0
  25. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/_types/general_manager.py +0 -0
  26. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/_types/interface.py +0 -0
  27. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/_types/manager.py +0 -0
  28. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/_types/measurement.py +0 -0
  29. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/_types/permission.py +0 -0
  30. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/_types/rule.py +0 -0
  31. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/_types/search.py +0 -0
  32. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/_types/utils.py +0 -0
  33. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/api/__init__.py +0 -0
  34. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/api/graphql_errors.py +0 -0
  35. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/api/graphql_prefetch.py +0 -0
  36. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/api/graphql_subscription_consumer.py +0 -0
  37. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/api/graphql_subscriptions.py +0 -0
  38. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/api/graphql_view.py +0 -0
  39. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/api/graphql_warmup.py +0 -0
  40. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/api/graphql_warmup_registry.py +0 -0
  41. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/api/graphql_warmup_tasks.py +0 -0
  42. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/api/mutation.py +0 -0
  43. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/api/notification_batching.py +0 -0
  44. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/api/property.py +0 -0
  45. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/api/registry.py +0 -0
  46. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/api/remote_api.py +0 -0
  47. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/api/remote_invalidation.py +0 -0
  48. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/api/remote_invalidation_client.py +0 -0
  49. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/apps.py +0 -0
  50. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/bucket/__init__.py +0 -0
  51. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/bucket/base_bucket.py +0 -0
  52. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/bucket/calculation_bucket.py +0 -0
  53. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/bucket/database_bucket.py +0 -0
  54. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/bucket/group_bucket.py +0 -0
  55. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/bucket/indexing.py +0 -0
  56. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/bucket/request_bucket.py +0 -0
  57. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/cache/__init__.py +0 -0
  58. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/cache/cache_decorator.py +0 -0
  59. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/cache/cache_tracker.py +0 -0
  60. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/cache/dependency_cache.py +0 -0
  61. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/cache/dependency_index.py +0 -0
  62. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/cache/dependency_matching.py +0 -0
  63. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/cache/dependency_publish.py +0 -0
  64. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/cache/dependency_shards.py +0 -0
  65. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/cache/model_dependency_collector.py +0 -0
  66. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/cache/run_context.py +0 -0
  67. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/cache/signals.py +0 -0
  68. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/__init__.py +0 -0
  69. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/audit.py +0 -0
  70. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/bootstrap.py +0 -0
  71. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/checks.py +0 -0
  72. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/consumer.py +0 -0
  73. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/errors.py +0 -0
  74. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/evals/__init__.py +0 -0
  75. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/evals/__main__.py +0 -0
  76. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/evals/baseline.py +0 -0
  77. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/evals/datasets/basic_queries.yaml +0 -0
  78. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/evals/datasets/demo_readiness.yaml +0 -0
  79. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/evals/datasets/edge_cases.yaml +0 -0
  80. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/evals/datasets/follow_ups.yaml +0 -0
  81. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/evals/datasets/large_schema.yaml +0 -0
  82. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/evals/datasets/multi_hop.yaml +0 -0
  83. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/evals/diagnostics.py +0 -0
  84. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/evals/fingerprints.py +0 -0
  85. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/evals/fixtures.py +0 -0
  86. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/evals/judges/__init__.py +0 -0
  87. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/evals/judges/answer_quality.py +0 -0
  88. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/evals/judges/contract.py +0 -0
  89. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/evals/judges/result_accuracy.py +0 -0
  90. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/evals/judges/tool_sequence.py +0 -0
  91. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/evals/readiness.py +0 -0
  92. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/evals/runner.py +0 -0
  93. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/evals/traces.py +0 -0
  94. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/grounding.py +0 -0
  95. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/models.py +0 -0
  96. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/providers/__init__.py +0 -0
  97. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/providers/_shared.py +0 -0
  98. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/providers/anthropic.py +0 -0
  99. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/providers/base.py +0 -0
  100. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/providers/google.py +0 -0
  101. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/providers/ollama.py +0 -0
  102. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/providers/openai.py +0 -0
  103. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/rate_limits.py +0 -0
  104. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/routing.py +0 -0
  105. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/schema_index.py +0 -0
  106. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/settings.py +0 -0
  107. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/signals.py +0 -0
  108. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/system_prompt.py +0 -0
  109. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/tool_metadata.py +0 -0
  110. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/tools.py +0 -0
  111. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/chat/views.py +0 -0
  112. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/conf.py +0 -0
  113. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/dataframes/__init__.py +0 -0
  114. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/dataframes/measurements.py +0 -0
  115. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/factory/__init__.py +0 -0
  116. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/factory/auto_factory.py +0 -0
  117. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/factory/factories.py +0 -0
  118. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/factory/factory_methods.py +0 -0
  119. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/__init__.py +0 -0
  120. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/base_interface.py +0 -0
  121. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/bundles/__init__.py +0 -0
  122. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/bundles/calculation.py +0 -0
  123. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/bundles/database.py +0 -0
  124. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/bundles/remote_manager.py +0 -0
  125. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/bundles/request.py +0 -0
  126. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/__init__.py +0 -0
  127. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/base.py +0 -0
  128. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/builtin.py +0 -0
  129. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/calculation/__init__.py +0 -0
  130. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/calculation/_compat.py +0 -0
  131. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/calculation/lifecycle.py +0 -0
  132. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/configuration.py +0 -0
  133. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/core/observability.py +0 -0
  134. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/core/utils.py +0 -0
  135. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/exceptions.py +0 -0
  136. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/existing_model/__init__.py +0 -0
  137. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/existing_model/_compat.py +0 -0
  138. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/existing_model/resolution.py +0 -0
  139. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/factory.py +0 -0
  140. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/orm/__init__.py +0 -0
  141. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/orm/_compat.py +0 -0
  142. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/orm/history.py +0 -0
  143. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/orm/lifecycle.py +0 -0
  144. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/orm/mutations.py +0 -0
  145. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/orm/support.py +0 -0
  146. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/orm_utils/__init__.py +0 -0
  147. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/orm_utils/django_manager_utils.py +0 -0
  148. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/orm_utils/field_descriptors.py +0 -0
  149. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/orm_utils/payload_normalizer.py +0 -0
  150. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/read_only/__init__.py +0 -0
  151. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/read_only/_compat.py +0 -0
  152. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/read_only/_types.py +0 -0
  153. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/read_only/lifecycle.py +0 -0
  154. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/read_only/management.py +0 -0
  155. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/registry.py +0 -0
  156. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/remote_manager.py +0 -0
  157. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/capabilities/request/__init__.py +0 -0
  158. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/infrastructure/__init__.py +0 -0
  159. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/infrastructure/startup_hooks.py +0 -0
  160. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/infrastructure/system_checks.py +0 -0
  161. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/interfaces/__init__.py +0 -0
  162. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/interfaces/calculation.py +0 -0
  163. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/interfaces/database.py +0 -0
  164. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/interfaces/existing_model.py +0 -0
  165. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/interfaces/read_only.py +0 -0
  166. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/interfaces/remote_manager.py +0 -0
  167. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/interfaces/request.py +0 -0
  168. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/manifests/__init__.py +0 -0
  169. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/manifests/capability_builder.py +0 -0
  170. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/manifests/capability_manifest.py +0 -0
  171. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/manifests/capability_models.py +0 -0
  172. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/orm_interface.py +0 -0
  173. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/requests.py +0 -0
  174. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/utils/__init__.py +0 -0
  175. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/utils/database_interface_protocols.py +0 -0
  176. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/utils/errors.py +0 -0
  177. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/utils/history.py +0 -0
  178. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/interface/utils/models.py +0 -0
  179. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/logging.py +0 -0
  180. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/management/commands/chat_cleanup.py +0 -0
  181. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/management/commands/cleanup_upload_intents.py +0 -0
  182. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/management/commands/graphql_warmup.py +0 -0
  183. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/management/commands/graphql_warmup_refresh_due.py +0 -0
  184. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/management/commands/search_index.py +0 -0
  185. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/management/commands/search_reconcile.py +0 -0
  186. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/management/commands/seed_manager_landscape.py +0 -0
  187. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/management/commands/shell.py +0 -0
  188. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/management/commands/workflow_drain_outbox.py +0 -0
  189. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/management/commands/workflow_replay_dead_letters.py +0 -0
  190. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/manager/__init__.py +0 -0
  191. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/manager/general_manager.py +0 -0
  192. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/manager/group_manager.py +0 -0
  193. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/manager/input.py +0 -0
  194. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/manager/meta.py +0 -0
  195. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/measurement/__init__.py +0 -0
  196. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/measurement/measurement.py +0 -0
  197. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/measurement/measurement_field.py +0 -0
  198. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/metrics/__init__.py +0 -0
  199. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/metrics/graphql.py +0 -0
  200. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/migrations/0001_initial.py +0 -0
  201. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/migrations/0002_workflow_outbox_scaling_indexes.py +0 -0
  202. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/migrations/0003_workflow_execution_correlation_constraint.py +0 -0
  203. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/migrations/0004_chat_persistence_models.py +0 -0
  204. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/migrations/0004_search_index_state.py +0 -0
  205. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/migrations/0005_merge_chat_search.py +0 -0
  206. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/migrations/0006_chat_pending_confirmation_scoped_ids.py +0 -0
  207. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/migrations/0007_upload_intent.py +0 -0
  208. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/migrations/0008_upload_finalization_versions.py +0 -0
  209. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/migrations/0009_upload_cleanup_state.py +0 -0
  210. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/migrations/__init__.py +0 -0
  211. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/models.py +0 -0
  212. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/permission/__init__.py +0 -0
  213. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/permission/audit.py +0 -0
  214. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/permission/base_permission.py +0 -0
  215. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/permission/graphql_capabilities.py +0 -0
  216. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/permission/manager_based_permission.py +0 -0
  217. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/permission/mutation_permission.py +0 -0
  218. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/permission/permission_checks.py +0 -0
  219. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/permission/permission_data_manager.py +0 -0
  220. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/permission/utils.py +0 -0
  221. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/public_api_registry.py +0 -0
  222. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/py.typed +0 -0
  223. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/rule/__init__.py +0 -0
  224. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/rule/handler.py +0 -0
  225. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/search/__init__.py +0 -0
  226. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/search/async_tasks.py +0 -0
  227. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/search/backend.py +0 -0
  228. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/search/backend_registry.py +0 -0
  229. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/search/backends/__init__.py +0 -0
  230. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/search/backends/dev.py +0 -0
  231. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/search/backends/meilisearch.py +0 -0
  232. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/search/backends/opensearch.py +0 -0
  233. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/search/backends/typesense.py +0 -0
  234. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/search/config.py +0 -0
  235. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/search/indexer.py +0 -0
  236. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/search/models.py +0 -0
  237. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/search/reconciliation.py +0 -0
  238. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/search/registry.py +0 -0
  239. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/search/tasks.py +0 -0
  240. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/search/utils.py +0 -0
  241. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/seeding/__init__.py +0 -0
  242. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/seeding/manager_landscape.py +0 -0
  243. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/uploads/__init__.py +0 -0
  244. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/uploads/adapters.py +0 -0
  245. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/uploads/checks.py +0 -0
  246. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/uploads/config.py +0 -0
  247. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/uploads/errors.py +0 -0
  248. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/uploads/finalization.py +0 -0
  249. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/uploads/graphql.py +0 -0
  250. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/uploads/graphql_types.py +0 -0
  251. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/uploads/metrics.py +0 -0
  252. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/uploads/models.py +0 -0
  253. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/uploads/public.py +0 -0
  254. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/uploads/s3.py +0 -0
  255. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/uploads/services.py +0 -0
  256. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/uploads/tokens.py +0 -0
  257. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/uploads/types.py +0 -0
  258. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/uploads/urls.py +0 -0
  259. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/uploads/views.py +0 -0
  260. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/utils/__init__.py +0 -0
  261. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/utils/args_to_kwargs.py +0 -0
  262. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/utils/filter_parser.py +0 -0
  263. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/utils/format_string.py +0 -0
  264. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/utils/json_encoder.py +0 -0
  265. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/utils/make_cache_key.py +0 -0
  266. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/utils/none_to_zero.py +0 -0
  267. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/utils/path_mapping.py +0 -0
  268. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/utils/public_api.py +0 -0
  269. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/utils/testing.py +0 -0
  270. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/utils/type_checks.py +0 -0
  271. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/workflow/__init__.py +0 -0
  272. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/workflow/actions.py +0 -0
  273. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/workflow/backend_registry.py +0 -0
  274. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/workflow/backends/__init__.py +0 -0
  275. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/workflow/backends/celery.py +0 -0
  276. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/workflow/backends/local.py +0 -0
  277. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/workflow/backends/n8n.py +0 -0
  278. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/workflow/config.py +0 -0
  279. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/workflow/engine.py +0 -0
  280. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/workflow/event_registry.py +0 -0
  281. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/workflow/events.py +0 -0
  282. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/workflow/models.py +0 -0
  283. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/workflow/signal_bridge.py +0 -0
  284. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/workflow/tasks.py +0 -0
  285. {generalmanager-0.64.0 → generalmanager-0.64.2}/src/general_manager/workflow/telemetry.py +0 -0
  286. {generalmanager-0.64.0 → generalmanager-0.64.2}/tests/test_settings.py +0 -0
  287. {generalmanager-0.64.0 → generalmanager-0.64.2}/tests/test_urls.py +0 -0
  288. {generalmanager-0.64.0 → generalmanager-0.64.2}/tests/testing_asgi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.64.0
3
+ Version: 0.64.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.64.0"
7
+ version = "0.64.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.64.0
3
+ Version: 0.64.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
@@ -33,6 +33,7 @@ src/general_manager/api/graphql.py
33
33
  src/general_manager/api/graphql_errors.py
34
34
  src/general_manager/api/graphql_mutations.py
35
35
  src/general_manager/api/graphql_prefetch.py
36
+ src/general_manager/api/graphql_relations.py
36
37
  src/general_manager/api/graphql_resolvers.py
37
38
  src/general_manager/api/graphql_search.py
38
39
  src/general_manager/api/graphql_subscription_consumer.py
@@ -101,6 +101,7 @@ from general_manager.api.graphql_resolvers import (
101
101
  create_list_resolver as _create_list_resolver_fn,
102
102
  create_resolver as _create_resolver_fn,
103
103
  )
104
+ from general_manager.api.graphql_relations import resolve_general_manager_type
104
105
  from general_manager.api.graphql_search import (
105
106
  register_search_query as _register_search_query_fn,
106
107
  create_search_union as _create_search_union_fn,
@@ -546,8 +547,13 @@ class GraphQL:
546
547
  # Map Attribute Types to Graphene Fields
547
548
  for field_name, field_info in interface_cls.get_attribute_types().items():
548
549
  field_type = field_info["type"]
549
- fields[field_name] = cls._map_field_to_graphene_read(
550
+ resolved_manager_type = resolve_general_manager_type(
550
551
  field_type,
552
+ cls.manager_registry,
553
+ )
554
+ resolved_field_type = resolved_manager_type or field_type
555
+ fields[field_name] = cls._map_field_to_graphene_read(
556
+ resolved_field_type,
551
557
  field_name,
552
558
  field_info,
553
559
  )
@@ -576,7 +582,10 @@ class GraphQL:
576
582
 
577
583
  fields[resolver_name] = resolve_stored_file
578
584
  else:
579
- fields[resolver_name] = cls._create_resolver(field_name, field_type)
585
+ fields[resolver_name] = cls._create_resolver(
586
+ field_name,
587
+ resolved_field_type,
588
+ )
580
589
 
581
590
  # handle GraphQLProperty attributes
582
591
  for (
@@ -594,9 +603,13 @@ class GraphQL:
594
603
 
595
604
  if origin in (list, tuple, set):
596
605
  element = type_args[0] if type_args else object
597
- if isinstance(element, type) and issubclass(element, GeneralManager):
606
+ manager_type = resolve_general_manager_type(
607
+ element,
608
+ cls.manager_registry,
609
+ )
610
+ if manager_type is not None:
598
611
  graphene_field = graphene.List(
599
- lambda elem=element: GraphQL.graphql_type_registry[
612
+ lambda elem=manager_type: GraphQL.graphql_type_registry[
600
613
  elem.__name__
601
614
  ]
602
615
  )
@@ -605,13 +618,22 @@ class GraphQL:
605
618
  element if isinstance(element, type) else str
606
619
  )
607
620
  graphene_field = graphene.List(base_type)
608
- resolved_type = element if isinstance(element, type) else str
621
+ resolved_type = manager_type or (
622
+ element if isinstance(element, type) else str
623
+ )
609
624
  else:
610
625
  resolved_type = (
611
626
  cast(type[object], type_args[0])
612
627
  if type_args
613
628
  else cast(type[object], raw_hint)
614
629
  )
630
+ resolved_type = (
631
+ resolve_general_manager_type(
632
+ resolved_type,
633
+ cls.manager_registry,
634
+ )
635
+ or resolved_type
636
+ )
615
637
  graphene_field = cls._map_field_to_graphene_read(
616
638
  resolved_type, attr_name
617
639
  )
@@ -821,7 +843,7 @@ class GraphQL:
821
843
  field_info,
822
844
  ) in generalManagerClass.Interface.get_attribute_types().items():
823
845
  field_type = field_info["type"]
824
- if safe_issubclass(field_type, GeneralManager):
846
+ if resolve_general_manager_type(field_type, GraphQL.manager_registry):
825
847
  continue
826
848
  else:
827
849
  sort_options.append(field_name)
@@ -970,7 +992,7 @@ class GraphQL:
970
992
 
971
993
  @staticmethod
972
994
  def _map_field_to_graphene_read(
973
- field_type: type,
995
+ field_type: object,
974
996
  field_name: str,
975
997
  field_info: Mapping[str, object] | None = None,
976
998
  ) -> object:
@@ -998,6 +1020,13 @@ class GraphQL:
998
1020
  Returns:
999
1021
  object: Graphene field or type configured for the attribute.
1000
1022
  """
1023
+ manager_type = resolve_general_manager_type(
1024
+ field_type,
1025
+ GraphQL.manager_registry,
1026
+ )
1027
+ if manager_type is not None:
1028
+ field_type = manager_type
1029
+
1001
1030
  if safe_issubclass(field_type, Measurement):
1002
1031
  return graphene.Field(MeasurementType, target_unit=graphene.String())
1003
1032
  elif safe_issubclass(field_type, GeneralManager):
@@ -1032,8 +1061,9 @@ class GraphQL:
1032
1061
  return graphene.Field(StoredFile)
1033
1062
  if orm_field_kind == "image":
1034
1063
  return graphene.Field(StoredImage)
1064
+ scalar_type = cast(type, field_type)
1035
1065
  return GraphQL._map_field_to_graphene_base_type(
1036
- field_type,
1066
+ scalar_type,
1037
1067
  field_info,
1038
1068
  )()
1039
1069
 
@@ -1191,7 +1221,10 @@ class GraphQL:
1191
1221
  input_field_name,
1192
1222
  input_field,
1193
1223
  ) in generalManagerClass.Interface.input_fields.items():
1194
- if safe_issubclass(input_field.type, GeneralManager):
1224
+ if resolve_general_manager_type(
1225
+ input_field.type,
1226
+ cls.manager_registry,
1227
+ ):
1195
1228
  key = f"{input_field_name}_id"
1196
1229
  identification_fields[key] = graphene.Argument(
1197
1230
  graphene.ID, required=input_field.required
@@ -21,11 +21,14 @@ from django.db import models
21
21
  from django.core.exceptions import FieldDoesNotExist
22
22
 
23
23
  from general_manager.interface.base_interface import AttributeTypedDict, InterfaceBase
24
+ from general_manager.api.graphql_relations import (
25
+ get_graphql_manager_registry,
26
+ resolve_general_manager_type,
27
+ )
24
28
  from general_manager.manager.general_manager import GeneralManager
25
29
  from general_manager.uploads.errors import UploadError, stable_upload_error
26
30
  from general_manager.uploads.graphql_types import UploadToken
27
31
  from general_manager.uploads.types import UploadOperation
28
- from general_manager.utils.type_checks import safe_issubclass
29
32
  from general_manager.utils.format_string import snake_to_camel
30
33
  from general_manager.api.graphql_errors import (
31
34
  MissingManagerIdentifierError,
@@ -166,13 +169,20 @@ def _normalize_mutation_kwargs_for_manager(
166
169
 
167
170
  attribute_types = interface_cls.get_attribute_types()
168
171
  normalized = dict(kwargs)
172
+ manager_registry = get_graphql_manager_registry()
169
173
 
170
174
  for key in list(kwargs.keys()):
171
175
  if key.endswith("_list") and not key.endswith("_id_list"):
172
176
  base_key = key.removesuffix("_list")
173
177
  type_info = attribute_types.get(key)
174
178
  relation_type = type_info["type"] if type_info is not None else None
175
- if safe_issubclass(relation_type, GeneralManager):
179
+ if (
180
+ resolve_general_manager_type(
181
+ relation_type,
182
+ manager_registry,
183
+ )
184
+ is not None
185
+ ):
176
186
  normalized.setdefault(f"{base_key}_id_list", normalized[key])
177
187
  normalized.pop(key, None)
178
188
  continue
@@ -180,7 +190,13 @@ def _normalize_mutation_kwargs_for_manager(
180
190
  if not key.endswith("_id"):
181
191
  type_info = attribute_types.get(key)
182
192
  relation_type = type_info["type"] if type_info is not None else None
183
- if safe_issubclass(relation_type, GeneralManager):
193
+ if (
194
+ resolve_general_manager_type(
195
+ relation_type,
196
+ manager_registry,
197
+ )
198
+ is not None
199
+ ):
184
200
  normalized.setdefault(f"{key}_id", normalized[key])
185
201
  normalized.pop(key, None)
186
202
 
@@ -196,20 +212,23 @@ def _graphql_mutation_field_name(
196
212
  return snake_to_camel(field_name)
197
213
 
198
214
  attribute_types = interface_cls.get_attribute_types()
215
+ manager_registry = get_graphql_manager_registry()
199
216
 
200
217
  if field_name.endswith("_id_list"):
201
218
  relation_name = f"{field_name.removesuffix('_id_list')}_list"
202
219
  relation_info = attribute_types.get(relation_name)
203
- if relation_info is not None and safe_issubclass(
204
- relation_info["type"], GeneralManager
220
+ if relation_info is not None and resolve_general_manager_type(
221
+ relation_info["type"],
222
+ manager_registry,
205
223
  ):
206
224
  return snake_to_camel(relation_name)
207
225
 
208
226
  if field_name.endswith("_id"):
209
227
  relation_name = field_name.removesuffix("_id")
210
228
  relation_info = attribute_types.get(relation_name)
211
- if relation_info is not None and safe_issubclass(
212
- relation_info["type"], GeneralManager
229
+ if relation_info is not None and resolve_general_manager_type(
230
+ relation_info["type"],
231
+ manager_registry,
213
232
  ):
214
233
  return snake_to_camel(relation_name)
215
234
 
@@ -224,6 +243,7 @@ def _graphql_mutation_field_name(
224
243
  def _is_direct_relation_raw_id_alias(
225
244
  name: str,
226
245
  attribute_types: dict[str, AttributeTypedDict],
246
+ manager_registry: dict[str, type[GeneralManager]],
227
247
  ) -> bool:
228
248
  """Return true when ``name`` is a raw relation id alias with a canonical field."""
229
249
  if name.endswith("_id_list"):
@@ -231,7 +251,13 @@ def _is_direct_relation_raw_id_alias(
231
251
  relation_info = attribute_types.get(relation_name)
232
252
  if relation_info is None:
233
253
  return False
234
- return safe_issubclass(relation_info["type"], GeneralManager)
254
+ return (
255
+ resolve_general_manager_type(
256
+ relation_info["type"],
257
+ manager_registry,
258
+ )
259
+ is not None
260
+ )
235
261
 
236
262
  if not name.endswith("_id"):
237
263
  return False
@@ -292,12 +318,17 @@ def create_write_fields(
292
318
  """
293
319
  fields: GrapheneFieldMap = {}
294
320
  attribute_types = interface_cls.get_attribute_types()
321
+ manager_registry = get_graphql_manager_registry()
295
322
  for name, info in attribute_types.items():
296
323
  if name in ["changed_by", "created_at", "updated_at"]:
297
324
  continue
298
325
  if info["is_derived"]:
299
326
  continue
300
- if _is_direct_relation_raw_id_alias(name, attribute_types):
327
+ if _is_direct_relation_raw_id_alias(
328
+ name,
329
+ attribute_types,
330
+ manager_registry,
331
+ ):
301
332
  continue
302
333
 
303
334
  typ = info["type"]
@@ -307,7 +338,13 @@ def create_write_fields(
307
338
  fld: object
308
339
  if info.get("orm_field_kind") in {"file", "image"}:
309
340
  fld = UploadToken(required=req, default_value=default)
310
- elif safe_issubclass(typ, GeneralManager):
341
+ elif (
342
+ resolve_general_manager_type(
343
+ typ,
344
+ manager_registry,
345
+ )
346
+ is not None
347
+ ):
311
348
  if name.endswith("_list"):
312
349
  fld = graphene.List(graphene.ID, required=req, default_value=default)
313
350
  else:
@@ -0,0 +1,180 @@
1
+ """Resolve manager targets from GraphQL relation annotations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import ast
6
+ from collections.abc import Mapping
7
+ from types import UnionType
8
+ from typing import ForwardRef, Union, get_args, get_origin
9
+
10
+ from general_manager.bucket.base_bucket import Bucket
11
+ from general_manager.manager.general_manager import GeneralManager
12
+ from general_manager.utils.type_checks import safe_issubclass
13
+
14
+
15
+ def get_graphql_manager_registry() -> dict[str, type[GeneralManager]]:
16
+ """Return the live GraphQL manager registry without an import-time cycle."""
17
+ from general_manager.api.graphql import GraphQL
18
+
19
+ return GraphQL.manager_registry
20
+
21
+
22
+ def resolve_general_manager_type(
23
+ declared_type: object,
24
+ manager_registry: Mapping[str, type[GeneralManager]] | None = None,
25
+ ) -> type[GeneralManager] | None:
26
+ """Return the single manager target represented by ``declared_type``.
27
+
28
+ Concrete manager classes, interface model classes carrying a manager
29
+ back-reference, supported collection annotations, optional unions, and
30
+ postponed string forms of those annotations are recognized. Ambiguous
31
+ annotations containing multiple manager targets return ``None``.
32
+ """
33
+ registry = manager_registry or {}
34
+ resolved = _collect_general_manager_types(declared_type, registry, set())
35
+ if len(resolved) != 1:
36
+ return None
37
+ return next(iter(resolved))
38
+
39
+
40
+ def _collect_general_manager_types(
41
+ declared_type: object,
42
+ manager_registry: Mapping[str, type[GeneralManager]],
43
+ seen: set[int],
44
+ ) -> set[type[GeneralManager]]:
45
+ value_id = id(declared_type)
46
+ if value_id in seen:
47
+ return set()
48
+ seen.add(value_id)
49
+
50
+ if safe_issubclass(declared_type, GeneralManager):
51
+ return {declared_type}
52
+
53
+ related_manager_type = getattr(declared_type, "_general_manager_class", None)
54
+ if safe_issubclass(related_manager_type, GeneralManager):
55
+ return {related_manager_type}
56
+
57
+ if isinstance(declared_type, ForwardRef):
58
+ declared_type = declared_type.__forward_arg__
59
+ if isinstance(declared_type, str):
60
+ manager_type = manager_registry.get(declared_type)
61
+ if manager_type is not None:
62
+ return {manager_type}
63
+ return _collect_string_general_manager_types(
64
+ declared_type,
65
+ manager_registry,
66
+ set(),
67
+ )
68
+
69
+ origin = get_origin(declared_type)
70
+ if origin is None:
71
+ return set()
72
+ if origin not in {list, tuple, set, Union, UnionType} and not safe_issubclass(
73
+ origin, Bucket
74
+ ):
75
+ return set()
76
+
77
+ manager_types: set[type[GeneralManager]] = set()
78
+ for argument in get_args(declared_type):
79
+ if argument is None or argument is type(None) or argument is Ellipsis:
80
+ continue
81
+ manager_types.update(
82
+ _collect_general_manager_types(argument, manager_registry, seen)
83
+ )
84
+ return manager_types
85
+
86
+
87
+ _SUPPORTED_STRING_WRAPPERS = {
88
+ "Bucket",
89
+ "List",
90
+ "Optional",
91
+ "Set",
92
+ "Tuple",
93
+ "Union",
94
+ "list",
95
+ "set",
96
+ "tuple",
97
+ }
98
+
99
+
100
+ def _collect_string_general_manager_types(
101
+ annotation: str,
102
+ manager_registry: Mapping[str, type[GeneralManager]],
103
+ seen: set[str],
104
+ ) -> set[type[GeneralManager]]:
105
+ expression = annotation.strip()
106
+ if not expression or expression in seen:
107
+ return set()
108
+ seen.add(expression)
109
+
110
+ try:
111
+ node = ast.parse(expression, mode="eval").body
112
+ except (SyntaxError, ValueError):
113
+ return set()
114
+ return _collect_annotation_node_manager_types(node, manager_registry, seen)
115
+
116
+
117
+ def _collect_annotation_node_manager_types(
118
+ node: ast.expr,
119
+ manager_registry: Mapping[str, type[GeneralManager]],
120
+ seen: set[str],
121
+ ) -> set[type[GeneralManager]]:
122
+ if isinstance(node, ast.Name):
123
+ manager_type = manager_registry.get(node.id)
124
+ return {manager_type} if manager_type is not None else set()
125
+
126
+ if isinstance(node, ast.Constant):
127
+ if isinstance(node.value, str):
128
+ return _collect_string_general_manager_types(
129
+ node.value,
130
+ manager_registry,
131
+ seen,
132
+ )
133
+ return set()
134
+
135
+ if isinstance(node, ast.Subscript):
136
+ wrapper_name = _annotation_node_name(node.value)
137
+ if wrapper_name is None or wrapper_name.rsplit(".", 1)[-1] not in (
138
+ _SUPPORTED_STRING_WRAPPERS
139
+ ):
140
+ return set()
141
+ return _collect_annotation_node_manager_types(
142
+ node.slice,
143
+ manager_registry,
144
+ seen,
145
+ )
146
+
147
+ if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
148
+ return _collect_annotation_node_manager_types(
149
+ node.left,
150
+ manager_registry,
151
+ seen,
152
+ ) | _collect_annotation_node_manager_types(
153
+ node.right,
154
+ manager_registry,
155
+ seen,
156
+ )
157
+
158
+ if isinstance(node, ast.Tuple):
159
+ manager_types: set[type[GeneralManager]] = set()
160
+ for element in node.elts:
161
+ manager_types.update(
162
+ _collect_annotation_node_manager_types(
163
+ element,
164
+ manager_registry,
165
+ seen,
166
+ )
167
+ )
168
+ return manager_types
169
+
170
+ return set()
171
+
172
+
173
+ def _annotation_node_name(node: ast.expr) -> str | None:
174
+ if isinstance(node, ast.Name):
175
+ return node.id
176
+ if isinstance(node, ast.Attribute):
177
+ parent_name = _annotation_node_name(node.value)
178
+ if parent_name is not None:
179
+ return f"{parent_name}.{node.attr}"
180
+ return None
@@ -24,6 +24,10 @@ from general_manager.bucket.group_bucket import GroupBucket
24
24
  from general_manager.manager.general_manager import GeneralManager
25
25
  from general_manager.measurement.measurement import Measurement
26
26
  from general_manager.api.graphql_errors import get_read_permission_filter
27
+ from general_manager.api.graphql_relations import (
28
+ get_graphql_manager_registry,
29
+ resolve_general_manager_type,
30
+ )
27
31
  from general_manager.api.graphql_prefetch import (
28
32
  collect_selected_graphql_property_names,
29
33
  plan_dependency_cache_prefetches,
@@ -834,7 +838,7 @@ def _selection_set_includes_path(
834
838
 
835
839
  def create_resolver(
836
840
  field_name: str,
837
- field_type: type[object],
841
+ field_type: object,
838
842
  filter_normalizer: ManagerFilterNormalizer | None = None,
839
843
  ) -> Resolver:
840
844
  """
@@ -845,8 +849,11 @@ def create_resolver(
845
849
  :class:`~general_manager.measurement.Measurement` fields, and
846
850
  :func:`create_normal_resolver` for everything else.
847
851
  """
848
- if field_name.endswith("_list") and safe_issubclass(field_type, GeneralManager):
849
- manager_field_type = cast(type[GeneralManager], field_type)
852
+ manager_field_type = resolve_general_manager_type(
853
+ field_type,
854
+ get_graphql_manager_registry(),
855
+ )
856
+ if field_name.endswith("_list") and manager_field_type is not None:
850
857
  return create_list_resolver(
851
858
  lambda self, _include_inactive: cast(
852
859
  Bucket[GeneralManager],
@@ -41,6 +41,10 @@ from general_manager.api.graphql_errors import (
41
41
  map_field_to_graphene_base_type,
42
42
  get_read_permission_filter,
43
43
  )
44
+ from general_manager.api.graphql_relations import (
45
+ get_graphql_manager_registry,
46
+ resolve_general_manager_type,
47
+ )
44
48
  from general_manager.api.graphql_resolvers import (
45
49
  can_read_instance,
46
50
  get_backend_shape,
@@ -538,9 +542,15 @@ def get_filter_options(
538
542
  "endswith",
539
543
  ]
540
544
 
541
- normalized_type = attribute_type if isinstance(attribute_type, type) else str
545
+ manager_type = resolve_general_manager_type(
546
+ attribute_type,
547
+ get_graphql_manager_registry(),
548
+ )
549
+ normalized_type = manager_type or (
550
+ attribute_type if isinstance(attribute_type, type) else str
551
+ )
542
552
 
543
- if safe_issubclass(normalized_type, GeneralManager):
553
+ if manager_type is not None:
544
554
  yield attribute_name, None
545
555
  elif attribute_name == "id":
546
556
  yield attribute_name, graphene.ID()
@@ -591,7 +601,7 @@ def get_filter_options(
591
601
 
592
602
 
593
603
  def get_relation_filter_option(
594
- attribute_type: type,
604
+ attribute_type: object,
595
605
  attribute_name: str,
596
606
  attr_info: Mapping[str, object],
597
607
  graphql_filter_type_registry: dict[str, type[graphene.InputObjectType]],
@@ -614,7 +624,11 @@ def get_relation_filter_option(
614
624
  """
615
625
  if remaining_depth <= 0:
616
626
  return None
617
- if not safe_issubclass(attribute_type, GeneralManager):
627
+ manager_type = resolve_general_manager_type(
628
+ attribute_type,
629
+ get_graphql_manager_registry(),
630
+ )
631
+ if manager_type is None:
618
632
  return None
619
633
 
620
634
  relation_kind = attr_info.get("relation_kind")
@@ -622,7 +636,7 @@ def get_relation_filter_option(
622
636
  return None
623
637
 
624
638
  nested_type = create_filter_options(
625
- attribute_type,
639
+ manager_type,
626
640
  graphql_filter_type_registry,
627
641
  map_field_to_graphene_read,
628
642
  relation_depth=remaining_depth - 1,
@@ -633,7 +647,7 @@ def get_relation_filter_option(
633
647
 
634
648
  if relation_kind == "collection":
635
649
  relation_type_name = (
636
- f"{attribute_type.__name__}{attribute_name.title().replace('_', '')}"
650
+ f"{manager_type.__name__}{attribute_name.title().replace('_', '')}"
637
651
  f"RelationFilterTypeDepth{remaining_depth - 1}"
638
652
  )
639
653
  if relation_type_name not in graphql_filter_type_registry:
@@ -700,9 +714,13 @@ def create_filter_options(
700
714
  filter_fields: dict[str, GrapheneFieldType] = {}
701
715
  for attr_name, attr_info in field_type.Interface.get_attribute_types().items():
702
716
  attr_type = attr_info["type"]
703
- if safe_issubclass(attr_type, GeneralManager):
717
+ manager_type = resolve_general_manager_type(
718
+ attr_type,
719
+ get_graphql_manager_registry(),
720
+ )
721
+ if manager_type is not None:
704
722
  relation_option = get_relation_filter_option(
705
- attr_type,
723
+ manager_type,
706
724
  attr_name,
707
725
  attr_info,
708
726
  graphql_filter_type_registry,
@@ -826,12 +844,16 @@ def normalize_filter_input(
826
844
  attr_type = attr_info.get("type")
827
845
  relation_kind = attr_info.get("relation_kind")
828
846
  lookup = attr_info.get("filter_lookup", key)
829
- if not safe_issubclass(attr_type, GeneralManager) or relation_kind is None:
847
+ manager_type = resolve_general_manager_type(
848
+ attr_type,
849
+ get_graphql_manager_registry(),
850
+ )
851
+ if manager_type is None or relation_kind is None:
830
852
  filters[key] = value
831
853
  continue
832
854
 
833
855
  if relation_kind == "direct":
834
- nested = normalize_filter_input(attr_type, value)
856
+ nested = normalize_filter_input(manager_type, value)
835
857
  for nested_key, nested_value in nested["filter"].items():
836
858
  filters[f"{lookup}__{nested_key}"] = nested_value
837
859
  for nested_key, nested_value in nested["exclude"].items():
@@ -842,13 +864,13 @@ def normalize_filter_input(
842
864
  any_value = value.get("any")
843
865
  none_value = value.get("none")
844
866
  if isinstance(any_value, dict):
845
- nested = normalize_filter_input(attr_type, any_value)
867
+ nested = normalize_filter_input(manager_type, any_value)
846
868
  for nested_key, nested_value in nested["filter"].items():
847
869
  filters[f"{lookup}__{nested_key}"] = nested_value
848
870
  for nested_key, nested_value in nested["exclude"].items():
849
871
  excludes[f"{lookup}__{nested_key}"] = nested_value
850
872
  if isinstance(none_value, dict):
851
- nested = normalize_filter_input(attr_type, none_value)
873
+ nested = normalize_filter_input(manager_type, none_value)
852
874
  for nested_key, nested_value in nested["filter"].items():
853
875
  excludes[f"{lookup}__{nested_key}"] = nested_value
854
876
  for nested_key, nested_value in nested["exclude"].items():
@@ -522,6 +522,13 @@ def handle_graph_ql(
522
522
  "creating graphql interfaces and mutations",
523
523
  context={"pending": len(pending_graphql_interfaces)},
524
524
  )
525
+ GraphQL.manager_registry.update(
526
+ {
527
+ general_manager_class.__name__: general_manager_class
528
+ for general_manager_class in pending_graphql_interfaces
529
+ if getattr(general_manager_class, "Interface", None) is not None
530
+ }
531
+ )
525
532
  for general_manager_class in pending_graphql_interfaces:
526
533
  GraphQL.create_graphql_interface(general_manager_class)
527
534
  GraphQL.create_graphql_mutation(general_manager_class)
@@ -311,10 +311,15 @@ class Rule(Generic[GeneralManagerType]):
311
311
  Returns:
312
312
  dict[str, str] | None: Mapping keyed by referenced variables or
313
313
  Django's `NON_FIELD_ERRORS` fallback when no variables are available;
314
- `None` if the predicate passed or was not evaluated.
314
+ `None` if the predicate passed, was skipped, or has not been evaluated.
315
315
 
316
316
  Raises:
317
- ErrorMessageGenerationError: If called before any input has been evaluated.
317
+ MissingErrorTemplateVariableError: If a failed rule's custom message
318
+ omits a placeholder for a referenced variable.
319
+ ErrorMessageGenerationError: If internal evaluation state records a
320
+ failed result without retaining its evaluated input.
321
+ Exception: A matching rule handler's documented message-generation
322
+ exceptions propagate unchanged.
318
323
  """
319
324
  if self._last_result or self._last_result is None:
320
325
  return None
File without changes