GeneralManager 0.63.2__tar.gz → 0.64.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {generalmanager-0.63.2/src/GeneralManager.egg-info → generalmanager-0.64.1}/PKG-INFO +1 -1
- {generalmanager-0.63.2 → generalmanager-0.64.1}/pyproject.toml +1 -1
- {generalmanager-0.63.2 → generalmanager-0.64.1/src/GeneralManager.egg-info}/PKG-INFO +1 -1
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/GeneralManager.egg-info/SOURCES.txt +2 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/_types/api.py +2 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/api/graphql.py +256 -79
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/api/graphql_mutations.py +47 -10
- generalmanager-0.64.1/src/general_manager/api/graphql_relations.py +72 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/api/graphql_resolvers.py +10 -3
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/api/graphql_search.py +34 -12
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/api/graphql_subscriptions.py +50 -0
- generalmanager-0.64.1/src/general_manager/api/notification_batching.py +121 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/api/remote_invalidation.py +51 -16
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/bootstrap.py +8 -1
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/cache/dependency_index.py +1 -1
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/migrations/0007_upload_intent.py +5 -5
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/public_api_registry.py +4 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/search/backends/meilisearch.py +1 -1
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/uploads/finalization.py +4 -4
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/uploads/models.py +5 -5
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/utils/filter_parser.py +1 -1
- {generalmanager-0.63.2 → generalmanager-0.64.1}/LICENSE +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/README.md +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/setup.cfg +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/GeneralManager.egg-info/dependency_links.txt +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/GeneralManager.egg-info/requires.txt +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/GeneralManager.egg-info/top_level.txt +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/_types/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/_types/bucket.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/_types/cache.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/_types/dataframes.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/_types/factory.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/_types/general_manager.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/_types/interface.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/_types/manager.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/_types/measurement.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/_types/permission.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/_types/rule.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/_types/search.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/_types/utils.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/api/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/api/graphql_errors.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/api/graphql_prefetch.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/api/graphql_subscription_consumer.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/api/graphql_view.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/api/graphql_warmup.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/api/graphql_warmup_registry.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/api/graphql_warmup_tasks.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/api/mutation.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/api/property.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/api/registry.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/api/remote_api.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/api/remote_invalidation_client.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/apps.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/bucket/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/bucket/base_bucket.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/bucket/calculation_bucket.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/bucket/database_bucket.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/bucket/group_bucket.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/bucket/indexing.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/bucket/request_bucket.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/cache/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/cache/cache_decorator.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/cache/cache_tracker.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/cache/dependency_cache.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/cache/dependency_matching.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/cache/dependency_publish.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/cache/dependency_shards.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/cache/model_dependency_collector.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/cache/run_context.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/cache/signals.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/audit.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/bootstrap.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/checks.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/consumer.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/errors.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/evals/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/evals/__main__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/evals/baseline.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/evals/datasets/basic_queries.yaml +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/evals/datasets/demo_readiness.yaml +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/evals/datasets/edge_cases.yaml +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/evals/datasets/follow_ups.yaml +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/evals/datasets/large_schema.yaml +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/evals/datasets/multi_hop.yaml +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/evals/diagnostics.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/evals/fingerprints.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/evals/fixtures.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/evals/judges/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/evals/judges/answer_quality.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/evals/judges/contract.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/evals/judges/result_accuracy.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/evals/judges/tool_sequence.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/evals/readiness.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/evals/runner.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/evals/traces.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/grounding.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/models.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/providers/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/providers/_shared.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/providers/anthropic.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/providers/base.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/providers/google.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/providers/ollama.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/providers/openai.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/rate_limits.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/routing.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/schema_index.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/settings.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/signals.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/system_prompt.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/tool_metadata.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/tools.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/chat/views.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/conf.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/dataframes/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/dataframes/measurements.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/factory/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/factory/auto_factory.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/factory/factories.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/factory/factory_methods.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/base_interface.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/bundles/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/bundles/calculation.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/bundles/database.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/bundles/remote_manager.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/bundles/request.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/base.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/builtin.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/calculation/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/calculation/_compat.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/calculation/lifecycle.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/configuration.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/core/observability.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/core/utils.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/exceptions.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/existing_model/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/existing_model/_compat.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/existing_model/resolution.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/factory.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/orm/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/orm/_compat.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/orm/history.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/orm/lifecycle.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/orm/mutations.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/orm/support.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/orm_utils/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/orm_utils/django_manager_utils.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/orm_utils/field_descriptors.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/orm_utils/payload_normalizer.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/read_only/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/read_only/_compat.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/read_only/_types.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/read_only/lifecycle.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/read_only/management.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/registry.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/remote_manager.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/capabilities/request/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/infrastructure/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/infrastructure/startup_hooks.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/infrastructure/system_checks.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/interfaces/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/interfaces/calculation.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/interfaces/database.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/interfaces/existing_model.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/interfaces/read_only.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/interfaces/remote_manager.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/interfaces/request.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/manifests/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/manifests/capability_builder.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/manifests/capability_manifest.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/manifests/capability_models.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/orm_interface.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/requests.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/utils/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/utils/database_interface_protocols.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/utils/errors.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/utils/history.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/interface/utils/models.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/logging.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/management/commands/chat_cleanup.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/management/commands/cleanup_upload_intents.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/management/commands/graphql_warmup.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/management/commands/graphql_warmup_refresh_due.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/management/commands/search_index.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/management/commands/search_reconcile.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/management/commands/seed_manager_landscape.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/management/commands/shell.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/management/commands/workflow_drain_outbox.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/management/commands/workflow_replay_dead_letters.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/manager/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/manager/general_manager.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/manager/group_manager.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/manager/input.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/manager/meta.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/measurement/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/measurement/measurement.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/measurement/measurement_field.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/metrics/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/metrics/graphql.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/migrations/0001_initial.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/migrations/0002_workflow_outbox_scaling_indexes.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/migrations/0003_workflow_execution_correlation_constraint.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/migrations/0004_chat_persistence_models.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/migrations/0004_search_index_state.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/migrations/0005_merge_chat_search.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/migrations/0006_chat_pending_confirmation_scoped_ids.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/migrations/0008_upload_finalization_versions.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/migrations/0009_upload_cleanup_state.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/migrations/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/models.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/permission/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/permission/audit.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/permission/base_permission.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/permission/graphql_capabilities.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/permission/manager_based_permission.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/permission/mutation_permission.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/permission/permission_checks.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/permission/permission_data_manager.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/permission/utils.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/py.typed +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/rule/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/rule/handler.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/rule/rule.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/search/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/search/async_tasks.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/search/backend.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/search/backend_registry.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/search/backends/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/search/backends/dev.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/search/backends/opensearch.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/search/backends/typesense.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/search/config.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/search/indexer.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/search/models.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/search/reconciliation.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/search/registry.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/search/tasks.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/search/utils.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/seeding/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/seeding/manager_landscape.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/uploads/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/uploads/adapters.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/uploads/checks.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/uploads/config.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/uploads/errors.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/uploads/graphql.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/uploads/graphql_types.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/uploads/metrics.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/uploads/public.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/uploads/s3.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/uploads/services.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/uploads/tokens.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/uploads/types.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/uploads/urls.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/uploads/views.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/utils/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/utils/args_to_kwargs.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/utils/format_string.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/utils/json_encoder.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/utils/make_cache_key.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/utils/none_to_zero.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/utils/path_mapping.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/utils/public_api.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/utils/testing.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/utils/type_checks.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/workflow/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/workflow/actions.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/workflow/backend_registry.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/workflow/backends/__init__.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/workflow/backends/celery.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/workflow/backends/local.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/workflow/backends/n8n.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/workflow/config.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/workflow/engine.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/workflow/event_registry.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/workflow/events.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/workflow/models.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/workflow/signal_bridge.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/workflow/tasks.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/src/general_manager/workflow/telemetry.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/tests/test_settings.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/tests/test_urls.py +0 -0
- {generalmanager-0.63.2 → generalmanager-0.64.1}/tests/testing_asgi.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GeneralManager
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.64.1
|
|
4
4
|
Summary: Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching.
|
|
5
5
|
Author-email: Tim Kleindick <tkleindick@yahoo.de>
|
|
6
6
|
License: MIT License
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "GeneralManager"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.64.1"
|
|
8
8
|
description = "Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{ name = "Tim Kleindick", email = "tkleindick@yahoo.de" }]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GeneralManager
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.64.1
|
|
4
4
|
Summary: Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching.
|
|
5
5
|
Author-email: Tim Kleindick <tkleindick@yahoo.de>
|
|
6
6
|
License: MIT License
|
|
@@ -33,6 +33,7 @@ src/general_manager/api/graphql.py
|
|
|
33
33
|
src/general_manager/api/graphql_errors.py
|
|
34
34
|
src/general_manager/api/graphql_mutations.py
|
|
35
35
|
src/general_manager/api/graphql_prefetch.py
|
|
36
|
+
src/general_manager/api/graphql_relations.py
|
|
36
37
|
src/general_manager/api/graphql_resolvers.py
|
|
37
38
|
src/general_manager/api/graphql_search.py
|
|
38
39
|
src/general_manager/api/graphql_subscription_consumer.py
|
|
@@ -42,6 +43,7 @@ src/general_manager/api/graphql_warmup.py
|
|
|
42
43
|
src/general_manager/api/graphql_warmup_registry.py
|
|
43
44
|
src/general_manager/api/graphql_warmup_tasks.py
|
|
44
45
|
src/general_manager/api/mutation.py
|
|
46
|
+
src/general_manager/api/notification_batching.py
|
|
45
47
|
src/general_manager/api/property.py
|
|
46
48
|
src/general_manager/api/registry.py
|
|
47
49
|
src/general_manager/api/remote_api.py
|
|
@@ -56,6 +56,7 @@ __all__ = [
|
|
|
56
56
|
"UploadTokenInvalidError",
|
|
57
57
|
"UploadTransferConflictError",
|
|
58
58
|
"UploadTransport",
|
|
59
|
+
"bulk_data_change_notifications",
|
|
59
60
|
"graph_ql_mutation",
|
|
60
61
|
"graph_ql_property",
|
|
61
62
|
"register_upload_adapter",
|
|
@@ -115,5 +116,6 @@ from general_manager.uploads.errors import UploadTokenInvalidError
|
|
|
115
116
|
from general_manager.uploads.errors import UploadTransferConflictError
|
|
116
117
|
from general_manager.uploads.types import UploadTransport
|
|
117
118
|
from general_manager.api.mutation import graph_ql_mutation
|
|
119
|
+
from general_manager.api.notification_batching import bulk_data_change_notifications
|
|
118
120
|
from general_manager.api.property import graph_ql_property
|
|
119
121
|
from general_manager.uploads.public import register_upload_adapter
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import asyncio
|
|
6
|
-
from contextlib import
|
|
6
|
+
from contextlib import asynccontextmanager
|
|
7
7
|
from copy import deepcopy
|
|
8
8
|
import re
|
|
9
9
|
from types import UnionType
|
|
@@ -101,6 +101,7 @@ from general_manager.api.graphql_resolvers import (
|
|
|
101
101
|
create_list_resolver as _create_list_resolver_fn,
|
|
102
102
|
create_resolver as _create_resolver_fn,
|
|
103
103
|
)
|
|
104
|
+
from general_manager.api.graphql_relations import resolve_general_manager_type
|
|
104
105
|
from general_manager.api.graphql_search import (
|
|
105
106
|
register_search_query as _register_search_query_fn,
|
|
106
107
|
create_search_union as _create_search_union_fn,
|
|
@@ -113,10 +114,13 @@ from general_manager.api.graphql_search import (
|
|
|
113
114
|
create_filter_options as _create_filter_options_fn,
|
|
114
115
|
normalize_filter_input as _normalize_filter_input_fn,
|
|
115
116
|
)
|
|
117
|
+
from general_manager.api.notification_batching import _queue_notification
|
|
116
118
|
from general_manager.api.graphql_subscriptions import (
|
|
117
119
|
get_channel_layer_safe as _get_channel_layer_fn,
|
|
118
120
|
group_name as _group_name_fn,
|
|
119
121
|
class_group_name as _class_group_name_fn,
|
|
122
|
+
refresh_group_name as _refresh_group_name_fn,
|
|
123
|
+
dispatch_subscription_event as _dispatch_subscription_event_fn,
|
|
120
124
|
channel_listener as _channel_listener_fn,
|
|
121
125
|
channel_message_listener as _channel_message_listener_fn,
|
|
122
126
|
prime_graphql_properties as _prime_graphql_properties_fn,
|
|
@@ -155,6 +159,101 @@ GraphQLFilterNormalizer = Callable[
|
|
|
155
159
|
dict[str, GraphQLFilterMapping],
|
|
156
160
|
]
|
|
157
161
|
GraphQLMutationMap = dict[str, type[graphene.Mutation]]
|
|
162
|
+
_SUBSCRIPTION_CLEANUP_FAILURE_MESSAGE = "subscription cleanup failed"
|
|
163
|
+
_SUBSCRIPTION_ROLLBACK_FAILURE_MESSAGE = "subscription setup and rollback failed"
|
|
164
|
+
_SUBSCRIPTION_STREAM_CLEANUP_FAILURE_MESSAGE = "subscription stream and cleanup failed"
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
async def _cleanup_subscription_resources(
|
|
168
|
+
channel_layer: BaseChannelLayer,
|
|
169
|
+
channel_name: str,
|
|
170
|
+
joined_groups: Iterable[str],
|
|
171
|
+
listener_task: asyncio.Task[None] | None = None,
|
|
172
|
+
) -> None:
|
|
173
|
+
"""Stop a listener and attempt to discard every successfully joined group."""
|
|
174
|
+
cleanup_errors: list[BaseException] = []
|
|
175
|
+
if listener_task is not None:
|
|
176
|
+
listener_task.cancel()
|
|
177
|
+
try:
|
|
178
|
+
await listener_task
|
|
179
|
+
except asyncio.CancelledError:
|
|
180
|
+
pass
|
|
181
|
+
except BaseException as exc: # noqa: BLE001
|
|
182
|
+
cleanup_errors.append(exc)
|
|
183
|
+
|
|
184
|
+
for group in joined_groups:
|
|
185
|
+
try:
|
|
186
|
+
await channel_layer.group_discard(group, channel_name)
|
|
187
|
+
except BaseException as exc: # noqa: BLE001
|
|
188
|
+
cleanup_errors.append(exc)
|
|
189
|
+
|
|
190
|
+
if len(cleanup_errors) == 1:
|
|
191
|
+
raise cleanup_errors[0]
|
|
192
|
+
if cleanup_errors:
|
|
193
|
+
raise BaseExceptionGroup(
|
|
194
|
+
_SUBSCRIPTION_CLEANUP_FAILURE_MESSAGE,
|
|
195
|
+
cleanup_errors,
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
async def _join_subscription_groups(
|
|
200
|
+
channel_layer: BaseChannelLayer,
|
|
201
|
+
channel_name: str,
|
|
202
|
+
group_names: Iterable[str],
|
|
203
|
+
) -> list[str]:
|
|
204
|
+
"""Join groups and roll back every successful join if a later join fails."""
|
|
205
|
+
joined_groups: list[str] = []
|
|
206
|
+
try:
|
|
207
|
+
for group in group_names:
|
|
208
|
+
await channel_layer.group_add(group, channel_name)
|
|
209
|
+
joined_groups.append(group)
|
|
210
|
+
except BaseException as setup_error:
|
|
211
|
+
try:
|
|
212
|
+
await _cleanup_subscription_resources(
|
|
213
|
+
channel_layer,
|
|
214
|
+
channel_name,
|
|
215
|
+
joined_groups,
|
|
216
|
+
)
|
|
217
|
+
except BaseException as cleanup_error: # noqa: BLE001
|
|
218
|
+
raise BaseExceptionGroup(
|
|
219
|
+
_SUBSCRIPTION_ROLLBACK_FAILURE_MESSAGE,
|
|
220
|
+
[setup_error, cleanup_error],
|
|
221
|
+
) from None
|
|
222
|
+
raise
|
|
223
|
+
return joined_groups
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
@asynccontextmanager
|
|
227
|
+
async def _subscription_cleanup_scope(
|
|
228
|
+
channel_layer: BaseChannelLayer,
|
|
229
|
+
channel_name: str,
|
|
230
|
+
joined_groups: Iterable[str],
|
|
231
|
+
listener_task: asyncio.Task[None],
|
|
232
|
+
) -> AsyncIterator[None]:
|
|
233
|
+
"""Clean subscription resources without masking an active stream failure."""
|
|
234
|
+
try:
|
|
235
|
+
yield
|
|
236
|
+
except BaseException as stream_error:
|
|
237
|
+
try:
|
|
238
|
+
await _cleanup_subscription_resources(
|
|
239
|
+
channel_layer,
|
|
240
|
+
channel_name,
|
|
241
|
+
joined_groups,
|
|
242
|
+
listener_task,
|
|
243
|
+
)
|
|
244
|
+
except BaseException as cleanup_error: # noqa: BLE001
|
|
245
|
+
raise BaseExceptionGroup(
|
|
246
|
+
_SUBSCRIPTION_STREAM_CLEANUP_FAILURE_MESSAGE,
|
|
247
|
+
[stream_error, cleanup_error],
|
|
248
|
+
) from None
|
|
249
|
+
raise
|
|
250
|
+
else:
|
|
251
|
+
await _cleanup_subscription_resources(
|
|
252
|
+
channel_layer,
|
|
253
|
+
channel_name,
|
|
254
|
+
joined_groups,
|
|
255
|
+
listener_task,
|
|
256
|
+
)
|
|
158
257
|
|
|
159
258
|
|
|
160
259
|
class GraphQL:
|
|
@@ -281,6 +380,15 @@ class GraphQL:
|
|
|
281
380
|
"""
|
|
282
381
|
return _class_group_name_fn(manager_class)
|
|
283
382
|
|
|
383
|
+
@staticmethod
|
|
384
|
+
def _refresh_group_name(manager_class: type[GeneralManager]) -> str:
|
|
385
|
+
"""
|
|
386
|
+
Compatibility wrapper for ``graphql_subscriptions.refresh_group_name(manager_class)``.
|
|
387
|
+
|
|
388
|
+
Returns the deterministic manager-wide refresh group name.
|
|
389
|
+
"""
|
|
390
|
+
return _refresh_group_name_fn(manager_class)
|
|
391
|
+
|
|
284
392
|
@staticmethod
|
|
285
393
|
async def _channel_listener(
|
|
286
394
|
channel_layer: BaseChannelLayer,
|
|
@@ -439,8 +547,13 @@ class GraphQL:
|
|
|
439
547
|
# Map Attribute Types to Graphene Fields
|
|
440
548
|
for field_name, field_info in interface_cls.get_attribute_types().items():
|
|
441
549
|
field_type = field_info["type"]
|
|
442
|
-
|
|
550
|
+
resolved_manager_type = resolve_general_manager_type(
|
|
443
551
|
field_type,
|
|
552
|
+
cls.manager_registry,
|
|
553
|
+
)
|
|
554
|
+
resolved_field_type = resolved_manager_type or field_type
|
|
555
|
+
fields[field_name] = cls._map_field_to_graphene_read(
|
|
556
|
+
resolved_field_type,
|
|
444
557
|
field_name,
|
|
445
558
|
field_info,
|
|
446
559
|
)
|
|
@@ -469,7 +582,10 @@ class GraphQL:
|
|
|
469
582
|
|
|
470
583
|
fields[resolver_name] = resolve_stored_file
|
|
471
584
|
else:
|
|
472
|
-
fields[resolver_name] = cls._create_resolver(
|
|
585
|
+
fields[resolver_name] = cls._create_resolver(
|
|
586
|
+
field_name,
|
|
587
|
+
resolved_field_type,
|
|
588
|
+
)
|
|
473
589
|
|
|
474
590
|
# handle GraphQLProperty attributes
|
|
475
591
|
for (
|
|
@@ -487,9 +603,13 @@ class GraphQL:
|
|
|
487
603
|
|
|
488
604
|
if origin in (list, tuple, set):
|
|
489
605
|
element = type_args[0] if type_args else object
|
|
490
|
-
|
|
606
|
+
manager_type = resolve_general_manager_type(
|
|
607
|
+
element,
|
|
608
|
+
cls.manager_registry,
|
|
609
|
+
)
|
|
610
|
+
if manager_type is not None:
|
|
491
611
|
graphene_field = graphene.List(
|
|
492
|
-
lambda elem=
|
|
612
|
+
lambda elem=manager_type: GraphQL.graphql_type_registry[
|
|
493
613
|
elem.__name__
|
|
494
614
|
]
|
|
495
615
|
)
|
|
@@ -498,13 +618,22 @@ class GraphQL:
|
|
|
498
618
|
element if isinstance(element, type) else str
|
|
499
619
|
)
|
|
500
620
|
graphene_field = graphene.List(base_type)
|
|
501
|
-
resolved_type =
|
|
621
|
+
resolved_type = manager_type or (
|
|
622
|
+
element if isinstance(element, type) else str
|
|
623
|
+
)
|
|
502
624
|
else:
|
|
503
625
|
resolved_type = (
|
|
504
626
|
cast(type[object], type_args[0])
|
|
505
627
|
if type_args
|
|
506
628
|
else cast(type[object], raw_hint)
|
|
507
629
|
)
|
|
630
|
+
resolved_type = (
|
|
631
|
+
resolve_general_manager_type(
|
|
632
|
+
resolved_type,
|
|
633
|
+
cls.manager_registry,
|
|
634
|
+
)
|
|
635
|
+
or resolved_type
|
|
636
|
+
)
|
|
508
637
|
graphene_field = cls._map_field_to_graphene_read(
|
|
509
638
|
resolved_type, attr_name
|
|
510
639
|
)
|
|
@@ -714,7 +843,7 @@ class GraphQL:
|
|
|
714
843
|
field_info,
|
|
715
844
|
) in generalManagerClass.Interface.get_attribute_types().items():
|
|
716
845
|
field_type = field_info["type"]
|
|
717
|
-
if
|
|
846
|
+
if resolve_general_manager_type(field_type, GraphQL.manager_registry):
|
|
718
847
|
continue
|
|
719
848
|
else:
|
|
720
849
|
sort_options.append(field_name)
|
|
@@ -863,7 +992,7 @@ class GraphQL:
|
|
|
863
992
|
|
|
864
993
|
@staticmethod
|
|
865
994
|
def _map_field_to_graphene_read(
|
|
866
|
-
field_type:
|
|
995
|
+
field_type: object,
|
|
867
996
|
field_name: str,
|
|
868
997
|
field_info: Mapping[str, object] | None = None,
|
|
869
998
|
) -> object:
|
|
@@ -891,6 +1020,13 @@ class GraphQL:
|
|
|
891
1020
|
Returns:
|
|
892
1021
|
object: Graphene field or type configured for the attribute.
|
|
893
1022
|
"""
|
|
1023
|
+
manager_type = resolve_general_manager_type(
|
|
1024
|
+
field_type,
|
|
1025
|
+
GraphQL.manager_registry,
|
|
1026
|
+
)
|
|
1027
|
+
if manager_type is not None:
|
|
1028
|
+
field_type = manager_type
|
|
1029
|
+
|
|
894
1030
|
if safe_issubclass(field_type, Measurement):
|
|
895
1031
|
return graphene.Field(MeasurementType, target_unit=graphene.String())
|
|
896
1032
|
elif safe_issubclass(field_type, GeneralManager):
|
|
@@ -925,8 +1061,9 @@ class GraphQL:
|
|
|
925
1061
|
return graphene.Field(StoredFile)
|
|
926
1062
|
if orm_field_kind == "image":
|
|
927
1063
|
return graphene.Field(StoredImage)
|
|
1064
|
+
scalar_type = cast(type, field_type)
|
|
928
1065
|
return GraphQL._map_field_to_graphene_base_type(
|
|
929
|
-
|
|
1066
|
+
scalar_type,
|
|
930
1067
|
field_info,
|
|
931
1068
|
)()
|
|
932
1069
|
|
|
@@ -1084,7 +1221,10 @@ class GraphQL:
|
|
|
1084
1221
|
input_field_name,
|
|
1085
1222
|
input_field,
|
|
1086
1223
|
) in generalManagerClass.Interface.input_fields.items():
|
|
1087
|
-
if
|
|
1224
|
+
if resolve_general_manager_type(
|
|
1225
|
+
input_field.type,
|
|
1226
|
+
cls.manager_registry,
|
|
1227
|
+
):
|
|
1088
1228
|
key = f"{input_field_name}_id"
|
|
1089
1229
|
identification_fields[key] = graphene.Argument(
|
|
1090
1230
|
graphene.ID, required=input_field.required
|
|
@@ -1352,7 +1492,7 @@ class GraphQL:
|
|
|
1352
1492
|
"""
|
|
1353
1493
|
Stream subscription events for a specific manager instance identified by the provided arguments.
|
|
1354
1494
|
|
|
1355
|
-
Yields an initial `SubscriptionEvent` with `action` set to `"snapshot"` containing the current manager instance, then yields `SubscriptionEvent`s for each subsequent action. For
|
|
1495
|
+
Yields an initial `SubscriptionEvent` with `action` set to `"snapshot"` containing the current manager instance, then yields `SubscriptionEvent`s for each subsequent action. For subsequent events, `item` will be the re-instantiated manager instance or `None` if instantiation fails. The subscriber is registered on the manager's channel groups (including dependent managers' groups) and the channel subscriptions and background listener are cleaned up when the iterator is closed or cancelled.
|
|
1356
1496
|
|
|
1357
1497
|
Parameters:
|
|
1358
1498
|
identification: Identification fields required to locate the manager instance (maps to the manager's identification signature).
|
|
@@ -1379,14 +1519,13 @@ class GraphQL:
|
|
|
1379
1519
|
)
|
|
1380
1520
|
except RuntimeError as exc:
|
|
1381
1521
|
raise GraphQLError(str(exc)) from exc
|
|
1382
|
-
channel_name = cast(str, await channel_layer.new_channel())
|
|
1383
|
-
queue: asyncio.Queue[str] = asyncio.Queue[str]()
|
|
1384
1522
|
|
|
1385
1523
|
group_names = {
|
|
1386
1524
|
cls._group_name(
|
|
1387
1525
|
generalManagerClass,
|
|
1388
1526
|
instance.identification,
|
|
1389
|
-
)
|
|
1527
|
+
),
|
|
1528
|
+
cls._refresh_group_name(generalManagerClass),
|
|
1390
1529
|
}
|
|
1391
1530
|
dependencies = cls._resolve_subscription_dependencies(
|
|
1392
1531
|
generalManagerClass,
|
|
@@ -1397,13 +1536,7 @@ class GraphQL:
|
|
|
1397
1536
|
group_names.add(
|
|
1398
1537
|
cls._group_name(dependency_class, dependency_identification)
|
|
1399
1538
|
)
|
|
1400
|
-
|
|
1401
|
-
for group in group_names:
|
|
1402
|
-
await channel_layer.group_add(group, channel_name)
|
|
1403
|
-
|
|
1404
|
-
listener_task = asyncio.create_task(
|
|
1405
|
-
cls._channel_listener(channel_layer, channel_name, queue)
|
|
1406
|
-
)
|
|
1539
|
+
group_names.add(cls._refresh_group_name(dependency_class))
|
|
1407
1540
|
|
|
1408
1541
|
async def event_stream() -> AsyncIterator[SubscriptionEvent]:
|
|
1409
1542
|
"""
|
|
@@ -1415,7 +1548,22 @@ class GraphQL:
|
|
|
1415
1548
|
Notes:
|
|
1416
1549
|
When the iterator is closed or exits, the background listener task is cancelled and the subscription's channel group memberships are discarded.
|
|
1417
1550
|
"""
|
|
1418
|
-
|
|
1551
|
+
channel_name = cast(str, await channel_layer.new_channel())
|
|
1552
|
+
queue: asyncio.Queue[str] = asyncio.Queue[str]()
|
|
1553
|
+
joined_groups = await _join_subscription_groups(
|
|
1554
|
+
channel_layer,
|
|
1555
|
+
channel_name,
|
|
1556
|
+
group_names,
|
|
1557
|
+
)
|
|
1558
|
+
listener_task = asyncio.create_task(
|
|
1559
|
+
cls._channel_listener(channel_layer, channel_name, queue)
|
|
1560
|
+
)
|
|
1561
|
+
async with _subscription_cleanup_scope(
|
|
1562
|
+
channel_layer,
|
|
1563
|
+
channel_name,
|
|
1564
|
+
joined_groups,
|
|
1565
|
+
listener_task,
|
|
1566
|
+
):
|
|
1419
1567
|
clear_capability_context(info)
|
|
1420
1568
|
yield SubscriptionEvent(item=instance, action="snapshot")
|
|
1421
1569
|
while True:
|
|
@@ -1431,12 +1579,6 @@ class GraphQL:
|
|
|
1431
1579
|
item = None
|
|
1432
1580
|
clear_capability_context(info)
|
|
1433
1581
|
yield SubscriptionEvent(item=item, action=action)
|
|
1434
|
-
finally:
|
|
1435
|
-
listener_task.cancel()
|
|
1436
|
-
with suppress(asyncio.CancelledError):
|
|
1437
|
-
await listener_task
|
|
1438
|
-
for group in group_names:
|
|
1439
|
-
await channel_layer.group_discard(group, channel_name)
|
|
1440
1582
|
|
|
1441
1583
|
return event_stream()
|
|
1442
1584
|
|
|
@@ -1466,9 +1608,10 @@ class GraphQL:
|
|
|
1466
1608
|
Stream future authorized change events for any instance of a manager class.
|
|
1467
1609
|
|
|
1468
1610
|
Unlike single-entity subscriptions, class-wide subscriptions do not
|
|
1469
|
-
yield an initial snapshot.
|
|
1470
|
-
|
|
1471
|
-
|
|
1611
|
+
yield an initial snapshot. Aggregate refresh events without an
|
|
1612
|
+
identification carry no item; identified row events, including
|
|
1613
|
+
row-level refresh actions, are hydrated and checked against the
|
|
1614
|
+
request user's object-level read permission before they are yielded.
|
|
1472
1615
|
"""
|
|
1473
1616
|
try:
|
|
1474
1617
|
channel_layer = cast(
|
|
@@ -1476,25 +1619,41 @@ class GraphQL:
|
|
|
1476
1619
|
)
|
|
1477
1620
|
except RuntimeError as exc:
|
|
1478
1621
|
raise GraphQLError(str(exc)) from exc
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
listener_task = asyncio.create_task(
|
|
1484
|
-
cls._channel_message_listener(channel_layer, channel_name, queue)
|
|
1485
|
-
)
|
|
1622
|
+
group_names = {
|
|
1623
|
+
cls._class_group_name(generalManagerClass),
|
|
1624
|
+
cls._refresh_group_name(generalManagerClass),
|
|
1625
|
+
}
|
|
1486
1626
|
|
|
1487
1627
|
async def event_stream() -> AsyncIterator[SubscriptionEvent]:
|
|
1488
|
-
|
|
1628
|
+
channel_name = cast(str, await channel_layer.new_channel())
|
|
1629
|
+
queue: asyncio.Queue[GraphQLFieldMap] = asyncio.Queue()
|
|
1630
|
+
joined_groups = await _join_subscription_groups(
|
|
1631
|
+
channel_layer,
|
|
1632
|
+
channel_name,
|
|
1633
|
+
group_names,
|
|
1634
|
+
)
|
|
1635
|
+
listener_task = asyncio.create_task(
|
|
1636
|
+
cls._channel_message_listener(channel_layer, channel_name, queue)
|
|
1637
|
+
)
|
|
1638
|
+
async with _subscription_cleanup_scope(
|
|
1639
|
+
channel_layer,
|
|
1640
|
+
channel_name,
|
|
1641
|
+
joined_groups,
|
|
1642
|
+
listener_task,
|
|
1643
|
+
):
|
|
1489
1644
|
while True:
|
|
1490
1645
|
message = await queue.get()
|
|
1491
1646
|
if message.get("manager") != generalManagerClass.__name__:
|
|
1492
1647
|
continue
|
|
1493
1648
|
action = message.get("action")
|
|
1649
|
+
if not isinstance(action, str):
|
|
1650
|
+
continue
|
|
1494
1651
|
identification = message.get("identification")
|
|
1495
|
-
if
|
|
1496
|
-
|
|
1497
|
-
|
|
1652
|
+
if action == "refresh" and identification is None:
|
|
1653
|
+
clear_capability_context(info)
|
|
1654
|
+
yield SubscriptionEvent(item=None, action=action)
|
|
1655
|
+
continue
|
|
1656
|
+
if not isinstance(identification, dict):
|
|
1498
1657
|
continue
|
|
1499
1658
|
identification_copy = deepcopy(identification)
|
|
1500
1659
|
try:
|
|
@@ -1509,11 +1668,6 @@ class GraphQL:
|
|
|
1509
1668
|
continue
|
|
1510
1669
|
clear_capability_context(info)
|
|
1511
1670
|
yield SubscriptionEvent(item=item, action=action)
|
|
1512
|
-
finally:
|
|
1513
|
-
listener_task.cancel()
|
|
1514
|
-
with suppress(asyncio.CancelledError):
|
|
1515
|
-
await listener_task
|
|
1516
|
-
await channel_layer.group_discard(group_name, channel_name)
|
|
1517
1671
|
|
|
1518
1672
|
return event_stream()
|
|
1519
1673
|
|
|
@@ -1595,14 +1749,15 @@ class GraphQL:
|
|
|
1595
1749
|
Send a "gm.subscription.event" message to the channel group corresponding to a changed GeneralManager instance.
|
|
1596
1750
|
|
|
1597
1751
|
If the provided instance is a registered GeneralManager and a channel
|
|
1598
|
-
layer is configured,
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1752
|
+
layer is configured, queue one manager-wide refresh while notification
|
|
1753
|
+
batching is active. Outside a batch, publish the row-level message to
|
|
1754
|
+
the instance and class-wide groups through one async bridge.
|
|
1755
|
+
Identification comes from the provided `identification` mapping when
|
|
1756
|
+
supplied, otherwise from the changed instance, and is deep-copied
|
|
1757
|
+
before dispatch. If the instance is `None`, the manager type is not
|
|
1758
|
+
registered, or no channel layer is available, the function returns
|
|
1759
|
+
without dispatching. Ordinary group dispatch failures are logged and
|
|
1760
|
+
do not stop attempts for remaining groups.
|
|
1606
1761
|
|
|
1607
1762
|
Parameters:
|
|
1608
1763
|
sender (type[GeneralManager] | GeneralManager): The signal sender; either a GeneralManager subclass or an instance.
|
|
@@ -1646,35 +1801,57 @@ class GraphQL:
|
|
|
1646
1801
|
)
|
|
1647
1802
|
group_name = cls._group_name(manager_class, event_identification)
|
|
1648
1803
|
class_group_name = cls._class_group_name(manager_class)
|
|
1649
|
-
message = {
|
|
1804
|
+
message: dict[str, object] = {
|
|
1650
1805
|
"type": "gm.subscription.event",
|
|
1651
1806
|
"action": action,
|
|
1652
1807
|
"manager": manager_class.__name__,
|
|
1653
1808
|
"identification": event_identification,
|
|
1654
1809
|
}
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1810
|
+
refresh_group_name = cls._refresh_group_name(manager_class)
|
|
1811
|
+
refresh_message: dict[str, object] = {
|
|
1812
|
+
"type": "gm.subscription.event",
|
|
1813
|
+
"action": "refresh",
|
|
1814
|
+
"manager": manager_class.__name__,
|
|
1815
|
+
}
|
|
1816
|
+
if _queue_notification(
|
|
1817
|
+
key=("graphql", refresh_group_name),
|
|
1818
|
+
group_send=channel_layer.group_send,
|
|
1819
|
+
group=refresh_group_name,
|
|
1820
|
+
message=refresh_message,
|
|
1821
|
+
):
|
|
1822
|
+
return
|
|
1823
|
+
|
|
1824
|
+
target_groups = (group_name, class_group_name)
|
|
1825
|
+
try:
|
|
1826
|
+
dispatched = async_to_sync(_dispatch_subscription_event_fn)(
|
|
1827
|
+
channel_layer,
|
|
1828
|
+
target_groups,
|
|
1829
|
+
message,
|
|
1830
|
+
)
|
|
1831
|
+
except MemoryError:
|
|
1832
|
+
raise
|
|
1833
|
+
except Exception as exc: # noqa: BLE001
|
|
1834
|
+
logger.warning(
|
|
1835
|
+
"failed to dispatch subscription event",
|
|
1836
|
+
context={
|
|
1837
|
+
"manager": manager_class.__name__,
|
|
1838
|
+
"action": action,
|
|
1839
|
+
"target_groups": list(target_groups),
|
|
1840
|
+
"message": message,
|
|
1841
|
+
},
|
|
1842
|
+
exc_info=exc,
|
|
1843
|
+
)
|
|
1844
|
+
return
|
|
1845
|
+
if dispatched > 0:
|
|
1846
|
+
logger.debug(
|
|
1847
|
+
"dispatched subscription event",
|
|
1848
|
+
context={
|
|
1849
|
+
"manager": manager_class.__name__,
|
|
1850
|
+
"action": action,
|
|
1851
|
+
"target_groups": list(target_groups),
|
|
1852
|
+
"successful_group_count": dispatched,
|
|
1853
|
+
},
|
|
1854
|
+
)
|
|
1678
1855
|
|
|
1679
1856
|
|
|
1680
1857
|
post_data_change.connect(GraphQL._handle_data_change, weak=False)
|