GeneralManager 0.85.0__tar.gz → 0.86.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (342) hide show
  1. {generalmanager-0.85.0/src/GeneralManager.egg-info → generalmanager-0.86.1}/PKG-INFO +1 -1
  2. {generalmanager-0.85.0 → generalmanager-0.86.1}/pyproject.toml +1 -1
  3. {generalmanager-0.85.0 → generalmanager-0.86.1/src/GeneralManager.egg-info}/PKG-INFO +1 -1
  4. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/graphql.py +120 -33
  5. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/graphql_identifiers.py +22 -3
  6. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/graphql_resolvers.py +13 -3
  7. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/graphql_search.py +4 -0
  8. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/graphql_subscriptions.py +8 -3
  9. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/mutation.py +5 -0
  10. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/bootstrap.py +5 -1
  11. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/bucket/calculation_bucket.py +117 -16
  12. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/base_interface.py +31 -1
  13. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/calculation/input_resolution.py +11 -3
  14. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/manager/general_manager.py +25 -2
  15. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/manager/input.py +152 -2
  16. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/manager/meta.py +10 -0
  17. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/utils/filter_parser.py +61 -7
  18. {generalmanager-0.85.0 → generalmanager-0.86.1}/LICENSE +0 -0
  19. {generalmanager-0.85.0 → generalmanager-0.86.1}/README.md +0 -0
  20. {generalmanager-0.85.0 → generalmanager-0.86.1}/setup.cfg +0 -0
  21. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/GeneralManager.egg-info/SOURCES.txt +0 -0
  22. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/GeneralManager.egg-info/dependency_links.txt +0 -0
  23. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/GeneralManager.egg-info/requires.txt +0 -0
  24. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/GeneralManager.egg-info/top_level.txt +0 -0
  25. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/__init__.py +0 -0
  26. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/_types/__init__.py +0 -0
  27. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/_types/api.py +0 -0
  28. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/_types/bucket.py +0 -0
  29. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/_types/cache.py +0 -0
  30. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/_types/dataframes.py +0 -0
  31. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/_types/factory.py +0 -0
  32. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/_types/general_manager.py +0 -0
  33. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/_types/interface.py +0 -0
  34. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/_types/manager.py +0 -0
  35. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/_types/measurement.py +0 -0
  36. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/_types/permission.py +0 -0
  37. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/_types/rule.py +0 -0
  38. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/_types/search.py +0 -0
  39. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/_types/utils.py +0 -0
  40. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/__init__.py +0 -0
  41. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/graphql_as_of.py +0 -0
  42. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/graphql_errors.py +0 -0
  43. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/graphql_groups.py +0 -0
  44. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/graphql_mutations.py +0 -0
  45. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/graphql_ordering.py +0 -0
  46. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/graphql_output.py +0 -0
  47. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/graphql_prefetch.py +0 -0
  48. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/graphql_relations.py +0 -0
  49. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/graphql_subscription_consumer.py +0 -0
  50. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/graphql_type.py +0 -0
  51. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/graphql_view.py +0 -0
  52. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/graphql_warmup.py +0 -0
  53. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/graphql_warmup_registry.py +0 -0
  54. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/graphql_warmup_tasks.py +0 -0
  55. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/notification_batching.py +0 -0
  56. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/property.py +0 -0
  57. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/registry.py +0 -0
  58. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/remote_api.py +0 -0
  59. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/remote_invalidation.py +0 -0
  60. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/api/remote_invalidation_client.py +0 -0
  61. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/apps.py +0 -0
  62. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/as_of.py +0 -0
  63. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/bucket/__init__.py +0 -0
  64. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/bucket/_materialized_bucket.py +0 -0
  65. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/bucket/_ordering.py +0 -0
  66. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/bucket/base_bucket.py +0 -0
  67. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/bucket/database_bucket.py +0 -0
  68. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/bucket/excel_bucket.py +0 -0
  69. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/bucket/group_bucket.py +0 -0
  70. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/bucket/indexing.py +0 -0
  71. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/bucket/projection.py +0 -0
  72. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/bucket/request_bucket.py +0 -0
  73. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/cache/__init__.py +0 -0
  74. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/cache/_dependency_graph.py +0 -0
  75. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/cache/batch_refresh.py +0 -0
  76. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/cache/cache_decorator.py +0 -0
  77. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/cache/cache_tracker.py +0 -0
  78. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/cache/data_change_context.py +0 -0
  79. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/cache/dependency_cache.py +0 -0
  80. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/cache/dependency_index.py +0 -0
  81. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/cache/dependency_matching.py +0 -0
  82. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/cache/dependency_publish.py +0 -0
  83. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/cache/dependency_shards.py +0 -0
  84. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/cache/model_dependency_collector.py +0 -0
  85. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/cache/run_context.py +0 -0
  86. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/cache/run_context_lru.py +0 -0
  87. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/cache/signals.py +0 -0
  88. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/cache/transaction_barrier.py +0 -0
  89. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/__init__.py +0 -0
  90. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/audit.py +0 -0
  91. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/bootstrap.py +0 -0
  92. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/checks.py +0 -0
  93. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/consumer.py +0 -0
  94. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/context.py +0 -0
  95. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/errors.py +0 -0
  96. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/evals/__init__.py +0 -0
  97. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/evals/__main__.py +0 -0
  98. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/evals/baseline.py +0 -0
  99. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/evals/datasets/basic_queries.yaml +0 -0
  100. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/evals/datasets/demo_readiness.yaml +0 -0
  101. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/evals/datasets/edge_cases.yaml +0 -0
  102. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/evals/datasets/follow_ups.yaml +0 -0
  103. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/evals/datasets/large_schema.yaml +0 -0
  104. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/evals/datasets/multi_hop.yaml +0 -0
  105. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/evals/datasets/planned_orchestration.yaml +0 -0
  106. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/evals/diagnostics.py +0 -0
  107. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/evals/fingerprints.py +0 -0
  108. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/evals/fixtures.py +0 -0
  109. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/evals/judges/__init__.py +0 -0
  110. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/evals/judges/answer_quality.py +0 -0
  111. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/evals/judges/contract.py +0 -0
  112. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/evals/judges/result_accuracy.py +0 -0
  113. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/evals/judges/tool_sequence.py +0 -0
  114. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/evals/readiness.py +0 -0
  115. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/evals/runner.py +0 -0
  116. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/evals/traces.py +0 -0
  117. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/grounding.py +0 -0
  118. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/models.py +0 -0
  119. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/planned/__init__.py +0 -0
  120. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/planned/budget.py +0 -0
  121. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/planned/calculations.py +0 -0
  122. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/planned/catalog.py +0 -0
  123. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/planned/config.py +0 -0
  124. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/planned/events.py +0 -0
  125. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/planned/evidence.py +0 -0
  126. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/planned/models.py +0 -0
  127. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/planned/planner.py +0 -0
  128. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/planned/provider_calls.py +0 -0
  129. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/planned/resolver.py +0 -0
  130. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/planned/routing.py +0 -0
  131. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/planned/scheduler.py +0 -0
  132. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/planned/synthesis.py +0 -0
  133. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/planned/validation.py +0 -0
  134. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/providers/__init__.py +0 -0
  135. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/providers/_shared.py +0 -0
  136. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/providers/anthropic.py +0 -0
  137. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/providers/base.py +0 -0
  138. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/providers/google.py +0 -0
  139. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/providers/ollama.py +0 -0
  140. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/providers/openai.py +0 -0
  141. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/rate_limits.py +0 -0
  142. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/routing.py +0 -0
  143. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/schema_index.py +0 -0
  144. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/settings.py +0 -0
  145. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/signals.py +0 -0
  146. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/system_prompt.py +0 -0
  147. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/tool_metadata.py +0 -0
  148. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/tools.py +0 -0
  149. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/turns.py +0 -0
  150. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/chat/views.py +0 -0
  151. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/conf.py +0 -0
  152. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/dataframes/__init__.py +0 -0
  153. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/dataframes/measurements.py +0 -0
  154. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/factory/__init__.py +0 -0
  155. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/factory/auto_factory.py +0 -0
  156. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/factory/factories.py +0 -0
  157. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/factory/factory_methods.py +0 -0
  158. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/__init__.py +0 -0
  159. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/bundles/__init__.py +0 -0
  160. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/bundles/calculation.py +0 -0
  161. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/bundles/database.py +0 -0
  162. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/bundles/excel.py +0 -0
  163. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/bundles/remote_manager.py +0 -0
  164. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/bundles/request.py +0 -0
  165. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/__init__.py +0 -0
  166. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/base.py +0 -0
  167. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/builtin.py +0 -0
  168. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/calculation/__init__.py +0 -0
  169. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/calculation/_compat.py +0 -0
  170. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/calculation/lifecycle.py +0 -0
  171. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/configuration.py +0 -0
  172. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/core/observability.py +0 -0
  173. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/core/utils.py +0 -0
  174. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/excel/__init__.py +0 -0
  175. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/exceptions.py +0 -0
  176. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/existing_model/__init__.py +0 -0
  177. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/existing_model/_compat.py +0 -0
  178. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/existing_model/resolution.py +0 -0
  179. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/factory.py +0 -0
  180. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/orm/__init__.py +0 -0
  181. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/orm/_compat.py +0 -0
  182. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/orm/bulk.py +0 -0
  183. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/orm/create_many.py +0 -0
  184. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/orm/history.py +0 -0
  185. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/orm/lifecycle.py +0 -0
  186. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/orm/mutations.py +0 -0
  187. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/orm/support.py +0 -0
  188. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/orm_utils/__init__.py +0 -0
  189. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/orm_utils/django_manager_utils.py +0 -0
  190. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/orm_utils/field_descriptors.py +0 -0
  191. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/orm_utils/payload_normalizer.py +0 -0
  192. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/orm_utils/update_state.py +0 -0
  193. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/read_only/__init__.py +0 -0
  194. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/read_only/_compat.py +0 -0
  195. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/read_only/_types.py +0 -0
  196. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/read_only/lifecycle.py +0 -0
  197. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/read_only/management.py +0 -0
  198. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/registry.py +0 -0
  199. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/remote_manager.py +0 -0
  200. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/capabilities/request/__init__.py +0 -0
  201. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/excel.py +0 -0
  202. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/excel_store.py +0 -0
  203. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/excel_workbook.py +0 -0
  204. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/infrastructure/__init__.py +0 -0
  205. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/infrastructure/startup_hooks.py +0 -0
  206. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/infrastructure/system_checks.py +0 -0
  207. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/interfaces/__init__.py +0 -0
  208. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/interfaces/calculation.py +0 -0
  209. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/interfaces/database.py +0 -0
  210. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/interfaces/excel.py +0 -0
  211. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/interfaces/existing_model.py +0 -0
  212. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/interfaces/read_only.py +0 -0
  213. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/interfaces/remote_manager.py +0 -0
  214. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/interfaces/request.py +0 -0
  215. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/manifests/__init__.py +0 -0
  216. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/manifests/capability_builder.py +0 -0
  217. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/manifests/capability_manifest.py +0 -0
  218. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/manifests/capability_models.py +0 -0
  219. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/orm_interface.py +0 -0
  220. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/requests.py +0 -0
  221. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/utils/__init__.py +0 -0
  222. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/utils/database_interface_protocols.py +0 -0
  223. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/utils/errors.py +0 -0
  224. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/utils/history.py +0 -0
  225. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/interface/utils/models.py +0 -0
  226. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/logging.py +0 -0
  227. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/management/commands/chat_cleanup.py +0 -0
  228. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/management/commands/cleanup_upload_intents.py +0 -0
  229. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/management/commands/graphql_warmup.py +0 -0
  230. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/management/commands/graphql_warmup_refresh_due.py +0 -0
  231. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/management/commands/search_index.py +0 -0
  232. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/management/commands/search_reconcile.py +0 -0
  233. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/management/commands/seed_manager_landscape.py +0 -0
  234. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/management/commands/shell.py +0 -0
  235. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/management/commands/sync_read_only.py +0 -0
  236. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/management/commands/workflow_drain_outbox.py +0 -0
  237. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/management/commands/workflow_replay_dead_letters.py +0 -0
  238. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/manager/__init__.py +0 -0
  239. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/manager/bulk_create.py +0 -0
  240. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/manager/group_manager.py +0 -0
  241. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/measurement/__init__.py +0 -0
  242. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/measurement/measurement.py +0 -0
  243. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/measurement/measurement_field.py +0 -0
  244. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/metrics/__init__.py +0 -0
  245. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/metrics/graphql.py +0 -0
  246. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/migrations/0001_initial.py +0 -0
  247. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/migrations/0002_workflow_outbox_scaling_indexes.py +0 -0
  248. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/migrations/0003_workflow_execution_correlation_constraint.py +0 -0
  249. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/migrations/0004_chat_persistence_models.py +0 -0
  250. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/migrations/0004_search_index_state.py +0 -0
  251. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/migrations/0005_merge_chat_search.py +0 -0
  252. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/migrations/0006_chat_pending_confirmation_scoped_ids.py +0 -0
  253. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/migrations/0007_upload_intent.py +0 -0
  254. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/migrations/0008_upload_finalization_versions.py +0 -0
  255. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/migrations/0009_upload_cleanup_state.py +0 -0
  256. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/migrations/0010_chat_pending_confirmation_portable_uniqueness.py +0 -0
  257. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/migrations/0011_search_index_state_dirty_generation.py +0 -0
  258. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/migrations/0012_chat_context_watermarks.py +0 -0
  259. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/migrations/__init__.py +0 -0
  260. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/models.py +0 -0
  261. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/permission/__init__.py +0 -0
  262. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/permission/audit.py +0 -0
  263. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/permission/base_permission.py +0 -0
  264. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/permission/graphql_capabilities.py +0 -0
  265. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/permission/manager_based_permission.py +0 -0
  266. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/permission/mutation_permission.py +0 -0
  267. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/permission/permission_checks.py +0 -0
  268. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/permission/permission_data_manager.py +0 -0
  269. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/permission/utils.py +0 -0
  270. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/public_api_registry.py +0 -0
  271. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/py.typed +0 -0
  272. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/rule/__init__.py +0 -0
  273. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/rule/handler.py +0 -0
  274. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/rule/rule.py +0 -0
  275. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/search/__init__.py +0 -0
  276. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/search/async_tasks.py +0 -0
  277. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/search/backend.py +0 -0
  278. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/search/backend_registry.py +0 -0
  279. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/search/backends/__init__.py +0 -0
  280. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/search/backends/dev.py +0 -0
  281. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/search/backends/meilisearch.py +0 -0
  282. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/search/backends/opensearch.py +0 -0
  283. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/search/backends/typesense.py +0 -0
  284. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/search/checks.py +0 -0
  285. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/search/config.py +0 -0
  286. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/search/identity.py +0 -0
  287. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/search/indexer.py +0 -0
  288. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/search/invalidation.py +0 -0
  289. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/search/m2m_invalidation.py +0 -0
  290. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/search/models.py +0 -0
  291. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/search/reconciliation.py +0 -0
  292. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/search/registry.py +0 -0
  293. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/search/tasks.py +0 -0
  294. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/search/utils.py +0 -0
  295. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/seeding/__init__.py +0 -0
  296. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/seeding/manager_landscape.py +0 -0
  297. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/uploads/__init__.py +0 -0
  298. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/uploads/adapters.py +0 -0
  299. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/uploads/checks.py +0 -0
  300. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/uploads/config.py +0 -0
  301. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/uploads/errors.py +0 -0
  302. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/uploads/finalization.py +0 -0
  303. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/uploads/graphql.py +0 -0
  304. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/uploads/graphql_types.py +0 -0
  305. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/uploads/metrics.py +0 -0
  306. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/uploads/models.py +0 -0
  307. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/uploads/public.py +0 -0
  308. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/uploads/s3.py +0 -0
  309. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/uploads/services.py +0 -0
  310. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/uploads/tokens.py +0 -0
  311. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/uploads/types.py +0 -0
  312. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/uploads/urls.py +0 -0
  313. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/uploads/views.py +0 -0
  314. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/utils/__init__.py +0 -0
  315. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/utils/_args_to_kwargs.py +0 -0
  316. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/utils/_cache_key_encoder.py +0 -0
  317. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/utils/_make_cache_key.py +0 -0
  318. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/utils/_none_to_zero.py +0 -0
  319. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/utils/format_string.py +0 -0
  320. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/utils/json_encoder.py +0 -0
  321. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/utils/path_mapping.py +0 -0
  322. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/utils/public_api.py +0 -0
  323. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/utils/testing.py +0 -0
  324. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/utils/type_checks.py +0 -0
  325. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/workflow/__init__.py +0 -0
  326. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/workflow/actions.py +0 -0
  327. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/workflow/backend_registry.py +0 -0
  328. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/workflow/backends/__init__.py +0 -0
  329. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/workflow/backends/celery.py +0 -0
  330. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/workflow/backends/local.py +0 -0
  331. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/workflow/backends/n8n.py +0 -0
  332. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/workflow/config.py +0 -0
  333. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/workflow/engine.py +0 -0
  334. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/workflow/event_registry.py +0 -0
  335. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/workflow/events.py +0 -0
  336. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/workflow/models.py +0 -0
  337. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/workflow/signal_bridge.py +0 -0
  338. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/workflow/tasks.py +0 -0
  339. {generalmanager-0.85.0 → generalmanager-0.86.1}/src/general_manager/workflow/telemetry.py +0 -0
  340. {generalmanager-0.85.0 → generalmanager-0.86.1}/tests/test_settings.py +0 -0
  341. {generalmanager-0.85.0 → generalmanager-0.86.1}/tests/test_urls.py +0 -0
  342. {generalmanager-0.85.0 → generalmanager-0.86.1}/tests/testing_asgi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.85.0
