GeneralManager 0.82.3__tar.gz → 0.82.5__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 (341) hide show
  1. {generalmanager-0.82.3/src/GeneralManager.egg-info → generalmanager-0.82.5}/PKG-INFO +1 -1
  2. {generalmanager-0.82.3 → generalmanager-0.82.5}/pyproject.toml +1 -1
  3. {generalmanager-0.82.3 → generalmanager-0.82.5/src/GeneralManager.egg-info}/PKG-INFO +1 -1
  4. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/GeneralManager.egg-info/SOURCES.txt +1 -0
  5. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/_types/search.py +4 -0
  6. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/graphql.py +7 -0
  7. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/graphql_output.py +44 -1
  8. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/graphql_search.py +5 -1
  9. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/graphql_type.py +8 -1
  10. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/management/commands/search_index.py +2 -12
  11. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/public_api_registry.py +5 -0
  12. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/search/backend.py +7 -2
  13. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/search/backends/dev.py +36 -1
  14. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/search/backends/meilisearch.py +106 -13
  15. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/search/config.py +26 -1
  16. generalmanager-0.82.5/src/general_manager/search/identity.py +287 -0
  17. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/search/indexer.py +16 -0
  18. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/search/reconciliation.py +14 -1
  19. {generalmanager-0.82.3 → generalmanager-0.82.5}/LICENSE +0 -0
  20. {generalmanager-0.82.3 → generalmanager-0.82.5}/README.md +0 -0
  21. {generalmanager-0.82.3 → generalmanager-0.82.5}/setup.cfg +0 -0
  22. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/GeneralManager.egg-info/dependency_links.txt +0 -0
  23. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/GeneralManager.egg-info/requires.txt +0 -0
  24. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/GeneralManager.egg-info/top_level.txt +0 -0
  25. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/__init__.py +0 -0
  26. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/_types/__init__.py +0 -0
  27. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/_types/api.py +0 -0
  28. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/_types/bucket.py +0 -0
  29. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/_types/cache.py +0 -0
  30. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/_types/dataframes.py +0 -0
  31. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/_types/factory.py +0 -0
  32. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/_types/general_manager.py +0 -0
  33. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/_types/interface.py +0 -0
  34. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/_types/manager.py +0 -0
  35. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/_types/measurement.py +0 -0
  36. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/_types/permission.py +0 -0
  37. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/_types/rule.py +0 -0
  38. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/_types/utils.py +0 -0
  39. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/__init__.py +0 -0
  40. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/graphql_as_of.py +0 -0
  41. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/graphql_errors.py +0 -0
  42. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/graphql_groups.py +0 -0
  43. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/graphql_identifiers.py +0 -0
  44. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/graphql_mutations.py +0 -0
  45. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/graphql_ordering.py +0 -0
  46. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/graphql_prefetch.py +0 -0
  47. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/graphql_relations.py +0 -0
  48. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/graphql_resolvers.py +0 -0
  49. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/graphql_subscription_consumer.py +0 -0
  50. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/graphql_subscriptions.py +0 -0
  51. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/graphql_view.py +0 -0
  52. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/graphql_warmup.py +0 -0
  53. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/graphql_warmup_registry.py +0 -0
  54. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/graphql_warmup_tasks.py +0 -0
  55. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/mutation.py +0 -0
  56. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/notification_batching.py +0 -0
  57. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/property.py +0 -0
  58. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/registry.py +0 -0
  59. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/remote_api.py +0 -0
  60. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/remote_invalidation.py +0 -0
  61. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/api/remote_invalidation_client.py +0 -0
  62. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/apps.py +0 -0
  63. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/as_of.py +0 -0
  64. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/bootstrap.py +0 -0
  65. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/bucket/__init__.py +0 -0
  66. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/bucket/_materialized_bucket.py +0 -0
  67. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/bucket/_ordering.py +0 -0
  68. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/bucket/base_bucket.py +0 -0
  69. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/bucket/calculation_bucket.py +0 -0
  70. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/bucket/database_bucket.py +0 -0
  71. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/bucket/excel_bucket.py +0 -0
  72. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/bucket/group_bucket.py +0 -0
  73. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/bucket/indexing.py +0 -0
  74. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/bucket/projection.py +0 -0
  75. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/bucket/request_bucket.py +0 -0
  76. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/cache/__init__.py +0 -0
  77. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/cache/_dependency_graph.py +0 -0
  78. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/cache/batch_refresh.py +0 -0
  79. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/cache/cache_decorator.py +0 -0
  80. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/cache/cache_tracker.py +0 -0
  81. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/cache/data_change_context.py +0 -0
  82. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/cache/dependency_cache.py +0 -0
  83. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/cache/dependency_index.py +0 -0
  84. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/cache/dependency_matching.py +0 -0
  85. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/cache/dependency_publish.py +0 -0
  86. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/cache/dependency_shards.py +0 -0
  87. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/cache/model_dependency_collector.py +0 -0
  88. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/cache/run_context.py +0 -0
  89. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/cache/run_context_lru.py +0 -0
  90. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/cache/signals.py +0 -0
  91. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/cache/transaction_barrier.py +0 -0
  92. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/__init__.py +0 -0
  93. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/audit.py +0 -0
  94. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/bootstrap.py +0 -0
  95. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/checks.py +0 -0
  96. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/consumer.py +0 -0
  97. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/context.py +0 -0
  98. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/errors.py +0 -0
  99. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/evals/__init__.py +0 -0
  100. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/evals/__main__.py +0 -0
  101. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/evals/baseline.py +0 -0
  102. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/evals/datasets/basic_queries.yaml +0 -0
  103. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/evals/datasets/demo_readiness.yaml +0 -0
  104. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/evals/datasets/edge_cases.yaml +0 -0
  105. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/evals/datasets/follow_ups.yaml +0 -0
  106. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/evals/datasets/large_schema.yaml +0 -0
  107. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/evals/datasets/multi_hop.yaml +0 -0
  108. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/evals/datasets/planned_orchestration.yaml +0 -0
  109. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/evals/diagnostics.py +0 -0
  110. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/evals/fingerprints.py +0 -0
  111. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/evals/fixtures.py +0 -0
  112. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/evals/judges/__init__.py +0 -0
  113. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/evals/judges/answer_quality.py +0 -0
  114. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/evals/judges/contract.py +0 -0
  115. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/evals/judges/result_accuracy.py +0 -0
  116. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/evals/judges/tool_sequence.py +0 -0
  117. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/evals/readiness.py +0 -0
  118. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/evals/runner.py +0 -0
  119. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/evals/traces.py +0 -0
  120. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/grounding.py +0 -0
  121. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/models.py +0 -0
  122. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/planned/__init__.py +0 -0
  123. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/planned/budget.py +0 -0
  124. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/planned/calculations.py +0 -0
  125. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/planned/catalog.py +0 -0
  126. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/planned/config.py +0 -0
  127. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/planned/events.py +0 -0
  128. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/planned/evidence.py +0 -0
  129. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/planned/models.py +0 -0
  130. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/planned/planner.py +0 -0
  131. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/planned/provider_calls.py +0 -0
  132. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/planned/resolver.py +0 -0
  133. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/planned/routing.py +0 -0
  134. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/planned/scheduler.py +0 -0
  135. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/planned/synthesis.py +0 -0
  136. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/planned/validation.py +0 -0
  137. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/providers/__init__.py +0 -0
  138. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/providers/_shared.py +0 -0
  139. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/providers/anthropic.py +0 -0
  140. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/providers/base.py +0 -0
  141. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/providers/google.py +0 -0
  142. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/providers/ollama.py +0 -0
  143. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/providers/openai.py +0 -0
  144. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/rate_limits.py +0 -0
  145. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/routing.py +0 -0
  146. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/schema_index.py +0 -0
  147. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/settings.py +0 -0
  148. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/signals.py +0 -0
  149. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/system_prompt.py +0 -0
  150. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/tool_metadata.py +0 -0
  151. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/tools.py +0 -0
  152. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/turns.py +0 -0
  153. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/chat/views.py +0 -0
  154. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/conf.py +0 -0
  155. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/dataframes/__init__.py +0 -0
  156. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/dataframes/measurements.py +0 -0
  157. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/factory/__init__.py +0 -0
  158. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/factory/auto_factory.py +0 -0
  159. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/factory/factories.py +0 -0
  160. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/factory/factory_methods.py +0 -0
  161. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/__init__.py +0 -0
  162. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/base_interface.py +0 -0
  163. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/bundles/__init__.py +0 -0
  164. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/bundles/calculation.py +0 -0
  165. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/bundles/database.py +0 -0
  166. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/bundles/excel.py +0 -0
  167. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/bundles/remote_manager.py +0 -0
  168. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/bundles/request.py +0 -0
  169. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/__init__.py +0 -0
  170. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/base.py +0 -0
  171. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/builtin.py +0 -0
  172. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/calculation/__init__.py +0 -0
  173. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/calculation/_compat.py +0 -0
  174. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/calculation/input_resolution.py +0 -0
  175. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/calculation/lifecycle.py +0 -0
  176. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/configuration.py +0 -0
  177. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/core/observability.py +0 -0
  178. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/core/utils.py +0 -0
  179. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/excel/__init__.py +0 -0
  180. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/exceptions.py +0 -0
  181. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/existing_model/__init__.py +0 -0
  182. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/existing_model/_compat.py +0 -0
  183. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/existing_model/resolution.py +0 -0
  184. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/factory.py +0 -0
  185. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/orm/__init__.py +0 -0
  186. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/orm/_compat.py +0 -0
  187. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/orm/bulk.py +0 -0
  188. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/orm/create_many.py +0 -0
  189. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/orm/history.py +0 -0
  190. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/orm/lifecycle.py +0 -0
  191. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/orm/mutations.py +0 -0
  192. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/orm/support.py +0 -0
  193. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/orm_utils/__init__.py +0 -0
  194. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/orm_utils/django_manager_utils.py +0 -0
  195. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/orm_utils/field_descriptors.py +0 -0
  196. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/orm_utils/payload_normalizer.py +0 -0
  197. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/orm_utils/update_state.py +0 -0
  198. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/read_only/__init__.py +0 -0
  199. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/read_only/_compat.py +0 -0
  200. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/read_only/_types.py +0 -0
  201. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/read_only/lifecycle.py +0 -0
  202. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/read_only/management.py +0 -0
  203. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/registry.py +0 -0
  204. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/remote_manager.py +0 -0
  205. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/capabilities/request/__init__.py +0 -0
  206. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/excel.py +0 -0
  207. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/excel_store.py +0 -0
  208. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/excel_workbook.py +0 -0
  209. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/infrastructure/__init__.py +0 -0
  210. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/infrastructure/startup_hooks.py +0 -0
  211. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/infrastructure/system_checks.py +0 -0
  212. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/interfaces/__init__.py +0 -0
  213. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/interfaces/calculation.py +0 -0
  214. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/interfaces/database.py +0 -0
  215. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/interfaces/excel.py +0 -0
  216. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/interfaces/existing_model.py +0 -0
  217. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/interfaces/read_only.py +0 -0
  218. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/interfaces/remote_manager.py +0 -0
  219. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/interfaces/request.py +0 -0
  220. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/manifests/__init__.py +0 -0
  221. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/manifests/capability_builder.py +0 -0
  222. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/manifests/capability_manifest.py +0 -0
  223. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/manifests/capability_models.py +0 -0
  224. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/orm_interface.py +0 -0
  225. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/requests.py +0 -0
  226. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/utils/__init__.py +0 -0
  227. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/utils/database_interface_protocols.py +0 -0
  228. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/utils/errors.py +0 -0
  229. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/utils/history.py +0 -0
  230. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/interface/utils/models.py +0 -0
  231. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/logging.py +0 -0
  232. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/management/commands/chat_cleanup.py +0 -0
  233. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/management/commands/cleanup_upload_intents.py +0 -0
  234. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/management/commands/graphql_warmup.py +0 -0
  235. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/management/commands/graphql_warmup_refresh_due.py +0 -0
  236. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/management/commands/search_reconcile.py +0 -0
  237. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/management/commands/seed_manager_landscape.py +0 -0
  238. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/management/commands/shell.py +0 -0
  239. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/management/commands/workflow_drain_outbox.py +0 -0
  240. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/management/commands/workflow_replay_dead_letters.py +0 -0
  241. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/manager/__init__.py +0 -0
  242. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/manager/bulk_create.py +0 -0
  243. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/manager/general_manager.py +0 -0
  244. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/manager/group_manager.py +0 -0
  245. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/manager/input.py +0 -0
  246. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/manager/meta.py +0 -0
  247. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/measurement/__init__.py +0 -0
  248. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/measurement/measurement.py +0 -0
  249. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/measurement/measurement_field.py +0 -0
  250. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/metrics/__init__.py +0 -0
  251. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/metrics/graphql.py +0 -0
  252. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/migrations/0001_initial.py +0 -0
  253. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/migrations/0002_workflow_outbox_scaling_indexes.py +0 -0
  254. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/migrations/0003_workflow_execution_correlation_constraint.py +0 -0
  255. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/migrations/0004_chat_persistence_models.py +0 -0
  256. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/migrations/0004_search_index_state.py +0 -0
  257. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/migrations/0005_merge_chat_search.py +0 -0
  258. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/migrations/0006_chat_pending_confirmation_scoped_ids.py +0 -0
  259. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/migrations/0007_upload_intent.py +0 -0
  260. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/migrations/0008_upload_finalization_versions.py +0 -0
  261. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/migrations/0009_upload_cleanup_state.py +0 -0
  262. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/migrations/0010_chat_pending_confirmation_portable_uniqueness.py +0 -0
  263. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/migrations/0011_search_index_state_dirty_generation.py +0 -0
  264. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/migrations/0012_chat_context_watermarks.py +0 -0
  265. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/migrations/__init__.py +0 -0
  266. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/models.py +0 -0
  267. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/permission/__init__.py +0 -0
  268. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/permission/audit.py +0 -0
  269. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/permission/base_permission.py +0 -0
  270. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/permission/graphql_capabilities.py +0 -0
  271. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/permission/manager_based_permission.py +0 -0
  272. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/permission/mutation_permission.py +0 -0
  273. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/permission/permission_checks.py +0 -0
  274. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/permission/permission_data_manager.py +0 -0
  275. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/permission/utils.py +0 -0
  276. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/py.typed +0 -0
  277. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/rule/__init__.py +0 -0
  278. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/rule/handler.py +0 -0
  279. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/rule/rule.py +0 -0
  280. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/search/__init__.py +0 -0
  281. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/search/async_tasks.py +0 -0
  282. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/search/backend_registry.py +0 -0
  283. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/search/backends/__init__.py +0 -0
  284. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/search/backends/opensearch.py +0 -0
  285. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/search/backends/typesense.py +0 -0
  286. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/search/checks.py +0 -0
  287. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/search/invalidation.py +0 -0
  288. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/search/m2m_invalidation.py +0 -0
  289. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/search/models.py +0 -0
  290. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/search/registry.py +0 -0
  291. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/search/tasks.py +0 -0
  292. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/search/utils.py +0 -0
  293. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/seeding/__init__.py +0 -0
  294. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/seeding/manager_landscape.py +0 -0
  295. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/uploads/__init__.py +0 -0
  296. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/uploads/adapters.py +0 -0
  297. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/uploads/checks.py +0 -0
  298. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/uploads/config.py +0 -0
  299. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/uploads/errors.py +0 -0
  300. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/uploads/finalization.py +0 -0
  301. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/uploads/graphql.py +0 -0
  302. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/uploads/graphql_types.py +0 -0
  303. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/uploads/metrics.py +0 -0
  304. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/uploads/models.py +0 -0
  305. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/uploads/public.py +0 -0
  306. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/uploads/s3.py +0 -0
  307. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/uploads/services.py +0 -0
  308. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/uploads/tokens.py +0 -0
  309. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/uploads/types.py +0 -0
  310. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/uploads/urls.py +0 -0
  311. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/uploads/views.py +0 -0
  312. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/utils/__init__.py +0 -0
  313. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/utils/_args_to_kwargs.py +0 -0
  314. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/utils/_cache_key_encoder.py +0 -0
  315. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/utils/_make_cache_key.py +0 -0
  316. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/utils/_none_to_zero.py +0 -0
  317. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/utils/filter_parser.py +0 -0
  318. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/utils/format_string.py +0 -0
  319. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/utils/json_encoder.py +0 -0
  320. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/utils/path_mapping.py +0 -0
  321. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/utils/public_api.py +0 -0
  322. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/utils/testing.py +0 -0
  323. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/utils/type_checks.py +0 -0
  324. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/workflow/__init__.py +0 -0
  325. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/workflow/actions.py +0 -0
  326. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/workflow/backend_registry.py +0 -0
  327. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/workflow/backends/__init__.py +0 -0
  328. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/workflow/backends/celery.py +0 -0
  329. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/workflow/backends/local.py +0 -0
  330. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/workflow/backends/n8n.py +0 -0
  331. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/workflow/config.py +0 -0
  332. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/workflow/engine.py +0 -0
  333. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/workflow/event_registry.py +0 -0
  334. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/workflow/events.py +0 -0
  335. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/workflow/models.py +0 -0
  336. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/workflow/signal_bridge.py +0 -0
  337. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/workflow/tasks.py +0 -0
  338. {generalmanager-0.82.3 → generalmanager-0.82.5}/src/general_manager/workflow/telemetry.py +0 -0
  339. {generalmanager-0.82.3 → generalmanager-0.82.5}/tests/test_settings.py +0 -0
  340. {generalmanager-0.82.3 → generalmanager-0.82.5}/tests/test_urls.py +0 -0
  341. {generalmanager-0.82.3 → generalmanager-0.82.5}/tests/testing_asgi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.82.3
