GeneralManager 0.87.5__tar.gz → 0.87.6__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 (377) hide show
  1. {generalmanager-0.87.5/src/GeneralManager.egg-info → generalmanager-0.87.6}/PKG-INFO +1 -1
  2. {generalmanager-0.87.5 → generalmanager-0.87.6}/pyproject.toml +1 -1
  3. {generalmanager-0.87.5 → generalmanager-0.87.6/src/GeneralManager.egg-info}/PKG-INFO +1 -1
  4. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/GeneralManager.egg-info/SOURCES.txt +3 -0
  5. generalmanager-0.87.6/src/general_manager/api/graphql_query_permissions.py +619 -0
  6. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql_resolvers.py +319 -92
  7. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql_search.py +430 -75
  8. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/apps.py +4 -0
  9. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/bucket/calculation_bucket.py +322 -15
  10. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/bucket/database_bucket.py +144 -1
  11. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/cache/run_context.py +15 -1
  12. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/cache/signals.py +82 -15
  13. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/base_interface.py +18 -0
  14. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/orm/support.py +26 -0
  15. generalmanager-0.87.6/src/general_manager/interface/capabilities/orm_utils/collection_probes.py +181 -0
  16. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/orm_utils/field_descriptors.py +37 -0
  17. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/manager/general_manager.py +4 -0
  18. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/manager/input.py +12 -0
  19. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/manager/meta.py +70 -25
  20. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/permission/manager_based_permission.py +190 -11
  21. generalmanager-0.87.6/src/general_manager/search/authorization.py +109 -0
  22. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/search/backend.py +17 -2
  23. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/search/backends/meilisearch.py +313 -6
  24. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/search/config.py +30 -3
  25. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/search/indexer.py +2 -0
  26. generalmanager-0.87.6/src/general_manager/search/projection.py +317 -0
  27. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/search/reconciliation.py +29 -4
  28. generalmanager-0.87.5/src/general_manager/api/graphql_query_permissions.py +0 -168
  29. {generalmanager-0.87.5 → generalmanager-0.87.6}/LICENSE +0 -0
  30. {generalmanager-0.87.5 → generalmanager-0.87.6}/README.md +0 -0
  31. {generalmanager-0.87.5 → generalmanager-0.87.6}/setup.cfg +0 -0
  32. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/GeneralManager.egg-info/dependency_links.txt +0 -0
  33. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/GeneralManager.egg-info/requires.txt +0 -0
  34. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/GeneralManager.egg-info/top_level.txt +0 -0
  35. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/__init__.py +0 -0
  36. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/_types/__init__.py +0 -0
  37. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/_types/api.py +0 -0
  38. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/_types/bucket.py +0 -0
  39. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/_types/cache.py +0 -0
  40. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/_types/dataframes.py +0 -0
  41. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/_types/factory.py +0 -0
  42. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/_types/general_manager.py +0 -0
  43. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/_types/interface.py +0 -0
  44. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/_types/manager.py +0 -0
  45. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/_types/measurement.py +0 -0
  46. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/_types/permission.py +0 -0
  47. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/_types/rule.py +0 -0
  48. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/_types/search.py +0 -0
  49. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/_types/utils.py +0 -0
  50. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/__init__.py +0 -0
  51. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql.py +0 -0
  52. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql_as_of.py +0 -0
  53. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql_errors.py +0 -0
  54. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql_filter_contract.py +0 -0
  55. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql_groups.py +0 -0
  56. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql_identifiers.py +0 -0
  57. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql_mutations.py +0 -0
  58. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql_ordering.py +0 -0
  59. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql_output.py +0 -0
  60. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql_prefetch.py +0 -0
  61. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql_relations.py +0 -0
  62. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql_subscription_consumer.py +0 -0
  63. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql_subscriptions.py +0 -0
  64. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql_type.py +0 -0
  65. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql_units.py +0 -0
  66. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql_value_contract.py +0 -0
  67. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql_view.py +0 -0
  68. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql_warmup.py +0 -0
  69. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql_warmup_registry.py +0 -0
  70. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/graphql_warmup_tasks.py +0 -0
  71. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/mutation.py +0 -0
  72. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/mutation_controls.py +0 -0
  73. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/notification_batching.py +0 -0
  74. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/property.py +0 -0
  75. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/registry.py +0 -0
  76. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/remote_api.py +0 -0
  77. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/remote_invalidation.py +0 -0
  78. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/api/remote_invalidation_client.py +0 -0
  79. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/as_of.py +0 -0
  80. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/bootstrap.py +0 -0
  81. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/bucket/__init__.py +0 -0
  82. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/bucket/_materialized_bucket.py +0 -0
  83. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/bucket/_ordering.py +0 -0
  84. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/bucket/base_bucket.py +0 -0
  85. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/bucket/excel_bucket.py +0 -0
  86. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/bucket/group_bucket.py +0 -0
  87. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/bucket/indexing.py +0 -0
  88. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/bucket/projection.py +0 -0
  89. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/bucket/request_bucket.py +0 -0
  90. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/cache/__init__.py +0 -0
  91. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/cache/_dependency_graph.py +0 -0
  92. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/cache/batch_refresh.py +0 -0
  93. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/cache/cache_decorator.py +0 -0
  94. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/cache/cache_tracker.py +0 -0
  95. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/cache/data_change_context.py +0 -0
  96. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/cache/dependency_cache.py +0 -0
  97. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/cache/dependency_index.py +0 -0
  98. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/cache/dependency_matching.py +0 -0
  99. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/cache/dependency_publish.py +0 -0
  100. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/cache/dependency_shards.py +0 -0
  101. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/cache/model_dependency_collector.py +0 -0
  102. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/cache/run_context_lru.py +0 -0
  103. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/cache/transaction_barrier.py +0 -0
  104. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/__init__.py +0 -0
  105. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/audit.py +0 -0
  106. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/audit_identity.py +0 -0
  107. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/bootstrap.py +0 -0
  108. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/checks.py +0 -0
  109. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/consumer.py +0 -0
  110. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/context.py +0 -0
  111. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/errors.py +0 -0
  112. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/__init__.py +0 -0
  113. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/__main__.py +0 -0
  114. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/baseline.py +0 -0
  115. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/datasets/basic_queries.yaml +0 -0
  116. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/datasets/demo_readiness.yaml +0 -0
  117. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/datasets/edge_cases.yaml +0 -0
  118. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/datasets/follow_ups.yaml +0 -0
  119. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/datasets/large_schema.yaml +0 -0
  120. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/datasets/multi_hop.yaml +0 -0
  121. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/datasets/planned_orchestration.yaml +0 -0
  122. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/diagnostics.py +0 -0
  123. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/execution.py +0 -0
  124. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/fingerprints.py +0 -0
  125. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/fixtures.py +0 -0
  126. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/judges/__init__.py +0 -0
  127. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/judges/answer_quality.py +0 -0
  128. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/judges/contract.py +0 -0
  129. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/judges/result_accuracy.py +0 -0
  130. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/judges/result_set.py +0 -0
  131. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/judges/tool_sequence.py +0 -0
  132. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/outcomes.py +0 -0
  133. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/readiness.py +0 -0
  134. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/runner.py +0 -0
  135. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/evals/traces.py +0 -0
  136. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/graphql_contract.py +0 -0
  137. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/grounding.py +0 -0
  138. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/models.py +0 -0
  139. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/mutation_inputs.py +0 -0
  140. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/__init__.py +0 -0
  141. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/action_contract.py +0 -0
  142. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/binding_diagnostics.py +0 -0
  143. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/budget.py +0 -0
  144. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/calculation_scope.py +0 -0
  145. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/calculations.py +0 -0
  146. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/catalog.py +0 -0
  147. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/category_binding.py +0 -0
  148. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/choice_context.py +0 -0
  149. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/clarification.py +0 -0
  150. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/config.py +0 -0
  151. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/contract.py +0 -0
  152. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/conversion.py +0 -0
  153. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/cross_query.py +0 -0
  154. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/deferred_calculations.py +0 -0
  155. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/deferred_schema.py +0 -0
  156. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/events.py +0 -0
  157. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/evidence.py +0 -0
  158. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/evidence_selection.py +0 -0
  159. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/group_actions.py +0 -0
  160. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/models.py +0 -0
  161. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/planner.py +0 -0
  162. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/planner_context.py +0 -0
  163. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/provider_calls.py +0 -0
  164. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/resolver.py +0 -0
  165. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/scheduler.py +0 -0
  166. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/schema_projection.py +0 -0
  167. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/selector_clarification.py +0 -0
  168. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/selector_question.py +0 -0
  169. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/synthesis.py +0 -0
  170. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/planned/validation.py +0 -0
  171. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/providers/__init__.py +0 -0
  172. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/providers/_shared.py +0 -0
  173. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/providers/anthropic.py +0 -0
  174. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/providers/base.py +0 -0
  175. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/providers/google.py +0 -0
  176. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/providers/ollama.py +0 -0
  177. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/providers/openai.py +0 -0
  178. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/rate_limits.py +0 -0
  179. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/routing.py +0 -0
  180. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/schema_index.py +0 -0
  181. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/schema_inspection.py +0 -0
  182. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/settings.py +0 -0
  183. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/signals.py +0 -0
  184. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/system_prompt.py +0 -0
  185. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/tool_metadata.py +0 -0
  186. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/tools.py +0 -0
  187. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/turns.py +0 -0
  188. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/chat/views.py +0 -0
  189. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/conf.py +0 -0
  190. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/dataframes/__init__.py +0 -0
  191. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/dataframes/measurements.py +0 -0
  192. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/factory/__init__.py +0 -0
  193. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/factory/auto_factory.py +0 -0
  194. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/factory/factories.py +0 -0
  195. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/factory/factory_methods.py +0 -0
  196. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/__init__.py +0 -0
  197. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/bundles/__init__.py +0 -0
  198. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/bundles/calculation.py +0 -0
  199. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/bundles/database.py +0 -0
  200. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/bundles/excel.py +0 -0
  201. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/bundles/remote_manager.py +0 -0
  202. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/bundles/request.py +0 -0
  203. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/__init__.py +0 -0
  204. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/base.py +0 -0
  205. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/builtin.py +0 -0
  206. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/calculation/__init__.py +0 -0
  207. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/calculation/_compat.py +0 -0
  208. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/calculation/input_resolution.py +0 -0
  209. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/calculation/lifecycle.py +0 -0
  210. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/configuration.py +0 -0
  211. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/core/observability.py +0 -0
  212. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/core/utils.py +0 -0
  213. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/excel/__init__.py +0 -0
  214. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/exceptions.py +0 -0
  215. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/existing_model/__init__.py +0 -0
  216. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/existing_model/_compat.py +0 -0
  217. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/existing_model/resolution.py +0 -0
  218. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/factory.py +0 -0
  219. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/orm/__init__.py +0 -0
  220. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/orm/_compat.py +0 -0
  221. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/orm/bulk.py +0 -0
  222. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/orm/create_many.py +0 -0
  223. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/orm/history.py +0 -0
  224. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/orm/history_query.py +0 -0
  225. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/orm/lifecycle.py +0 -0
  226. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/orm/mutations.py +0 -0
  227. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/orm_utils/__init__.py +0 -0
  228. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/orm_utils/django_manager_utils.py +0 -0
  229. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/orm_utils/payload_normalizer.py +0 -0
  230. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/orm_utils/update_state.py +0 -0
  231. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/read_only/__init__.py +0 -0
  232. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/read_only/_compat.py +0 -0
  233. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/read_only/_types.py +0 -0
  234. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/read_only/lifecycle.py +0 -0
  235. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/read_only/management.py +0 -0
  236. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/registry.py +0 -0
  237. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/remote_manager.py +0 -0
  238. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/capabilities/request/__init__.py +0 -0
  239. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/excel.py +0 -0
  240. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/excel_store.py +0 -0
  241. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/excel_workbook.py +0 -0
  242. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/infrastructure/__init__.py +0 -0
  243. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/infrastructure/startup_hooks.py +0 -0
  244. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/infrastructure/system_checks.py +0 -0
  245. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/interfaces/__init__.py +0 -0
  246. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/interfaces/calculation.py +0 -0
  247. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/interfaces/database.py +0 -0
  248. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/interfaces/excel.py +0 -0
  249. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/interfaces/existing_model.py +0 -0
  250. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/interfaces/read_only.py +0 -0
  251. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/interfaces/remote_manager.py +0 -0
  252. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/interfaces/request.py +0 -0
  253. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/manifests/__init__.py +0 -0
  254. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/manifests/capability_builder.py +0 -0
  255. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/manifests/capability_manifest.py +0 -0
  256. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/manifests/capability_models.py +0 -0
  257. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/orm_interface.py +0 -0
  258. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/requests.py +0 -0
  259. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/unit_contract.py +0 -0
  260. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/utils/__init__.py +0 -0
  261. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/utils/database_interface_protocols.py +0 -0
  262. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/utils/errors.py +0 -0
  263. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/utils/history.py +0 -0
  264. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/interface/utils/models.py +0 -0
  265. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/logging.py +0 -0
  266. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/management/commands/chat_cleanup.py +0 -0
  267. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/management/commands/cleanup_upload_intents.py +0 -0
  268. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/management/commands/graphql_warmup.py +0 -0
  269. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/management/commands/graphql_warmup_refresh_due.py +0 -0
  270. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/management/commands/search_index.py +0 -0
  271. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/management/commands/search_reconcile.py +0 -0
  272. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/management/commands/seed_manager_landscape.py +0 -0
  273. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/management/commands/shell.py +0 -0
  274. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/management/commands/sync_read_only.py +0 -0
  275. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/management/commands/workflow_drain_outbox.py +0 -0
  276. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/management/commands/workflow_replay_dead_letters.py +0 -0
  277. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/manager/__init__.py +0 -0
  278. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/manager/bulk_create.py +0 -0
  279. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/manager/group_manager.py +0 -0
  280. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/measurement/__init__.py +0 -0
  281. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/measurement/measurement.py +0 -0
  282. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/measurement/measurement_field.py +0 -0
  283. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/metrics/__init__.py +0 -0
  284. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/metrics/graphql.py +0 -0
  285. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/migrations/0001_initial.py +0 -0
  286. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/migrations/0002_workflow_outbox_scaling_indexes.py +0 -0
  287. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/migrations/0003_workflow_execution_correlation_constraint.py +0 -0
  288. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/migrations/0004_chat_persistence_models.py +0 -0
  289. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/migrations/0004_search_index_state.py +0 -0
  290. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/migrations/0005_merge_chat_search.py +0 -0
  291. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/migrations/0006_chat_pending_confirmation_scoped_ids.py +0 -0
  292. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/migrations/0007_upload_intent.py +0 -0
  293. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/migrations/0008_upload_finalization_versions.py +0 -0
  294. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/migrations/0009_upload_cleanup_state.py +0 -0
  295. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/migrations/0010_chat_pending_confirmation_portable_uniqueness.py +0 -0
  296. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/migrations/0011_search_index_state_dirty_generation.py +0 -0
  297. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/migrations/0012_chat_context_watermarks.py +0 -0
  298. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/migrations/__init__.py +0 -0
  299. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/models.py +0 -0
  300. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/permission/__init__.py +0 -0
  301. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/permission/audit.py +0 -0
  302. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/permission/base_permission.py +0 -0
  303. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/permission/graphql_capabilities.py +0 -0
  304. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/permission/mutation_permission.py +0 -0
  305. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/permission/permission_checks.py +0 -0
  306. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/permission/permission_data_manager.py +0 -0
  307. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/permission/utils.py +0 -0
  308. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/public_api_registry.py +0 -0
  309. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/py.typed +0 -0
  310. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/rule/__init__.py +0 -0
  311. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/rule/handler.py +0 -0
  312. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/rule/rule.py +0 -0
  313. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/search/__init__.py +0 -0
  314. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/search/async_tasks.py +0 -0
  315. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/search/backend_registry.py +0 -0
  316. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/search/backends/__init__.py +0 -0
  317. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/search/backends/dev.py +0 -0
  318. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/search/backends/opensearch.py +0 -0
  319. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/search/backends/typesense.py +0 -0
  320. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/search/checks.py +0 -0
  321. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/search/identity.py +0 -0
  322. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/search/invalidation.py +0 -0
  323. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/search/m2m_invalidation.py +0 -0
  324. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/search/models.py +0 -0
  325. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/search/registry.py +0 -0
  326. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/search/tasks.py +0 -0
  327. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/search/utils.py +0 -0
  328. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/seeding/__init__.py +0 -0
  329. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/seeding/manager_landscape.py +0 -0
  330. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/uploads/__init__.py +0 -0
  331. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/uploads/adapters.py +0 -0
  332. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/uploads/checks.py +0 -0
  333. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/uploads/config.py +0 -0
  334. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/uploads/errors.py +0 -0
  335. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/uploads/finalization.py +0 -0
  336. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/uploads/graphql.py +0 -0
  337. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/uploads/graphql_types.py +0 -0
  338. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/uploads/metrics.py +0 -0
  339. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/uploads/models.py +0 -0
  340. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/uploads/public.py +0 -0
  341. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/uploads/s3.py +0 -0
  342. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/uploads/services.py +0 -0
  343. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/uploads/tokens.py +0 -0
  344. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/uploads/types.py +0 -0
  345. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/uploads/urls.py +0 -0
  346. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/uploads/views.py +0 -0
  347. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/utils/__init__.py +0 -0
  348. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/utils/_args_to_kwargs.py +0 -0
  349. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/utils/_cache_key_encoder.py +0 -0
  350. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/utils/_make_cache_key.py +0 -0
  351. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/utils/_none_to_zero.py +0 -0
  352. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/utils/executable_contract.py +0 -0
  353. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/utils/filter_parser.py +0 -0
  354. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/utils/format_string.py +0 -0
  355. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/utils/json_encoder.py +0 -0
  356. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/utils/path_mapping.py +0 -0
  357. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/utils/public_api.py +0 -0
  358. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/utils/testing.py +0 -0
  359. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/utils/type_checks.py +0 -0
  360. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/workflow/__init__.py +0 -0
  361. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/workflow/actions.py +0 -0
  362. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/workflow/backend_registry.py +0 -0
  363. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/workflow/backends/__init__.py +0 -0
  364. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/workflow/backends/celery.py +0 -0
  365. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/workflow/backends/local.py +0 -0
  366. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/workflow/backends/n8n.py +0 -0
  367. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/workflow/config.py +0 -0
  368. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/workflow/engine.py +0 -0
  369. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/workflow/event_registry.py +0 -0
  370. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/workflow/events.py +0 -0
  371. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/workflow/models.py +0 -0
  372. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/workflow/signal_bridge.py +0 -0
  373. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/workflow/tasks.py +0 -0
  374. {generalmanager-0.87.5 → generalmanager-0.87.6}/src/general_manager/workflow/telemetry.py +0 -0
  375. {generalmanager-0.87.5 → generalmanager-0.87.6}/tests/test_settings.py +0 -0
  376. {generalmanager-0.87.5 → generalmanager-0.87.6}/tests/test_urls.py +0 -0
  377. {generalmanager-0.87.5 → generalmanager-0.87.6}/tests/testing_asgi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.87.5
3
+ Version: 0.87.6
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.87.5"
7
+ version = "0.87.6"
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.87.5
3
+ Version: 0.87.6
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
@@ -221,6 +221,7 @@ src/general_manager/interface/capabilities/orm/lifecycle.py
221
221
  src/general_manager/interface/capabilities/orm/mutations.py
222
222
  src/general_manager/interface/capabilities/orm/support.py
223
223
  src/general_manager/interface/capabilities/orm_utils/__init__.py
224
+ src/general_manager/interface/capabilities/orm_utils/collection_probes.py
224
225
  src/general_manager/interface/capabilities/orm_utils/django_manager_utils.py
225
226
  src/general_manager/interface/capabilities/orm_utils/field_descriptors.py
226
227
  src/general_manager/interface/capabilities/orm_utils/payload_normalizer.py
@@ -301,6 +302,7 @@ src/general_manager/rule/handler.py
301
302
  src/general_manager/rule/rule.py
302
303
  src/general_manager/search/__init__.py
303
304
  src/general_manager/search/async_tasks.py
305
+ src/general_manager/search/authorization.py
304
306
  src/general_manager/search/backend.py
305
307
  src/general_manager/search/backend_registry.py
306
308
  src/general_manager/search/checks.py
@@ -310,6 +312,7 @@ src/general_manager/search/indexer.py
310
312
  src/general_manager/search/invalidation.py
311
313
  src/general_manager/search/m2m_invalidation.py
312
314
  src/general_manager/search/models.py
315
+ src/general_manager/search/projection.py
313
316
  src/general_manager/search/reconciliation.py
314
317
  src/general_manager/search/registry.py
315
318
  src/general_manager/search/tasks.py
@@ -0,0 +1,619 @@
1
+ """Authorize query operands before they influence membership or ordering."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Iterable
6
+ from dataclasses import dataclass, field
7
+ from inspect import getattr_static
8
+ from typing import TYPE_CHECKING, cast
9
+
10
+ from graphql import GraphQLError
11
+
12
+ from general_manager.bucket.base_bucket import Bucket
13
+ from general_manager.bucket.request_bucket import RequestBucket
14
+ from general_manager.manager.general_manager import GeneralManager
15
+ from general_manager.manager.meta import GeneralManagerMeta
16
+
17
+ if TYPE_CHECKING:
18
+ from graphene import ResolveInfo
19
+ from general_manager.interface.base_interface import (
20
+ AttributeTypedDict,
21
+ InterfaceBase,
22
+ )
23
+
24
+
25
+ class QueryFieldPermissionError(GraphQLError):
26
+ """A requested operand is not authorized on the candidate scope."""
27
+
28
+ def __init__(self, field: str) -> None:
29
+ super().__init__(f"Permission denied to use query field '{field}'.")
30
+
31
+
32
+ _LIMIT_ERROR = "Query field authorization candidate limit exceeded."
33
+ _AMBIGUOUS_ERROR = "Cannot authorize ambiguous query relation."
34
+ _RELATION_ERROR = "Permission denied to traverse query relation."
35
+
36
+
37
+ class QueryRelationPermissionError(GraphQLError):
38
+ """A search candidate contains a related row the actor cannot read."""
39
+
40
+ def __init__(self) -> None:
41
+ super().__init__(_RELATION_ERROR)
42
+
43
+
44
+ INCOMPLETE_ERROR = "Query field authorization requires a complete candidate set."
45
+ CUSTOM_PROJECTION_ERROR = (
46
+ "Cannot authorize fields of a custom search document projection."
47
+ )
48
+
49
+ # Bound field/path decisions; bucket materialization and row checks precede this.
50
+ MAX_QUERY_PERMISSION_CANDIDATES = 1000
51
+ _LOOKUPS = {
52
+ "exact",
53
+ "iexact",
54
+ "in",
55
+ "isnull",
56
+ "lt",
57
+ "lte",
58
+ "gt",
59
+ "gte",
60
+ "contains",
61
+ "icontains",
62
+ "startswith",
63
+ "istartswith",
64
+ "endswith",
65
+ "iendswith",
66
+ "range",
67
+ }
68
+
69
+
70
+ @dataclass(slots=True)
71
+ class _NativePathNode:
72
+ """One shared native source prefix, without storing permission decisions."""
73
+
74
+ children: dict[str, _NativePathNode] = field(default_factory=dict)
75
+
76
+
77
+ @dataclass(slots=True)
78
+ class QueryFieldAuthorizationBudget:
79
+ """Share only accounting across authorization calls in one operation."""
80
+
81
+ decisions: int = 0
82
+
83
+ def charge(self) -> None:
84
+ """Reject work exceeding the operation's field/path decision limit."""
85
+ self.decisions += 1
86
+ if self.decisions > MAX_QUERY_PERMISSION_CANDIDATES:
87
+ raise GraphQLError(_LIMIT_ERROR)
88
+
89
+
90
+ def _operand_field_names(
91
+ manager: type[GeneralManager],
92
+ field_name: str,
93
+ attributes: dict[str, AttributeTypedDict],
94
+ *,
95
+ native_paths: bool,
96
+ ) -> tuple[list[str], set[str], set[str]]:
97
+ """Resolve the existing field/relationship spellings for one operand."""
98
+ from general_manager.api.graphql_relations import (
99
+ get_graphql_manager_registry,
100
+ resolve_general_manager_type,
101
+ )
102
+ from general_manager.api.graphql_resolvers import relation_id_alias_field
103
+
104
+ aliases = (
105
+ []
106
+ if native_paths
107
+ else [
108
+ name
109
+ for name, metadata in attributes.items()
110
+ if metadata.get("filter_lookup", name) == field_name
111
+ ]
112
+ )
113
+ names = set(aliases or [field_name])
114
+ native_relations: set[str] = set()
115
+ for name in tuple(names):
116
+ relation = relation_id_alias_field(manager, name, native_source=native_paths)
117
+ if not native_paths and relation is None and name.endswith("_id"):
118
+ alias = name.removesuffix("_id")
119
+ metadata: dict[str, object] = dict(attributes.get(alias, {}))
120
+ if (
121
+ resolve_general_manager_type(
122
+ metadata.get("type"), get_graphql_manager_registry()
123
+ )
124
+ is not None
125
+ ):
126
+ relation = alias
127
+ if relation is not None:
128
+ names.add(relation)
129
+ if native_paths:
130
+ native_relations.add(relation)
131
+ return aliases, names, native_relations
132
+
133
+
134
+ def _unchanged_metadata_methods(
135
+ owner: object, bindings: Iterable[tuple[str, object, object]]
136
+ ) -> bool:
137
+ """Check the actual metadata owners, including instance and code overrides."""
138
+ from general_manager.utils.executable_contract import executable_matches
139
+
140
+ for name, original, signature in bindings:
141
+ if getattr_static(owner, name, None) is not original:
142
+ return False
143
+ executable = (
144
+ original.__func__ if isinstance(original, classmethod) else original
145
+ )
146
+ if not executable_matches(executable, signature):
147
+ return False
148
+ return True
149
+
150
+
151
+ @dataclass(frozen=True, slots=True)
152
+ class _FlatQueryField:
153
+ """Structure only: runtime decisions still run in the original order."""
154
+
155
+ names: tuple[str, ...]
156
+ additional: bool
157
+
158
+
159
+ @dataclass(slots=True)
160
+ class _NativeQueryStructure:
161
+ """One call's stable standard ORM schema and declarative policy structure."""
162
+
163
+ manager: type[GeneralManager]
164
+ interface: type[InterfaceBase]
165
+ permission: object
166
+ attributes: dict[str, AttributeTypedDict]
167
+ properties: frozenset[str]
168
+ fields: dict[tuple[str, ...], _FlatQueryField | None] = field(default_factory=dict)
169
+ additional: dict[str, bool | None] = field(default_factory=dict)
170
+
171
+ def flat_field(self, parts: tuple[str, ...]) -> _FlatQueryField | None:
172
+ """Prepare only a visited, known flat operand; keep general paths dynamic."""
173
+ if parts in self.fields:
174
+ return self.fields[parts]
175
+ from general_manager.api.graphql_relations import (
176
+ get_graphql_manager_registry,
177
+ resolve_general_manager_type,
178
+ )
179
+ from general_manager.permission.manager_based_permission import (
180
+ additional_local_read_permission,
181
+ )
182
+
183
+ self.fields[parts] = None
184
+ field_name, *rest = parts
185
+ if len(rest) > 1 or (rest and rest[0] not in _LOOKUPS):
186
+ return None
187
+ aliases, names, _ = _operand_field_names(
188
+ self.manager, field_name, self.attributes, native_paths=False
189
+ )
190
+ if (
191
+ len(aliases) > 1
192
+ or not names.intersection(self.attributes)
193
+ or names.intersection(self.properties)
194
+ ):
195
+ return None
196
+ metadata: dict[str, object] = dict(
197
+ self.attributes.get(aliases[0] if aliases else field_name, {})
198
+ )
199
+ annotation = metadata.get("type")
200
+ identity_alias = field_name.endswith("_id") and len(names) > 1
201
+ if not identity_alias and (
202
+ type(annotation) is not type
203
+ or (
204
+ (
205
+ back_reference := getattr_static(
206
+ annotation, "_general_manager_class", None
207
+ )
208
+ )
209
+ is not None
210
+ and type(back_reference) is not GeneralManagerMeta
211
+ )
212
+ or resolve_general_manager_type(annotation, get_graphql_manager_registry())
213
+ is not None
214
+ or metadata.get("relation_kind") in {"direct", "collection"}
215
+ ):
216
+ return None
217
+ # Rule definitions, including their lists/dicts, are stable for this
218
+ # call. No actor/object result or Permission instance is retained.
219
+ for name in names:
220
+ if name not in self.additional:
221
+ self.additional[name] = additional_local_read_permission(
222
+ self.permission, name
223
+ )
224
+ if self.additional[name] is None:
225
+ return None
226
+ prepared = _FlatQueryField(
227
+ tuple(names), any(self.additional[name] for name in names)
228
+ )
229
+ self.fields[parts] = prepared
230
+ return prepared
231
+
232
+
233
+ def _prepare_native_query_structure(
234
+ manager: type[GeneralManager],
235
+ ) -> _NativeQueryStructure | None:
236
+ """Attest canonical metadata providers without evaluating a permission."""
237
+ from general_manager.interface.base_interface import _NATIVE_QUERY_METADATA_METHODS
238
+ from general_manager.interface.capabilities.orm import support as orm_support
239
+ from general_manager.interface.capabilities.orm_utils.field_descriptors import (
240
+ FieldDescriptor,
241
+ )
242
+ from general_manager.interface.manifests.capability_models import (
243
+ CapabilitySelection,
244
+ )
245
+ from general_manager.interface.orm_interface import OrmInterfaceBase
246
+ from general_manager.permission.manager_based_permission import (
247
+ _can_prepare_local_read_definitions,
248
+ )
249
+ from general_manager.utils.executable_contract import executable_matches
250
+
251
+ interface = getattr_static(manager, "Interface", None)
252
+ permission = getattr_static(manager, "Permission", None)
253
+ if (
254
+ type(interface) is not type(OrmInterfaceBase)
255
+ or not issubclass(interface, OrmInterfaceBase)
256
+ or not _unchanged_metadata_methods(interface, _NATIVE_QUERY_METADATA_METHODS)
257
+ or getattr_static(permission, "__based_on__", None) is not None
258
+ or not _can_prepare_local_read_definitions(permission)
259
+ ):
260
+ return None
261
+ # Canonical wrappers may still read custom descriptors or mappings. Those
262
+ # are dynamic providers and must retain their original per-visit behavior.
263
+ if (
264
+ type(getattr_static(interface, "_capability_handlers", None)) is not dict
265
+ or type(getattr_static(interface, "_capability_selection", None))
266
+ is not CapabilitySelection
267
+ or getattr_static(interface, "_configured_capabilities_applied", None)
268
+ is not True
269
+ or getattr_static(interface, "_parent_class", None) is not manager
270
+ ):
271
+ return None
272
+ descriptors = getattr_static(interface, "_field_descriptors", None)
273
+ if type(descriptors) is not dict:
274
+ return None
275
+ if any(
276
+ type(name) is not str
277
+ or type(descriptor) is not FieldDescriptor
278
+ or type(descriptor.metadata) is not dict
279
+ for name, descriptor in descriptors.items()
280
+ ):
281
+ return None
282
+ resolver, signature = orm_support._NATIVE_QUERY_SUPPORT_RESOLVER
283
+ if orm_support.get_support_capability is not resolver or not executable_matches(
284
+ resolver, signature
285
+ ):
286
+ return None
287
+ for handler, capability in (
288
+ (interface.get_capability_handler("read"), orm_support.OrmReadCapability),
289
+ (
290
+ interface.get_capability_handler("orm_support"),
291
+ orm_support.OrmPersistenceSupportCapability,
292
+ ),
293
+ ):
294
+ if (
295
+ type(handler) is not capability
296
+ or getattr_static(type(handler), "__getattribute__", None)
297
+ is not object.__getattribute__
298
+ or not _unchanged_metadata_methods(
299
+ handler, orm_support._NATIVE_QUERY_METADATA_METHODS[capability]
300
+ )
301
+ ):
302
+ return None
303
+ return _NativeQueryStructure(
304
+ manager,
305
+ interface,
306
+ permission,
307
+ interface.get_attribute_types(),
308
+ frozenset(interface.get_graph_ql_properties()),
309
+ )
310
+
311
+
312
+ class _NativeQueryStructures:
313
+ """Lazily prepare a call's ordinary manager classes; never cache decisions."""
314
+
315
+ def __init__(self) -> None:
316
+ self.managers: dict[type[GeneralManager], _NativeQueryStructure | None] = {}
317
+
318
+ def flat_field(
319
+ self, instance: GeneralManager, parts: tuple[str, ...]
320
+ ) -> _FlatQueryField | None:
321
+ """Return a reusable flat-field plan only for unchanged native manager contracts."""
322
+ manager = type(instance)
323
+ if type(manager) is not GeneralManagerMeta:
324
+ return None
325
+ if manager not in self.managers:
326
+ from general_manager.interface.orm_interface import OrmInterfaceBase
327
+ from general_manager.manager.general_manager import (
328
+ _COMMON_MANAGER_EXECUTABLES,
329
+ _COMMON_MANAGER_GETATTR,
330
+ _COMMON_MANAGER_IDENTIFICATION,
331
+ )
332
+ from general_manager.permission.manager_based_permission import (
333
+ AdditiveManagerPermission,
334
+ )
335
+ from general_manager.utils.executable_contract import executable_matches
336
+
337
+ identification, identification_signature = _COMMON_MANAGER_IDENTIFICATION
338
+ if (
339
+ getattr_static(manager, "__getattribute__")
340
+ is not object.__getattribute__
341
+ or getattr_static(manager, "__getattr__") is not _COMMON_MANAGER_GETATTR
342
+ or getattr_static(manager, "identification") is not identification
343
+ or not executable_matches(identification.fget, identification_signature)
344
+ or not executable_matches(
345
+ _COMMON_MANAGER_GETATTR, _COMMON_MANAGER_EXECUTABLES[2][1]
346
+ )
347
+ ):
348
+ self.managers[manager] = None
349
+ return None
350
+ interface = getattr_static(manager, "Interface", None)
351
+ permission = getattr_static(manager, "Permission", None)
352
+ if (
353
+ type(interface) is not type(OrmInterfaceBase)
354
+ or getattr_static(type(interface), "__get__", None) is not None
355
+ or (
356
+ permission is not None
357
+ and (
358
+ type(permission) is not type(AdditiveManagerPermission)
359
+ or getattr_static(type(permission), "__get__", None) is not None
360
+ )
361
+ )
362
+ ):
363
+ self.managers[manager] = None
364
+ return None
365
+ if (
366
+ instance.Interface is not interface
367
+ or getattr(instance, "Permission", None) is not permission
368
+ ):
369
+ return None
370
+ self.managers[manager] = _prepare_native_query_structure(manager)
371
+ structure = self.managers[manager]
372
+ if (
373
+ structure is None
374
+ or instance.Interface is not structure.interface
375
+ or getattr(instance, "Permission", None) is not structure.permission
376
+ ):
377
+ return None
378
+ return structure.flat_field(parts)
379
+
380
+
381
+ def authorize_query_fields(
382
+ candidates: Iterable[GeneralManager],
383
+ info: ResolveInfo,
384
+ paths: Iterable[str],
385
+ *,
386
+ native_paths: bool = False,
387
+ budget_additional_permissions_only: bool = False,
388
+ budget: QueryFieldAuthorizationBudget | None = None,
389
+ prepare_native_structure: bool = False,
390
+ ) -> None:
391
+ """Check all operands against every row-visible candidate, never just hits.
392
+
393
+ Related rows require their own row permission as well as field permission.
394
+ Failure leaves the original candidate set unchanged and rejects the query.
395
+ ``native_paths`` checks exact projection sources without backend aliases or
396
+ lookup operators. Callers validate those paths statically before iteration.
397
+ Their shared prefixes are walked once for each candidate/member occurrence;
398
+ all child fields and related-row gates remain required. No decision is
399
+ reused between candidates, unrelated source branches or authorization calls.
400
+ Native list resolvers may budget only additional or unknown field policies.
401
+ That mode still executes every runtime field and related-row check; it
402
+ changes accounting, never the authorization decision or candidate scope.
403
+ Native database lists may prepare canonical flat ORM operand structure once
404
+ per call. This assumes schema and declarative rule definitions stay fixed
405
+ during the call; every runtime permission check remains. Custom providers
406
+ and complex paths retain the general traversal. A new call prepares afresh.
407
+ """
408
+ from general_manager.api.graphql_relations import (
409
+ resolve_general_manager_type,
410
+ get_graphql_manager_registry,
411
+ )
412
+ from general_manager.api.graphql_resolvers import (
413
+ can_read_instance,
414
+ check_read_permission,
415
+ )
416
+
417
+ normalized = set()
418
+ for path in paths:
419
+ parts = path.split("__")
420
+ if parts:
421
+ normalized.add(tuple(parts))
422
+ if not normalized:
423
+ return
424
+ normalized_paths = sorted(normalized)
425
+ native_root = _NativePathNode()
426
+ if native_paths:
427
+ for native_parts in normalized_paths:
428
+ node = native_root
429
+ for part in native_parts:
430
+ node = node.children.setdefault(part, _NativePathNode())
431
+ budget = budget or QueryFieldAuthorizationBudget()
432
+ structures = (
433
+ _NativeQueryStructures()
434
+ if prepare_native_structure
435
+ and budget_additional_permissions_only
436
+ and not native_paths
437
+ else None
438
+ )
439
+
440
+ def needs_additional_budget(instance: GeneralManager, names: set[str]) -> bool:
441
+ """Inspect the current policy, including subtype and instance overrides."""
442
+ from inspect import getattr_static
443
+
444
+ from general_manager.permission.base_permission import BasePermission
445
+ from general_manager.permission.manager_based_permission import (
446
+ additional_local_read_permission,
447
+ )
448
+
449
+ permission = getattr(instance, "Permission", None)
450
+ if permission is None:
451
+ return False
452
+ if not isinstance(permission, type) or not issubclass(
453
+ permission, BasePermission
454
+ ):
455
+ return True
456
+ # A delegated object's runtime type and nullable fallback can tighten
457
+ # the local rule. Keep that proof outside this accounting shortcut.
458
+ if getattr_static(permission, "__based_on__", None) is not None:
459
+ return True
460
+ return any(
461
+ additional_local_read_permission(permission, name) is not False
462
+ for name in names
463
+ )
464
+
465
+ def check(
466
+ instance: GeneralManager,
467
+ parts: tuple[str, ...],
468
+ native_node: _NativePathNode | None = None,
469
+ ) -> None:
470
+ """Authorize one exact operand path, charging each visited field decision."""
471
+ prepared = structures.flat_field(instance, parts) if structures else None
472
+ if prepared is not None:
473
+ if prepared.additional:
474
+ budget.charge()
475
+ # Identification is per object. Preserve its validation/errors at
476
+ # the original point even though the field is already known.
477
+ set(instance.identification)
478
+ if any(
479
+ not check_read_permission(instance, info, name)
480
+ for name in prepared.names
481
+ ):
482
+ raise QueryFieldPermissionError(parts[0])
483
+ return
484
+ if not budget_additional_permissions_only:
485
+ budget.charge()
486
+ field, *rest = parts
487
+ attributes = instance.Interface.get_attribute_types()
488
+ # Backend collection lookup names can differ from public manager names.
489
+ aliases, names, native_relations = _operand_field_names(
490
+ type(instance), field, attributes, native_paths=native_paths
491
+ )
492
+ if budget_additional_permissions_only and needs_additional_budget(
493
+ instance, names
494
+ ):
495
+ budget.charge()
496
+ known_fields = set(attributes) | set(instance.identification)
497
+ known_fields.update(instance.Interface.get_graph_ql_properties())
498
+ known_fields.update(instance.Interface.get_attributes())
499
+ known_fields.update(instance.Interface.input_fields)
500
+ if not names.intersection(known_fields):
501
+ raise QueryFieldPermissionError(field)
502
+ if any(not check_read_permission(instance, info, name) for name in names):
503
+ raise QueryFieldPermissionError(field)
504
+ for relation in sorted(native_relations):
505
+ # An ORM attname is a scalar spelling of a related field. Give it
506
+ # the same target row/leaf gates as an explicit relation path.
507
+ value = getattr(instance, relation)
508
+ if value is None:
509
+ continue
510
+ related_type = resolve_general_manager_type(
511
+ attributes[relation].get("type"), get_graphql_manager_registry()
512
+ )
513
+ if (
514
+ not isinstance(value, GeneralManager)
515
+ or related_type is None
516
+ or not isinstance(value, related_type)
517
+ ):
518
+ raise GraphQLError(_RELATION_ERROR)
519
+ if not can_read_instance(value, info):
520
+ raise QueryRelationPermissionError()
521
+ from django.db import models
522
+ from general_manager.interface.orm_interface import OrmInterfaceBase
523
+
524
+ orm_interface = cast(
525
+ type[OrmInterfaceBase[models.Model]], instance.Interface
526
+ )
527
+ foreign_key = orm_interface._model._meta.get_field(relation)
528
+ target_field = getattr(foreign_key, "target_field", None)
529
+ if not isinstance(target_field, models.Field):
530
+ raise GraphQLError(_RELATION_ERROR)
531
+ target_names = {target_field.name}
532
+ if target_field.primary_key:
533
+ target_names.add("id")
534
+ for target_name in sorted(target_names):
535
+ check(value, (target_name,))
536
+ if not rest and not (native_node and native_node.children):
537
+ return
538
+ if len(aliases) > 1:
539
+ raise GraphQLError(_AMBIGUOUS_ERROR)
540
+ field_metadata: dict[str, object] = dict(
541
+ attributes.get(aliases[0] if aliases else field, {})
542
+ )
543
+ if native_paths:
544
+ from general_manager.search.projection import source_field_annotation
545
+
546
+ _, annotation = source_field_annotation(type(instance), field)
547
+ field_metadata["type"] = annotation
548
+ if (
549
+ not native_paths
550
+ and len(rest) == 1
551
+ and rest[0] in _LOOKUPS
552
+ and (
553
+ (field.endswith("_id") and len(names) > 1)
554
+ or (
555
+ field_metadata.get("type") is not None
556
+ and resolve_general_manager_type(
557
+ field_metadata.get("type"), get_graphql_manager_registry()
558
+ )
559
+ is None
560
+ and field_metadata.get("relation_kind")
561
+ not in {"direct", "collection"}
562
+ )
563
+ )
564
+ ):
565
+ return
566
+ related_type = resolve_general_manager_type(
567
+ field_metadata.get("type"), get_graphql_manager_registry()
568
+ )
569
+ if (
570
+ not native_paths
571
+ and len(rest) == 1
572
+ and rest[0] in _LOOKUPS
573
+ and related_type is not None
574
+ ):
575
+ related_fields = set(related_type.Interface.get_attribute_types())
576
+ related_fields.update(related_type.Interface.get_attributes())
577
+ related_fields.update(related_type.Interface.get_graph_ql_properties())
578
+ if rest[0] not in related_fields:
579
+ return
580
+ value = getattr(instance, aliases[0] if aliases else field)
581
+ if value is None:
582
+ return
583
+ related = value if isinstance(value, (Bucket, list, tuple, set)) else [value]
584
+ for member in related:
585
+ if not isinstance(member, GeneralManager):
586
+ # A lookup is an operator only after resolving its preceding
587
+ # scalar field. A relation's field named "contains" is a field.
588
+ if not native_paths and len(rest) == 1 and rest[0] in _LOOKUPS:
589
+ continue
590
+ raise GraphQLError(_RELATION_ERROR)
591
+ if (
592
+ native_paths
593
+ and related_type is not None
594
+ and not isinstance(member, related_type)
595
+ ):
596
+ raise GraphQLError(_RELATION_ERROR)
597
+ if not can_read_instance(member, info):
598
+ raise QueryRelationPermissionError()
599
+ if native_node is None:
600
+ check(member, tuple(rest))
601
+ else:
602
+ for child_field, child in sorted(native_node.children.items()):
603
+ check(member, (child_field,), child)
604
+ if (
605
+ native_paths
606
+ and isinstance(related, RequestBucket)
607
+ and not related.response_is_complete
608
+ ):
609
+ raise GraphQLError(INCOMPLETE_ERROR)
610
+
611
+ for candidate in candidates:
612
+ if native_paths:
613
+ for native_field, native_node in sorted(native_root.children.items()):
614
+ check(candidate, (native_field,), native_node)
615
+ else:
616
+ for normalized_parts in normalized_paths:
617
+ check(candidate, normalized_parts)
618
+ if isinstance(candidates, RequestBucket) and not candidates.response_is_complete:
619
+ raise GraphQLError(INCOMPLETE_ERROR)