3
+ Version: 0.86.1
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.85.0"
7
+ version = "0.86.1"
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.85.0
3
+ Version: 0.86.1
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
@@ -47,6 +47,7 @@ from general_manager.bucket._materialized_bucket import MaterializedBucket
47
47
  from general_manager.bucket.group_bucket import GroupBucket
48
48
  from general_manager.bucket.request_bucket import RequestBucket
49
49
  from general_manager.bucket.indexing import freeze_bucket_index_value
50
+ from general_manager.cache.cache_tracker import DependencyTracker
50
51
  from general_manager.cache.dependency_index import (
51
52
  Dependency,
52
53
  )
@@ -116,6 +117,7 @@ from general_manager.api.graphql_resolvers import (
116
117
  apply_pagination as _apply_pagination_fn,
117
118
  apply_grouping as _apply_grouping_fn,
118
119
  check_read_permission as _check_read_permission_fn,
120
+ check_read_permission_for_user as _check_read_permission_for_user_fn,
119
121
  can_read_instance_for_user as _can_read_instance_for_user_fn,
120
122
  create_measurement_resolver as _create_measurement_resolver_fn,
121
123
  create_normal_resolver as _create_normal_resolver_fn,
@@ -835,14 +837,25 @@ class GraphQL:
835
837
  graphene_type_name = f"{generalManagerClass.__name__}Type"
836
838
  fields: GraphQLFieldMap = {}
837
839
 
840
+ # Only declared typed-list inputs opt into native list output semantics.
841
+ input_fields = getattr(interface_cls, "input_fields", {})
838
842
  # Map Attribute Types to Graphene Fields
839
- for field_name, field_info in interface_cls.get_attribute_types().items():
843
+ for field_name, attribute_info in interface_cls.get_attribute_types().items():
844
+ field_info: Mapping[str, object] = attribute_info
845
+ input_field = input_fields.get(field_name)
846
+ is_collection_input = getattr(input_field, "is_collection", False) is True
847
+ if is_collection_input:
848
+ field_info = {**field_info, "is_collection_input": True}
840
849
  field_type = field_info["type"]
841
850
  resolved_manager_type = resolve_general_manager_type(
842
851
  field_type,
843
852
  cls.manager_registry,
844
853
  )
845
- resolved_field_type = resolved_manager_type or field_type
854
+ resolved_field_type = (
855
+ field_type
856
+ if is_collection_input
857
+ else resolved_manager_type or field_type
858
+ )
846
859
  fields[field_name] = cls._map_field_to_graphene_read(
847
860
  resolved_field_type,
848
861
  field_name,
@@ -873,10 +886,22 @@ class GraphQL:
873
886
  )
874
887
 
875
888
  fields[resolver_name] = resolve_stored_file
889
+ elif is_collection_input:
890
+ fields[resolver_name] = (
891
+ cls._create_measurement_resolver(field_name)
892
+ if safe_issubclass(get_args(field_type)[0], Measurement)
893
+ else _create_normal_resolver_fn(
894
+ field_name,
895
+ authorize_manager_collection=resolve_general_manager_type(
896
+ get_args(field_type)[0], cls.manager_registry
897
+ )
898
+ is not None,
899
+ )
900
+ )
876
901
  else:
877
902
  fields[resolver_name] = cls._create_resolver(
878
903
  field_name,
879
- resolved_field_type,
904
+ cast(type, resolved_field_type),
880
905
  )
881
906
  if (
882
907
  field_name.endswith("_list")
@@ -1396,6 +1421,24 @@ class GraphQL:
1396
1421
  Returns:
1397
1422
  object: Graphene field or type configured for the attribute.
1398
1423
  """
1424
+ if field_info and field_info.get("is_collection_input") is True:
1425
+ element = get_args(field_type)[0]
1426
+ manager_element = resolve_general_manager_type(
1427
+ element, GraphQL.manager_registry
1428
+ )
1429
+ if manager_element is not None:
1430
+ return graphene.List(
1431
+ graphene.NonNull(
1432
+ lambda: GraphQL.graphql_type_registry[manager_element.__name__]
1433
+ )
1434
+ )
1435
+ scalar = (
1436
+ MeasurementType
1437
+ if safe_issubclass(element, Measurement)
1438
+ else GraphQL._map_field_to_graphene_base_type(element)
1439
+ )
1440
+ return graphene.List(graphene.NonNull(scalar))
1441
+
1399
1442
  manager_type = resolve_general_manager_type(
1400
1443
  field_type,
1401
1444
  GraphQL.manager_registry,
@@ -2350,6 +2393,36 @@ class GraphQL:
2350
2393
  raise
2351
2394
  return item if readable else None
2352
2395
 
2396
+ @classmethod
2397
+ def _prepare_detail_subscription(
2398
+ cls,
2399
+ manager_class: type[GeneralManager],
2400
+ identification: GraphQLIdentification,
2401
+ user: object,
2402
+ *,
2403
+ property_names: Iterable[str] = (),
2404
+ ) -> tuple[GeneralManager, set[Dependency]] | None:
2405
+ """Hydrate and authorize before priming selected readable properties.
2406
+
2407
+ Call in a worker thread: construction, native permissions and property
2408
+ reads may all access the ORM. Only hydration errors are suppressed;
2409
+ permission-backend and property failures must fail the stream closed.
2410
+ """
2411
+ with DependencyTracker() as dependencies:
2412
+ try:
2413
+ instance, _ = cls._instantiate_manager(manager_class, identification)
2414
+ except SUBSCRIPTION_HYDRATION_ERRORS:
2415
+ return None
2416
+ if not _can_read_instance_for_user_fn(instance, user):
2417
+ return None
2418
+ readable_properties = [
2419
+ name
2420
+ for name in property_names
2421
+ if _check_read_permission_for_user_fn(instance, user, name)
2422
+ ]
2423
+ cls._prime_graphql_properties(instance, readable_properties)
2424
+ return instance, dependencies
2425
+
2353
2426
  @classmethod
2354
2427
  def _add_subscription_field(
2355
2428
  cls,
@@ -2370,7 +2443,7 @@ class GraphQL:
2370
2443
 
2371
2444
  Notes:
2372
2445
  - The subscribe function requires an available channel layer and subscribes the caller to channel groups derived from the instance identification and its resolved dependencies.
2373
- - The subscribe coroutine yields SubscriptionEvent objects with fields `item` (the current instance or None if it cannot be instantiated) and `action` (a string such as `"snapshot"` or other change actions).
2446
+ - Detail events contain an authorized current instance and an action; unavailable or unreadable targets terminate the detail stream.
2374
2447
  - On termination the subscription cleans up listener tasks and unsubscribes from channel groups.
2375
2448
  """
2376
2449
  manager_field_name = pascal_to_snake(generalManagerClass.__name__)
@@ -2410,27 +2483,30 @@ class GraphQL:
2410
2483
  """
2411
2484
  Stream subscription events for a specific manager instance identified by the provided arguments.
2412
2485
 
2413
- Yields an initial `SubscriptionEvent` with `action` set to `"snapshot"` containing the current manager instance, then yields `SubscriptionEvent`s for each subsequent action. For subsequent events, `item` will be the re-instantiated manager instance or `None` if instantiation fails. The subscriber is registered on the manager's channel groups (including dependent managers' groups) and the channel subscriptions and background listener are cleaned up when the iterator is closed or cancelled.
2414
-
2415
- Parameters:
2416
- identification: Identification fields required to locate the manager instance (maps to the manager's identification signature).
2417
-
2418
- Returns:
2419
- AsyncIterator[SubscriptionEvent]: An asynchronous iterator that first yields a snapshot event and then yields update events; each event's `item` is the manager instance or `None` if it could not be instantiated.
2486
+ Authorize the request user before property priming and registration.
2487
+ Recheck access before each event; unavailable or unreadable targets
2488
+ end the iterator without forwarding the queued action. Closing the
2489
+ iterator removes its listeners and channel memberships.
2420
2490
  """
2421
2491
  identification_copy = deepcopy(identification)
2422
2492
  property_names = cls._subscription_property_names(info, generalManagerClass)
2493
+ subscription_user = info.context.user
2423
2494
  try:
2424
- instance, dependency_records = await asyncio.to_thread(
2425
- cls._instantiate_manager,
2495
+ prepared = await asyncio.to_thread(
2496
+ cls._prepare_detail_subscription,
2426
2497
  generalManagerClass,
2427
2498
  identification_copy,
2428
- collect_dependencies=True,
2499
+ subscription_user,
2429
2500
  property_names=property_names,
2430
2501
  )
2431
2502
  except Exception as exc: # pragma: no cover - bubbled to GraphQL
2432
2503
  raise GraphQLError(str(exc)) from exc
2433
2504
 
2505
+ if prepared is None:
2506
+ message = "Subscription target is unavailable or not readable."
2507
+ raise GraphQLError(message)
2508
+ instance, dependency_records = prepared
2509
+
2434
2510
  try:
2435
2511
  channel_layer = cast(
2436
2512
  BaseChannelLayer, cls._get_channel_layer(strict=True)
@@ -2457,15 +2533,16 @@ class GraphQL:
2457
2533
  group_names.add(cls._refresh_group_name(dependency_class))
2458
2534
 
2459
2535
  async def event_stream() -> AsyncIterator[SubscriptionEvent]:
2460
- """
2461
- Yield subscription events for a manager instance, starting with an initial snapshot followed by subsequent updates.
2462
-
2463
- Returns:
2464
- AsyncIterator[SubscriptionEvent]: An asynchronous iterator that first yields a `SubscriptionEvent` with `action` set to `"snapshot"` and `item` containing the current manager instance (or `None` if instantiation failed). Subsequent yields provide `SubscriptionEvent` values for each received action, where `action` is the action string and `item` is the (re-)instantiated manager or `None` if instantiation failed.
2465
-
2466
- Notes:
2467
- When the iterator is closed or exits, the background listener task is cancelled and the subscription's channel group memberships are discarded.
2468
- """
2536
+ """Deliver authorized events and clean up on every exit path."""
2537
+ # The iterator may be consumed long after subscribe() returns.
2538
+ prepared = await asyncio.to_thread(
2539
+ cls._prepare_detail_subscription,
2540
+ generalManagerClass,
2541
+ identification_copy,
2542
+ subscription_user,
2543
+ )
2544
+ if prepared is None:
2545
+ return
2469
2546
  channel_name = cast(str, await channel_layer.new_channel())
2470
2547
  queue: asyncio.Queue[str] = asyncio.Queue[str]()
2471
2548
  joined_groups = await _join_subscription_groups(
@@ -2482,19 +2559,29 @@ class GraphQL:
2482
2559
  joined_groups,
2483
2560
  listener_task,
2484
2561
  ):
2562
+ # Group registration awaits I/O; access can change meanwhile.
2563
+ prepared = await asyncio.to_thread(
2564
+ cls._prepare_detail_subscription,
2565
+ generalManagerClass,
2566
+ identification_copy,
2567
+ subscription_user,
2568
+ )
2569
+ if prepared is None:
2570
+ return
2571
+ item, _ = prepared
2485
2572
  clear_capability_context(info)
2486
- yield SubscriptionEvent(item=instance, action="snapshot")
2573
+ yield SubscriptionEvent(item=item, action="snapshot")
2487
2574
  while True:
2488
2575
  action = await queue.get()
2489
- try:
2490
- item, _ = await asyncio.to_thread(
2491
- cls._instantiate_manager,
2492
- generalManagerClass,
2493
- identification_copy,
2494
- property_names=property_names,
2495
- )
2496
- except SUBSCRIPTION_HYDRATION_ERRORS:
2497
- item = None
2576
+ prepared = await asyncio.to_thread(
2577
+ cls._prepare_detail_subscription,
2578
+ generalManagerClass,
2579
+ identification_copy,
2580
+ subscription_user,
2581
+ )
2582
+ if prepared is None:
2583
+ return
2584
+ item, _ = prepared
2498
2585
  clear_capability_context(info)
2499
2586
  yield SubscriptionEvent(item=item, action=action)
2500
2587
 
@@ -92,8 +92,13 @@ def build_identification_arguments(
92
92
  # name is independent of the actual primary-key column name.
93
93
  is_orm_id = is_orm_identifier_input(manager_class, name)
94
94
  required = input_field.required or (for_mutation and is_orm_id)
95
+ is_collection = getattr(input_field, "is_collection", False) is True
96
+ element_type = (
97
+ input_field.collection_element_type if is_collection else input_field.type
98
+ )
99
+ assert element_type is not None
95
100
  manager_type = resolve_general_manager_type(
96
- input_field.type, get_graphql_manager_registry()
101
+ element_type, get_graphql_manager_registry()
97
102
  )
98
103
  if manager_type is not None:
99
104
  # Reuse custom mutation support for structured/composite manager
@@ -101,16 +106,30 @@ def build_identification_arguments(
101
106
  from general_manager.api.mutation import (
102
107
  _build_manager_argument_field,
103
108
  _uses_single_id_input,
109
+ _get_or_create_manager_input_type,
104
110
  )
105
111
 
112
+ if is_collection:
113
+ reference = (
114
+ graphene.ID
115
+ if _uses_single_id_input(manager_type)
116
+ else _get_or_create_manager_input_type(manager_type)
117
+ )
118
+ arguments[f"{name}_id"] = graphene.Argument(
119
+ graphene.List(graphene.NonNull(reference)), required=required
120
+ )
121
+ continue
106
122
  arguments[f"{name}_id"] = (
107
123
  graphene.Argument(graphene.ID, required=required)
108
124
  if _uses_single_id_input(manager_type)
109
125
  else _build_manager_argument_field(manager_type, required=required)
110
126
  )
111
127
  else:
112
- scalar = map_identification_scalar(manager_class, name, input_field.type)
113
- arguments[name] = graphene.Argument(scalar, required=required)
128
+ scalar = map_identification_scalar(manager_class, name, element_type)
129
+ arguments[name] = graphene.Argument(
130
+ graphene.List(graphene.NonNull(scalar)) if is_collection else scalar,
131
+ required=required,
132
+ )
114
133
  return arguments
115
134
 
116
135
 
@@ -1339,12 +1339,15 @@ def create_measurement_resolver(field_name: str) -> Resolver:
1339
1339
  return resolver
1340
1340
 
1341
1341
 
1342
- def create_normal_resolver(field_name: str) -> Resolver:
1342
+ def create_normal_resolver(
1343
+ field_name: str, *, authorize_manager_collection: bool = False
1344
+ ) -> Resolver:
1343
1345
  """
1344
1346
  Return a resolver for a scalar (non-list, non-Measurement) field.
1345
1347
 
1346
1348
  The generated resolver returns ``None`` when field read permission is denied;
1347
- otherwise it returns ``getattr(self, field_name)``.
1349
+ otherwise it returns ``getattr(self, field_name)``. Typed manager collections
1350
+ additionally omit members denied by the manager-level read gate.
1348
1351
  """
1349
1352
 
1350
1353
  def resolver(self: GeneralManager, info: GraphQLResolveInfo) -> object:
@@ -1356,11 +1359,18 @@ def create_normal_resolver(field_name: str) -> Resolver:
1356
1359
  if relation_id is not _NO_GROUPED_RELATION_ID_ALIAS:
1357
1360
  return relation_id
1358
1361
  _validate_grouped_field_projection(self, field_name)
1359
- return project_grouped_field_value(
1362
+ value = project_grouped_field_value(
1360
1363
  self,
1361
1364
  field_name,
1362
1365
  read_grouped_field_value(self, field_name),
1363
1366
  )
1367
+ if authorize_manager_collection and value is not None:
1368
+ return [
1369
+ member
1370
+ for member in cast(list[GeneralManager], value)
1371
+ if can_read_instance_for_user(member, info.context.user)
1372
+ ]
1373
+ return value
1364
1374
 
1365
1375
  return resolve_with_read_permission(
1366
1376
  self,
@@ -805,6 +805,10 @@ def create_filter_options(
805
805
 
806
806
  filter_fields: dict[str, GrapheneFieldType] = {}
807
807
  for attr_name, attr_info in field_type.Interface.get_attribute_types().items():
808
+ # Native constructor selections do not add a new GraphQL filter language.
809
+ input_field = getattr(field_type.Interface, "input_fields", {}).get(attr_name)
810
+ if getattr(input_field, "is_collection", False) is True:
811
+ continue
808
812
  effective_attr_info = _get_filter_relation_info(
809
813
  field_type,
810
814
  attr_name,
@@ -348,7 +348,14 @@ def resolve_subscription_dependencies(
348
348
  interface_cls = manager_class.Interface
349
349
 
350
350
  for input_name, input_field in interface_cls.input_fields.items():
351
- if not issubclass(input_field.type, GeneralManager):
351
+ manager_type = (
352
+ input_field.collection_element_type
353
+ if getattr(input_field, "is_collection", False) is True
354
+ else input_field.type
355
+ )
356
+ if not isinstance(manager_type, type) or not issubclass(
357
+ manager_type, GeneralManager
358
+ ):
352
359
  continue
353
360
 
354
361
  raw_value = instance._interface.identification.get(input_name)
@@ -359,7 +366,6 @@ def resolve_subscription_dependencies(
359
366
  for value in values:
360
367
  if isinstance(value, GeneralManager):
361
368
  identification = deepcopy(value.identification)
362
- manager_type = input_field.type
363
369
  if (
364
370
  manager_type is manager_class
365
371
  and identification == instance.identification
@@ -375,7 +381,6 @@ def resolve_subscription_dependencies(
375
381
  dep_list.append((manager_type, identification))
376
382
  elif isinstance(value, dict):
377
383
  identification_dict = deepcopy(cast(Identification, value))
378
- manager_type = input_field.type
379
384
  if (
380
385
  manager_type is manager_class
381
386
  and identification_dict == instance.identification
@@ -180,6 +180,11 @@ def _get_or_create_manager_input_type(
180
180
  for input_name, input_field in _manager_input_fields(manager_class).items():
181
181
  field_type = input_field.type
182
182
  required = input_field.required
183
+ if get_origin(field_type) is list:
184
+ fields[input_name] = graphene.InputField(
185
+ _mutation_input_type(field_type), required=required
186
+ )
187
+ continue
183
188
  if _is_general_manager_type(field_type):
184
189
  if _uses_single_id_input(field_type):
185
190
  fields[input_name] = graphene.ID(required=required)
@@ -368,7 +368,11 @@ def initialize_general_manager_classes(
368
368
  seen: set[str] = set()
369
369
  input_fields = getattr(general_manager_class.Interface, "input_fields", {})
370
370
  for attribute_name, attribute in input_fields.items():
371
- if isinstance(attribute, Input) and issubclass(attribute.type, _GM):
371
+ if (
372
+ isinstance(attribute, Input)
373
+ and isinstance(attribute.type, type)
374
+ and issubclass(attribute.type, _GM)
375
+ ):
372
376
  seen.add(attribute_name)
373
377
  yield attribute_name, attribute.type
374
378
 
@@ -36,10 +36,15 @@ from general_manager.bucket._ordering import (
36
36
  validate_ordering_fields,
37
37
  )
38
38
  from general_manager.bucket.projection import ProjectionRows
39
- from general_manager.manager.input import Input, InputDomain
39
+ from general_manager.manager.input import (
40
+ Input,
41
+ InputDomain,
42
+ _prepare_normalized_identification,
43
+ )
40
44
  from general_manager.utils.filter_parser import (
41
45
  FilterFunction,
42
46
  ParsedFilters,
47
+ ParsedFilterCriteria,
43
48
  create_filter_function,
44
49
  parse_filters,
45
50
  )
@@ -240,6 +245,7 @@ class CalculationBucket(Bucket[GeneralManagerType]):
240
245
  parse_filters(group, possible_values) for group in self._exclude_call_groups
241
246
  )
242
247
 
248
+ self._normalized_collections: dict[Hashable, object] = {}
243
249
  self._data: list[Combination] | None = None
244
250
  self._allowed_identifications: list[Combination] | None = None
245
251
  self._sort_fields: tuple[str, ...] = ()
@@ -687,7 +693,7 @@ class CalculationBucket(Bucket[GeneralManagerType]):
687
693
  self._ensure_as_of_compatible()
688
694
  combinations = self.generate_combinations()
689
695
  for combo in combinations:
690
- yield self._manager_class(**combo)
696
+ yield self._construct_manager(combo)
691
697
 
692
698
  def _project_rows(self, fields: tuple[str, ...]) -> ProjectionRows:
693
699
  """Project normalized calculation inputs without manager instances."""
@@ -712,7 +718,7 @@ class CalculationBucket(Bucket[GeneralManagerType]):
712
718
  tuple(
713
719
  resolve_calculation_input_value(
714
720
  interface_class,
715
- identification,
721
+ self._normalized_constructor_values(identification),
716
722
  field,
717
723
  resolved_values,
718
724
  )
@@ -803,8 +809,8 @@ class CalculationBucket(Bucket[GeneralManagerType]):
803
809
  or any(len(group) > 1 for group in self._exclude_call_groups)
804
810
  )
805
811
 
806
- @staticmethod
807
812
  def _matches_call_group(
813
+ self,
808
814
  manager: GeneralManagerType,
809
815
  group: ParsedFilters,
810
816
  ) -> bool:
@@ -814,9 +820,19 @@ class CalculationBucket(Bucket[GeneralManagerType]):
814
820
  value = getattr(manager, field_name)
815
821
  except AttributeError:
816
822
  return False
817
- for filter_func in definitions.get("filter_funcs", []):
818
- if not filter_func(value):
823
+ if "collection_criteria" in definitions:
824
+ dependencies = {
825
+ name: getattr(manager, name)
826
+ for name in self.input_fields[field_name].depends_on
827
+ }
828
+ if not self._collection_matches(
829
+ field_name, value, definitions, dependencies
830
+ ):
819
831
  return False
832
+ else:
833
+ for filter_func in definitions.get("filter_funcs", []):
834
+ if not filter_func(value):
835
+ return False
820
836
  for lookup, expected in definitions.get("filter_kwargs", {}).items():
821
837
  identification = getattr(value, "identification", None)
822
838
  lookup_parts = lookup.split("__") if lookup else []
@@ -904,13 +920,56 @@ class CalculationBucket(Bucket[GeneralManagerType]):
904
920
  identity_for=lambda combo: combo,
905
921
  )
906
922
 
923
+ def _normalize_collection(
924
+ self, name: str, value: object, context: Combination
925
+ ) -> object:
926
+ """Normalize a selection once for each dependency context in this plan."""
927
+ field = self.input_fields[name]
928
+ dependencies = {
929
+ dependency: context[dependency] for dependency in field.depends_on
930
+ }
931
+ key = (
932
+ name,
933
+ freeze_bucket_index_value(value),
934
+ freeze_bucket_index_value(dependencies),
935
+ )
936
+ if key not in self._normalized_collections:
937
+ self._normalized_collections[key] = field.cast(
938
+ value, dependencies, cache_context=(self._manager_class, name)
939
+ )
940
+ result = self._normalized_collections[key]
941
+ return list(result) if isinstance(result, list) else result
942
+
943
+ def _collection_matches(
944
+ self,
945
+ name: str,
946
+ value: object,
947
+ criteria: ParsedFilterCriteria,
948
+ context: Combination,
949
+ ) -> bool:
950
+ """Compare complete normalized selections with normalized alternatives."""
951
+ return all(
952
+ any(
953
+ value == self._normalize_collection(name, candidate, context)
954
+ for candidate in alternatives
955
+ )
956
+ for alternatives in criteria.get("collection_criteria", [])
957
+ )
958
+
959
+ def _normalized_constructor_values(self, combination: Combination) -> Combination:
960
+ """Mark normalized lists when reconstructing bucket managers or projections."""
961
+ return _prepare_normalized_identification(self._manager_class, combination)
962
+
963
+ def _construct_manager(self, combination: Combination) -> GeneralManagerType:
964
+ return self._manager_class(**self._normalized_constructor_values(combination))
965
+
907
966
  def _manager_combinations(
908
967
  self,
909
968
  combinations: list[Combination],
910
969
  ) -> list[GeneralManagerType]:
911
970
  """Instantiate managers for each raw input-combination dictionary."""
912
971
  self._ensure_as_of_compatible()
913
- return [self._manager_class(**combo) for combo in combinations]
972
+ return [self._construct_manager(combo) for combo in combinations]
914
973
 
915
974
  @staticmethod
916
975
  def _manager_identifications(
@@ -1165,16 +1224,56 @@ class CalculationBucket(Bucket[GeneralManagerType]):
1165
1224
  input_name: str = sorted_inputs[index]
1166
1225
  input_field = self.input_fields[input_name]
1167
1226
 
1168
- possible_values = self.get_possible_values(
1169
- input_name, input_field, current_combo
1170
- )
1227
+ field_filters = filters.get(input_name, {})
1228
+ field_excludes = excludes.get(input_name, {})
1229
+ possible_values: Iterable[object] | Bucket[GeneralManager] | None
1230
+ if input_field.is_collection and input_field.possible_values is None:
1231
+ if "candidate_values" in field_filters:
1232
+ possible_values = field_filters["candidate_values"]
1233
+ elif input_field.required:
1234
+ raise InvalidPossibleValuesError(input_name)
1235
+ else:
1236
+ possible_values = [None]
1237
+ else:
1238
+ possible_values = self.get_possible_values(
1239
+ input_name, input_field, current_combo
1240
+ )
1171
1241
  if possible_values is None:
1172
1242
  if input_passes_filters(input_name, current_combo):
1173
1243
  yield from helper(index + 1, current_combo)
1174
1244
  return
1175
1245
 
1176
- field_filters = filters.get(input_name, {})
1177
- field_excludes = excludes.get(input_name, {})
1246
+ if input_field.is_collection:
1247
+ from general_manager.interface.capabilities.calculation.input_resolution import (
1248
+ resolve_calculation_input_value,
1249
+ )
1250
+
1251
+ resolved_dependencies: Combination = {}
1252
+ for dependency in input_field.depends_on:
1253
+ resolve_calculation_input_value(
1254
+ cast(
1255
+ "type[CalculationInterface]", self._manager_class.Interface
1256
+ ),
1257
+ self._normalized_constructor_values(current_combo),
1258
+ dependency,
1259
+ resolved_dependencies,
1260
+ )
1261
+ for raw_value in possible_values:
1262
+ value = self._normalize_collection(
1263
+ input_name, raw_value, resolved_dependencies
1264
+ )
1265
+ if not self._collection_matches(
1266
+ input_name, value, field_filters, resolved_dependencies
1267
+ ):
1268
+ continue
1269
+ if field_excludes and self._collection_matches(
1270
+ input_name, value, field_excludes, resolved_dependencies
1271
+ ):
1272
+ continue
1273
+ current_combo[input_name] = value
1274
+ yield from helper(index + 1, current_combo)
1275
+ del current_combo[input_name]
1276
+ return
1178
1277
 
1179
1278
  # use filter_funcs and exclude_funcs to filter possible values
1180
1279
  if isinstance(possible_values, Bucket):
@@ -1197,7 +1296,9 @@ class CalculationBucket(Bucket[GeneralManagerType]):
1197
1296
  possible_values = list(possible_values)
1198
1297
 
1199
1298
  for value in possible_values:
1200
- if not isinstance(value, input_field.type):
1299
+ if not input_field.is_collection and not isinstance(
1300
+ value, input_field.type
1301
+ ):
1201
1302
  continue
1202
1303
  current_combo[input_name] = value
1203
1304
  yield from helper(index + 1, current_combo)
@@ -1247,7 +1348,7 @@ class CalculationBucket(Bucket[GeneralManagerType]):
1247
1348
  matching combinations have been found.
1248
1349
  """
1249
1350
  for combo in combinations:
1250
- manager = self._manager_class(**combo)
1351
+ manager = self._construct_manager(combo)
1251
1352
  if (
1252
1353
  allowed_identification_keys is not None
1253
1354
  and freeze_bucket_index_value(manager.identification)
@@ -1371,10 +1472,10 @@ class CalculationBucket(Bucket[GeneralManagerType]):
1371
1472
 
1372
1473
  return MaterializedBucket(
1373
1474
  self._manager_class,
1374
- tuple(self._manager_class(**combination) for combination in result),
1475
+ tuple(self._construct_manager(combination) for combination in result),
1375
1476
  snapshot=self._effective_search_date,
1376
1477
  )
1377
- return self._manager_class(**result)
1478
+ return self._construct_manager(result)
1378
1479
 
1379
1480
  def __contains__(self, item: GeneralManagerType) -> bool:
1380
1481
  """