3
+ Version: 0.82.5
4
4
  Summary: Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching.
5
5
  Author-email: Tim Kleindick <tkleindick@yahoo.de>
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "GeneralManager"
7
- version = "0.82.3"
7
+ version = "0.82.5"
8
8
  description = "Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching."
9
9
  readme = "README.md"
10
10
  authors = [{ name = "Tim Kleindick", email = "tkleindick@yahoo.de" }]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.82.3
3
+ Version: 0.82.5
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
@@ -274,6 +274,7 @@ src/general_manager/search/backend.py
274
274
  src/general_manager/search/backend_registry.py
275
275
  src/general_manager/search/checks.py
276
276
  src/general_manager/search/config.py
277
+ src/general_manager/search/identity.py
277
278
  src/general_manager/search/indexer.py
278
279
  src/general_manager/search/invalidation.py
279
280
  src/general_manager/search/m2m_invalidation.py
@@ -18,10 +18,12 @@ __all__ = [
18
18
  "SearchConfigSpec",
19
19
  "SearchDocument",
20
20
  "SearchHit",
21
+ "SearchIdentityFilterGroup",
21
22
  "SearchIndexer",
22
23
  "SearchInvalidationRule",
23
24
  "SearchResult",
24
25
  "TypesenseBackend",
26
+ "build_search_filters",
25
27
  "configure_search_backend",
26
28
  "configure_search_backend_from_settings",
27
29
  "get_search_backend",
@@ -44,10 +46,12 @@ from general_manager.search.config import SearchConfigProtocol
44
46
  from general_manager.search.config import SearchConfigSpec
45
47
  from general_manager.search.backend import SearchDocument
46
48
  from general_manager.search.backend import SearchHit
49
+ from general_manager.search.identity import SearchIdentityFilterGroup
47
50
  from general_manager.search.indexer import SearchIndexer
48
51
  from general_manager.search.config import SearchInvalidationRule
49
52
  from general_manager.search.backend import SearchResult
50
53
  from general_manager.search.backends.typesense import TypesenseBackend
54
+ from general_manager.search.identity import build_search_filters
51
55
  from general_manager.search.backend_registry import configure_search_backend
52
56
  from general_manager.search.backend_registry import (
53
57
  configure_search_backend_from_settings,
@@ -100,6 +100,7 @@ from general_manager.api.graphql_mutations import (
100
100
  generate_delete_mutation_class as _generate_delete_mutation_class_fn,
101
101
  )
102
102
  from general_manager.api.graphql_output import (
103
+ GraphQLOutputIdentityMetadataError,
103
104
  create_output_field_resolver,
104
105
  map_graphql_output_annotation,
105
106
  resolve_output_type_hints,
@@ -518,6 +519,11 @@ class GraphQL:
518
519
  )
519
520
  fields: dict[str, graphene.Field] = {}
520
521
  for declared_field in dataclasses.fields(output_class):
522
+ is_identifier = declared_field.metadata.get("is_identifier", False)
523
+ if not isinstance(is_identifier, bool):
524
+ raise GraphQLOutputIdentityMetadataError(
525
+ output_name, declared_field.name, is_identifier
526
+ )
521
527
  mapped = map_graphql_output_annotation(
522
528
  hints[declared_field.name],
523
529
  owner_name=output_name,
@@ -528,6 +534,7 @@ class GraphQL:
528
534
  output_type_registry=cls.graphql_output_type_registry,
529
535
  measurement_type=MeasurementType,
530
536
  scalar_mapper=cls._map_field_to_graphene_base_type,
537
+ is_identifier=is_identifier,
531
538
  )
532
539
  field = cast(graphene.Field, mapped.field)
533
540
  field.resolver = create_output_field_resolver(
@@ -9,6 +9,7 @@ from decimal import Decimal
9
9
  import sys
10
10
  from types import UnionType
11
11
  from typing import Any, ForwardRef, Union, get_args, get_origin, get_type_hints
12
+ from uuid import UUID
12
13
 
13
14
  import graphene
14
15
 
@@ -40,6 +41,16 @@ class GraphQLOutputAnnotationError(TypeError):
40
41
  )
41
42
 
42
43
 
44
+ class GraphQLOutputIdentityMetadataError(TypeError):
45
+ """Raised when an output field's identity flag is not boolean."""
46
+
47
+ def __init__(self, owner_name: str, field_name: str, flag: object) -> None:
48
+ super().__init__(
49
+ f"Invalid is_identifier metadata for {owner_name}.{field_name}: "
50
+ f"expected bool, got {flag!r}"
51
+ )
52
+
53
+
43
54
  @dataclass(frozen=True, slots=True)
44
55
  class _MappedAnnotation:
45
56
  """Internal Graphene type metadata before a field wrapper is mounted."""
@@ -144,6 +155,7 @@ def _map_collection_annotation(
144
155
  output_type_registry: Mapping[str, type[graphene.ObjectType]],
145
156
  measurement_type: type[graphene.ObjectType],
146
157
  scalar_mapper: Callable[[type], type],
158
+ is_identifier: bool = False,
147
159
  ) -> _MappedAnnotation:
148
160
  origin = get_origin(annotation)
149
161
  if origin not in (list, tuple, set):
@@ -159,6 +171,13 @@ def _map_collection_annotation(
159
171
  raise _annotation_error(owner_name, field_name, annotation)
160
172
  element_annotation = args[0]
161
173
 
174
+ if is_identifier:
175
+ _, identity_type = _unwrap_optional_annotation(
176
+ element_annotation, owner_name=owner_name, field_name=field_name
177
+ )
178
+ if identity_type not in (int, str, UUID):
179
+ raise _annotation_error(owner_name, field_name, annotation)
180
+
162
181
  element = _map_annotation(
163
182
  element_annotation,
164
183
  owner_name=owner_name,
@@ -169,6 +188,7 @@ def _map_collection_annotation(
169
188
  output_type_registry=output_type_registry,
170
189
  measurement_type=measurement_type,
171
190
  scalar_mapper=scalar_mapper,
191
+ is_identifier=is_identifier,
172
192
  )
173
193
  element_type = element.graphene_type
174
194
  if not element.nullable:
@@ -192,6 +212,7 @@ def _map_non_optional_value(
192
212
  output_type_registry: Mapping[str, type[graphene.ObjectType]],
193
213
  measurement_type: type[graphene.ObjectType],
194
214
  scalar_mapper: Callable[[type], type],
215
+ is_identifier: bool = False,
195
216
  ) -> _MappedAnnotation:
196
217
  annotation = _resolve_registered_name(
197
218
  annotation,
@@ -220,6 +241,17 @@ def _map_non_optional_value(
220
241
  output_type_registry=output_type_registry,
221
242
  measurement_type=measurement_type,
222
243
  scalar_mapper=scalar_mapper,
244
+ is_identifier=is_identifier,
245
+ )
246
+
247
+ if is_identifier:
248
+ if annotation not in (int, str, UUID):
249
+ raise _annotation_error(owner_name, field_name, annotation)
250
+ return _MappedAnnotation(
251
+ graphene.ID,
252
+ annotation,
253
+ nullable=False,
254
+ contains_measurement=False,
223
255
  )
224
256
 
225
257
  if safe_issubclass(annotation, GraphQLType):
@@ -290,6 +322,7 @@ def _map_annotation(
290
322
  output_type_registry: Mapping[str, type[graphene.ObjectType]],
291
323
  measurement_type: type[graphene.ObjectType],
292
324
  scalar_mapper: Callable[[type], type],
325
+ is_identifier: bool = False,
293
326
  ) -> _MappedAnnotation:
294
327
  nullable, concrete = _unwrap_optional_annotation(
295
328
  annotation,
@@ -306,6 +339,7 @@ def _map_annotation(
306
339
  output_type_registry=output_type_registry,
307
340
  measurement_type=measurement_type,
308
341
  scalar_mapper=scalar_mapper,
342
+ is_identifier=is_identifier,
309
343
  )
310
344
  return replace(mapped, nullable=nullable)
311
345
 
@@ -322,6 +356,7 @@ def _map_non_optional_annotation(
322
356
  measurement_type: type[graphene.ObjectType],
323
357
  scalar_mapper: Callable[[type], type],
324
358
  required: bool,
359
+ is_identifier: bool = False,
325
360
  ) -> MappedGraphQLOutput:
326
361
  """Map one non-optional annotation to a Graphene field."""
327
362
  mapped = _map_non_optional_value(
@@ -334,6 +369,7 @@ def _map_non_optional_annotation(
334
369
  output_type_registry=output_type_registry,
335
370
  measurement_type=measurement_type,
336
371
  scalar_mapper=scalar_mapper,
372
+ is_identifier=is_identifier,
337
373
  )
338
374
  field_kwargs: dict[str, object] = {}
339
375
  if mapped.contains_measurement:
@@ -355,8 +391,14 @@ def map_graphql_output_annotation(
355
391
  output_type_registry: Mapping[str, type[graphene.ObjectType]],
356
392
  measurement_type: type[graphene.ObjectType],
357
393
  scalar_mapper: Callable[[type], type],
394
+ is_identifier: bool = False,
358
395
  ) -> MappedGraphQLOutput:
359
- """Map a strict GraphQL output annotation to a mounted Graphene field."""
396
+ """Map a strict output hint, preserving nullability and native values.
397
+
398
+ Explicit identity fields accept int, str, UUID, and supported flat
399
+ collections of those types. Their resolver type stays native while the
400
+ generated scalar is ID. Unmarked fields retain the strict legacy mapping.
401
+ """
360
402
  nullable, concrete_type = _unwrap_optional_annotation(
361
403
  annotation,
362
404
  owner_name=owner_name,
@@ -374,6 +416,7 @@ def map_graphql_output_annotation(
374
416
  measurement_type=measurement_type,
375
417
  scalar_mapper=scalar_mapper,
376
418
  required=not nullable,
419
+ is_identifier=is_identifier,
377
420
  )
378
421
  except GraphQLOutputAnnotationError as error:
379
422
  # Preserve the annotation written on the owning field in diagnostics,
@@ -41,6 +41,7 @@ from general_manager.measurement.measurement import Measurement
41
41
  from general_manager.utils.type_checks import safe_issubclass
42
42
  from general_manager.search.backend_registry import get_search_backend
43
43
  from general_manager.search.backend import SearchHit
44
+ from general_manager.search.identity import SearchFilters, build_search_filters
44
45
  from general_manager.search.registry import (
45
46
  get_search_config,
46
47
  get_type_label,
@@ -1257,7 +1258,7 @@ def register_search_query(
1257
1258
  permission_plan,
1258
1259
  backend_shape=backend_shape,
1259
1260
  )
1260
- filter_groups = (
1261
+ filter_groups: SearchFilters = (
1261
1262
  manager_filters or None
1262
1263
  if decision == "allow_all"
1263
1264
  else merge_permission_filters(
@@ -1265,6 +1266,9 @@ def register_search_query(
1265
1266
  permission_plan.filters,
1266
1267
  )
1267
1268
  )
1269
+ filter_groups = build_search_filters(
1270
+ manager_class, index_name, filter_groups
1271
+ )
1268
1272
  total_hits_for_manager = 0
1269
1273
  candidate_hits_for_manager = 0
1270
1274
  offset_cursor = 0
@@ -29,7 +29,14 @@ class GraphQLTypeMeta(type):
29
29
 
30
30
 
31
31
  class GraphQLType(metaclass=GraphQLTypeMeta):
32
- """Frozen annotated value exposed only as a GraphQL output object."""
32
+ """Frozen annotated value exposed only as a GraphQL output object.
33
+
34
+ Use ``dataclasses.field(metadata={"is_identifier": True})`` to declare
35
+ native int, str, or UUID identity fields and their supported homogeneous
36
+ collections. Schema generation preserves annotation nullability and native
37
+ values while exposing ID scalars. Missing or false metadata keeps existing
38
+ output types; other flag values fail schema generation with TypeError.
39
+ """
33
40
 
34
41
 
35
42
  def get_registered_graphql_types() -> tuple[type[GraphQLType], ...]:
@@ -9,9 +9,8 @@ from django.core.management.base import BaseCommand
9
9
 
10
10
  from general_manager.logging import get_logger
11
11
  from general_manager.search.backend_registry import get_search_backend
12
- from general_manager.search.indexer import SearchIndexer
12
+ from general_manager.search.indexer import SearchIndexer, _ensure_index
13
13
  from general_manager.search.registry import (
14
- collect_index_settings,
15
14
  get_index_names,
16
15
  iter_searchable_managers,
17
16
  )
@@ -99,16 +98,7 @@ class Command(BaseCommand):
99
98
  target_indexes = get_index_names()
100
99
 
101
100
  for index_name in sorted(target_indexes):
102
- settings_payload = collect_index_settings(index_name)
103
- backend.ensure_index(
104
- index_name,
105
- {
106
- "searchable_fields": settings_payload.searchable_fields,
107
- "filterable_fields": settings_payload.filterable_fields,
108
- "sortable_fields": settings_payload.sortable_fields,
109
- "field_boosts": settings_payload.field_boosts,
110
- },
111
- )
101
+ _ensure_index(backend, index_name)
112
102
  logger.info(
113
103
  "search index ensured",
114
104
  context={"index": index_name},
@@ -793,6 +793,11 @@ RULE_EXPORTS: LazyExportMap = {
793
793
  }
794
794
 
795
795
  SEARCH_EXPORTS: LazyExportMap = {
796
+ "SearchIdentityFilterGroup": (
797
+ "general_manager.search.identity",
798
+ "SearchIdentityFilterGroup",
799
+ ),
800
+ "build_search_filters": ("general_manager.search.identity", "build_search_filters"),
796
801
  "FieldConfig": ("general_manager.search.config", "FieldConfig"),
797
802
  "IndexConfig": ("general_manager.search.config", "IndexConfig"),
798
803
  "SearchConfigProtocol": ("general_manager.search.config", "SearchConfigProtocol"),
@@ -2,8 +2,9 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import builtins
5
6
  from collections.abc import Mapping, Sequence
6
- from dataclasses import dataclass
7
+ from dataclasses import dataclass, field
7
8
  from typing import Protocol, runtime_checkable
8
9
 
9
10
 
@@ -20,7 +21,10 @@ class SearchDocument:
20
21
  protocol does not require adapters to reject mismatches between
21
22
  `document.index` and an `index_name` argument. `data` contains
22
23
  searchable/stored fields. `field_boosts` and `index_boost` are hints for
23
- adapters that support weighted matching. The payload mappings, including
24
+ adapters that support weighted matching. `identity_fields` maps explicit
25
+ identity names to native scalar types (`int`, `str`, or `UUID`), including
26
+ nullable/collection element types. It never coerces document values.
27
+ The payload mappings, including
24
28
  `identification`, are not copied by the model; callers should treat them as
25
29
  immutable after handing them to a backend. Dataclass field annotations are
26
30
  the validation boundary; this model does not coerce or validate runtime
@@ -36,6 +40,7 @@ class SearchDocument:
36
40
  data: Mapping[str, object]
37
41
  field_boosts: Mapping[str, float]
38
42
  index_boost: float | None = None
43
+ identity_fields: Mapping[str, builtins.type] = field(default_factory=dict)
39
44
 
40
45
 
41
46
  @dataclass(frozen=True)
@@ -10,6 +10,11 @@ from threading import RLock
10
10
  from general_manager.search.backend import SearchDocument, SearchHit, SearchResult
11
11
  from general_manager.bucket._ordering import normalize_ordering, sort_items
12
12
  from general_manager.utils.filter_parser import apply_lookup
13
+ from general_manager.search.identity import (
14
+ SearchIdentityFilterGroup,
15
+ identity_lookup,
16
+ canonical_identity,
17
+ )
13
18
 
14
19
 
15
20
  @dataclass
@@ -176,6 +181,10 @@ class DevSearchBackend:
176
181
  case-sensitive, missing fields behave like `None`, incompatible
177
182
  mixed-type comparisons and invalid lookup/value combinations
178
183
  return `False`, and `None` compares only through `exact`.
184
+ Explicit `SearchIdentityFilterGroup` equality/membership uses
185
+ native casts and owner scope without changing these operator
186
+ rules. Matching document metadata and a present field are
187
+ required. Plain mappings retain raw comparisons.
179
188
  filter_expression (str | None): Unsupported in this backend; passing a value raises NotImplementedError.
180
189
  sort (Sequence[str] | None): Signed document data field names.
181
190
  Prefix a field with ``-`` for descending order. If omitted,
@@ -392,12 +401,38 @@ class DevSearchBackend:
392
401
  if not all(isinstance(group, Mapping) for group in filters):
393
402
  return False
394
403
  return any(self._passes_filters(document, group) for group in filters)
404
+ if isinstance(filters, SearchIdentityFilterGroup):
405
+ if filters.type_label is not None and document.type != filters.type_label:
406
+ return False
395
407
  for key, value in filters.items():
396
- if "__" in key:
408
+ identity = None
409
+ if isinstance(filters, SearchIdentityFilterGroup):
410
+ identity = identity_lookup(key, filters.identity_fields)
411
+ if identity is not None:
412
+ field_name, lookup, native_type = identity
413
+ if (
414
+ field_name not in document.data
415
+ or document.identity_fields.get(field_name) is not native_type
416
+ ):
417
+ return False
418
+ elif "__" in key:
397
419
  field_name, lookup = key.split("__", 1)
398
420
  else:
399
421
  field_name, lookup = key, "exact"
400
422
  doc_value = document.data.get(field_name)
423
+ if identity is not None and (
424
+ lookup != "in" or isinstance(value, (list, tuple, set))
425
+ ):
426
+ doc_value = (
427
+ [canonical_identity(native_type, item) for item in doc_value]
428
+ if isinstance(doc_value, (list, tuple, set))
429
+ else canonical_identity(native_type, doc_value)
430
+ )
431
+ value = (
432
+ [canonical_identity(native_type, item) for item in value]
433
+ if isinstance(value, (list, tuple, set))
434
+ else canonical_identity(native_type, value)
435
+ )
401
436
  if lookup == "exact" and isinstance(value, (list, tuple, set)):
402
437
  if isinstance(doc_value, (list, tuple, set)):
403
438
  if not set(doc_value).intersection(value):
@@ -8,6 +8,7 @@ from collections.abc import Callable, Iterable
8
8
  from importlib import import_module
9
9
  from inspect import signature
10
10
  from typing import Mapping, Protocol, Sequence, cast
11
+ from uuid import UUID
11
12
 
12
13
  from general_manager.search.backend import (
13
14
  SearchBackendClientMissingError,
@@ -17,6 +18,14 @@ from general_manager.search.backend import (
17
18
  SearchResult,
18
19
  )
19
20
  from general_manager.bucket._ordering import normalize_ordering
21
+ from general_manager.search.identity import (
22
+ SearchIdentityFilterGroup,
23
+ bind_search_filters,
24
+ identity_field_key,
25
+ identity_token,
26
+ meilisearch_identity_filters,
27
+ SearchIdentityConfigurationError,
28
+ )
20
29
 
21
30
 
22
31
  def _load_meilisearch_api_error() -> type[Exception] | None:
@@ -155,6 +164,9 @@ class MeilisearchBackend:
155
164
  - "searchable_fields": iterable of field names to set as searchableAttributes.
156
165
  - "filterable_fields": iterable of field names to set as filterableAttributes.
157
166
  - "sortable_fields": iterable of field names to set as sortableAttributes.
167
+ - "identity_fields": contracts keyed by document type; each
168
+ maps identity names to int/str/UUID. Shadow filterability is
169
+ added only for names listed in "filterable_fields".
158
170
 
159
171
  Non-iterable setting values and strings/bytes are ignored; iterable
160
172
  values such as lists, tuples, and sets are converted to strings. This
@@ -169,6 +181,29 @@ class MeilisearchBackend:
169
181
  index = self._get_or_create_index(index_name)
170
182
  searchable_fields = self._string_sequence_setting(settings, "searchable_fields")
171
183
  filterable_fields = self._string_sequence_setting(settings, "filterable_fields")
184
+ contracts = settings.get("identity_fields", {})
185
+ if not isinstance(contracts, Mapping):
186
+ raise SearchIdentityConfigurationError(
187
+ "identity_fields", "expected a mapping of type contracts"
188
+ )
189
+ identity_names: set[str] = set()
190
+ for owner, contract in contracts.items():
191
+ if not isinstance(contract, Mapping):
192
+ raise SearchIdentityConfigurationError(
193
+ str(owner), "expected a native field mapping"
194
+ )
195
+ validated = SearchIdentityFilterGroup({}, identity_fields=contract)
196
+ identity_names.update(validated.identity_fields)
197
+ if filterable_fields is not None:
198
+ shadow_fields = {
199
+ "gm_identity." + identity_field_key(name)
200
+ for name in identity_names
201
+ if name in filterable_fields
202
+ }
203
+ filterable_fields = [
204
+ *filterable_fields,
205
+ *sorted(shadow_fields - set(filterable_fields)),
206
+ ]
172
207
  sortable_fields = self._string_sequence_setting(settings, "sortable_fields")
173
208
  ranking_rules = self._ranking_rules_with_sort_first(index, settings)
174
209
  task = index.update_settings({"rankingRules": ranking_rules})
@@ -322,7 +357,13 @@ class MeilisearchBackend:
322
357
  with structured filters. String rendering uses ``str(value)`` and
323
358
  escapes backslashes and double quotes; this also applies to numbers,
324
359
  booleans, and ``None``. Empty `in` lists produce an empty
325
- parenthesized clause. ``sort`` is normalized as signed field names
360
+ parenthesized clause. Declared identity equality/membership uses
361
+ separate versioned tokens without changing source values. Plain
362
+ structured filters inherit registered manager/index contracts;
363
+ `SearchIdentityFilterGroup` supports unregistered documents.
364
+ Old documents without tokens require reindexing; raw
365
+ `filter_expression` bypasses identity transport.
366
+ ``sort`` is normalized as signed field names
326
367
  and forwarded as ordered Meilisearch ``field:direction`` entries.
327
368
  A sorted query reads the index settings and raises
328
369
  ``MeilisearchOrderingConfigurationError`` unless ``sort`` has the
@@ -342,7 +383,9 @@ class MeilisearchBackend:
342
383
  filter_expr = (
343
384
  filter_expression
344
385
  if filter_expression is not None
345
- else self._build_filter_expression(filters, types)
386
+ else self._build_filter_expression(
387
+ bind_search_filters(index_name, filters, types), types
388
+ )
346
389
  )
347
390
  if filter_expr:
348
391
  payload["filter"] = filter_expr
@@ -447,22 +490,48 @@ class MeilisearchBackend:
447
490
  - `data`: the original data mapping,
448
491
  - additional top-level keys copied from `document.data` except
449
492
  reserved keys (`id`, `gm_document_id`, `type`,
450
- `identification`, `data`).
493
+ `identification`, `data`, `gm_identity`).
494
+ - `gm_identity`: bounded equality tokens for declared present
495
+ identity fields. UUID/set JSON conversion affects only the
496
+ payload copy, never the source document.
451
497
  """
452
- reserved_keys = {"id", "gm_document_id", "type", "identification", "data"}
498
+ reserved_keys = {
499
+ "id",
500
+ "gm_document_id",
501
+ "type",
502
+ "identification",
503
+ "data",
504
+ "gm_identity",
505
+ }
453
506
  extra_data = {
454
507
  key: value
455
508
  for key, value in document.data.items()
456
509
  if key not in reserved_keys
457
510
  }
458
- return {
459
- "id": MeilisearchBackend._normalize_document_id(document.id),
460
- "gm_document_id": document.id,
461
- "type": document.type,
462
- "identification": document.identification,
463
- "data": document.data,
464
- **extra_data,
465
- }
511
+ identities: dict[str, object] = {}
512
+ for name, native_type in document.identity_fields.items():
513
+ if name not in document.data:
514
+ continue
515
+ value = document.data[name]
516
+ identities[identity_field_key(name)] = (
517
+ [identity_token(native_type, item) for item in value]
518
+ if isinstance(value, (list, tuple, set))
519
+ else identity_token(native_type, value)
520
+ )
521
+ return cast(
522
+ dict[str, object],
523
+ _json_search_value(
524
+ {
525
+ "id": MeilisearchBackend._normalize_document_id(document.id),
526
+ "gm_document_id": document.id,
527
+ "type": document.type,
528
+ "identification": document.identification,
529
+ "data": document.data,
530
+ **extra_data,
531
+ "gm_identity": identities,
532
+ }
533
+ ),
534
+ )
466
535
 
467
536
  @staticmethod
468
537
  def _build_filter_expression(
@@ -485,6 +554,9 @@ class MeilisearchBackend:
485
554
  fields in one mapping are combined with AND; multiple mappings
486
555
  are combined with OR. Empty `in` lists produce the exact clause
487
556
  ``()``.
557
+ Explicit identity groups instead target versioned `gm_identity`
558
+ fields. Null has its own token; empty identity `in` operands
559
+ produce an always-false clause.
488
560
  types (Sequence[str] | None):
489
561
  Sequence of type names to restrict results to; these are combined with OR against the `type` field.
490
562
 
@@ -502,12 +574,22 @@ class MeilisearchBackend:
502
574
  group_clauses: list[str] = []
503
575
  for group in filter_groups:
504
576
  parts: list[str] = []
505
- for key, value in group.items():
577
+ if (
578
+ isinstance(group, SearchIdentityFilterGroup)
579
+ and group.type_label is not None
580
+ ):
581
+ parts.append(f'type = "{_escape_filter_value(group.type_label)}"')
582
+ for key, value in meilisearch_identity_filters(group):
506
583
  if "__" in key:
507
584
  field_name, lookup = key.split("__", 1)
508
585
  else:
509
586
  field_name, lookup = key, "exact"
510
587
  if lookup == "in" and isinstance(value, (list, tuple, set)):
588
+ if field_name.startswith("gm_identity.") and not value:
589
+ parts.append(
590
+ f"({field_name} EXISTS AND {field_name} NOT EXISTS)"
591
+ )
592
+ continue
511
593
  options = " OR ".join(
512
594
  [
513
595
  f'{field_name} = "{_escape_filter_value(item)}"'
@@ -808,6 +890,17 @@ def _is_meilisearch_already_exists(error: Exception) -> bool:
808
890
  return status == 409 or "already_exists" in code
809
891
 
810
892
 
893
+ def _json_search_value(value: object) -> object:
894
+ """Copy native document values into JSON-compatible provider payloads."""
895
+ if isinstance(value, UUID):
896
+ return str(value)
897
+ if isinstance(value, Mapping):
898
+ return {key: _json_search_value(item) for key, item in value.items()}
899
+ if isinstance(value, (list, tuple, set)):
900
+ return [_json_search_value(item) for item in value]
901
+ return value
902
+
903
+
811
904
  def _escape_filter_value(value: object) -> str:
812
905
  """
813
906
  Escape a value for inclusion in a Meilisearch filter expression.
@@ -5,12 +5,13 @@ from __future__ import annotations
5
5
  from collections.abc import Callable, Iterable, Mapping, Sequence
6
6
  from dataclasses import dataclass, field
7
7
  from typing import Literal, Protocol, cast
8
+ from uuid import UUID
8
9
 
9
10
  from general_manager.manager.general_manager import GeneralManager
10
11
 
11
12
 
12
13
  _RESERVED_DOCUMENT_FIELD_NAMES = frozenset(
13
- {"id", "gm_document_id", "type", "identification", "data"}
14
+ {"id", "gm_document_id", "type", "identification", "data", "gm_identity"}
14
15
  )
15
16
 
16
17
 
@@ -110,6 +111,10 @@ class IndexConfig:
110
111
  sorts: Field names allowed for backend sorting.
111
112
  boost: Optional positive index-level boost.
112
113
  min_score: Optional non-negative minimum relevance score.
114
+ identity_fields: Native scalar kinds (`int`, `str`, `UUID`) for configured
115
+ document aliases, including nullable/collection element types.
116
+ Manager identity metadata is inherited automatically; conflicting
117
+ overrides fail when the index contract is resolved.
113
118
 
114
119
  Raises:
115
120
  InvalidIndexBoostError: If `boost` is not `None` and is less than or
@@ -126,6 +131,7 @@ class IndexConfig:
126
131
  sorts: Sequence[str] = field(default_factory=tuple)
127
132
  boost: float | None = None
128
133
  min_score: float | None = None
134
+ identity_fields: Mapping[str, type] = field(default_factory=dict)
129
135
 
130
136
  def __post_init__(self) -> None:
131
137
  """Validate index-level boost and minimum score after initialization."""
@@ -143,6 +149,25 @@ class IndexConfig:
143
149
  for field_name in (*self.filters, *self.sorts):
144
150
  if field_name in _RESERVED_DOCUMENT_FIELD_NAMES:
145
151
  raise ReservedDocumentFieldNameError(field_name)
152
+ from general_manager.search.identity import SearchIdentityConfigurationError
153
+
154
+ serialized_fields = {
155
+ *(
156
+ entry.name if isinstance(entry, FieldConfig) else entry
157
+ for entry in self.fields
158
+ ),
159
+ *self.filters,
160
+ *self.sorts,
161
+ }
162
+ for field_name, native_type in self.identity_fields.items():
163
+ if field_name not in serialized_fields:
164
+ raise SearchIdentityConfigurationError(
165
+ field_name, "field is not configured"
166
+ )
167
+ if native_type not in (int, str, UUID):
168
+ raise SearchIdentityConfigurationError(
169
+ field_name, "expected int, str or UUID"
170
+ )
146
171
  if self.boost is not None and self.boost <= 0:
147
172
  raise InvalidIndexBoostError
148
173
  if self.min_score is not None and self.min_score < 0: