GeneralManager 0.80.0__tar.gz → 0.80.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {generalmanager-0.80.0/src/GeneralManager.egg-info → generalmanager-0.80.2}/PKG-INFO +1 -1
- {generalmanager-0.80.0 → generalmanager-0.80.2}/pyproject.toml +1 -1
- {generalmanager-0.80.0 → generalmanager-0.80.2/src/GeneralManager.egg-info}/PKG-INFO +1 -1
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/GeneralManager.egg-info/SOURCES.txt +1 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/graphql_mutations.py +6 -3
- generalmanager-0.80.2/src/general_manager/cache/_dependency_graph.py +116 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/cache/cache_decorator.py +37 -11
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/cache/cache_tracker.py +165 -30
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/cache/dependency_cache.py +37 -2
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/cache/model_dependency_collector.py +13 -9
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/cache/run_context.py +38 -14
- generalmanager-0.80.2/src/general_manager/cache/run_context_lru.py +3307 -0
- generalmanager-0.80.0/src/general_manager/cache/run_context_lru.py +0 -1389
- {generalmanager-0.80.0 → generalmanager-0.80.2}/LICENSE +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/README.md +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/setup.cfg +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/GeneralManager.egg-info/dependency_links.txt +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/GeneralManager.egg-info/requires.txt +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/GeneralManager.egg-info/top_level.txt +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/_types/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/_types/api.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/_types/bucket.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/_types/cache.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/_types/dataframes.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/_types/factory.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/_types/general_manager.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/_types/interface.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/_types/manager.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/_types/measurement.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/_types/permission.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/_types/rule.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/_types/search.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/_types/utils.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/graphql.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/graphql_as_of.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/graphql_errors.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/graphql_groups.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/graphql_ordering.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/graphql_output.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/graphql_prefetch.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/graphql_relations.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/graphql_resolvers.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/graphql_search.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/graphql_subscription_consumer.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/graphql_subscriptions.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/graphql_type.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/graphql_view.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/graphql_warmup.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/graphql_warmup_registry.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/graphql_warmup_tasks.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/mutation.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/notification_batching.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/property.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/registry.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/remote_api.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/remote_invalidation.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/remote_invalidation_client.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/apps.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/as_of.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/bootstrap.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/bucket/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/bucket/_materialized_bucket.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/bucket/_ordering.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/bucket/base_bucket.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/bucket/calculation_bucket.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/bucket/database_bucket.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/bucket/excel_bucket.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/bucket/group_bucket.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/bucket/indexing.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/bucket/projection.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/bucket/request_bucket.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/cache/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/cache/data_change_context.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/cache/dependency_index.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/cache/dependency_matching.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/cache/dependency_publish.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/cache/dependency_shards.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/cache/signals.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/audit.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/bootstrap.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/checks.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/consumer.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/context.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/errors.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/evals/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/evals/__main__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/evals/baseline.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/evals/datasets/basic_queries.yaml +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/evals/datasets/demo_readiness.yaml +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/evals/datasets/edge_cases.yaml +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/evals/datasets/follow_ups.yaml +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/evals/datasets/large_schema.yaml +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/evals/datasets/multi_hop.yaml +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/evals/datasets/planned_orchestration.yaml +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/evals/diagnostics.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/evals/fingerprints.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/evals/fixtures.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/evals/judges/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/evals/judges/answer_quality.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/evals/judges/contract.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/evals/judges/result_accuracy.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/evals/judges/tool_sequence.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/evals/readiness.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/evals/runner.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/evals/traces.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/grounding.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/models.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/planned/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/planned/budget.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/planned/calculations.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/planned/catalog.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/planned/config.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/planned/events.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/planned/evidence.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/planned/models.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/planned/planner.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/planned/provider_calls.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/planned/resolver.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/planned/routing.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/planned/scheduler.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/planned/synthesis.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/planned/validation.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/providers/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/providers/_shared.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/providers/anthropic.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/providers/base.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/providers/google.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/providers/ollama.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/providers/openai.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/rate_limits.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/routing.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/schema_index.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/settings.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/signals.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/system_prompt.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/tool_metadata.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/tools.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/turns.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/chat/views.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/conf.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/dataframes/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/dataframes/measurements.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/factory/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/factory/auto_factory.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/factory/factories.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/factory/factory_methods.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/base_interface.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/bundles/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/bundles/calculation.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/bundles/database.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/bundles/excel.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/bundles/remote_manager.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/bundles/request.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/base.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/builtin.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/calculation/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/calculation/_compat.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/calculation/input_resolution.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/calculation/lifecycle.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/configuration.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/core/observability.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/core/utils.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/excel/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/exceptions.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/existing_model/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/existing_model/_compat.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/existing_model/resolution.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/factory.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/orm/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/orm/_compat.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/orm/history.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/orm/lifecycle.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/orm/mutations.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/orm/support.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/orm_utils/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/orm_utils/django_manager_utils.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/orm_utils/field_descriptors.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/orm_utils/payload_normalizer.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/orm_utils/update_state.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/read_only/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/read_only/_compat.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/read_only/_types.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/read_only/lifecycle.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/read_only/management.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/registry.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/remote_manager.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/capabilities/request/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/excel.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/excel_store.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/excel_workbook.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/infrastructure/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/infrastructure/startup_hooks.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/infrastructure/system_checks.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/interfaces/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/interfaces/calculation.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/interfaces/database.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/interfaces/excel.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/interfaces/existing_model.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/interfaces/read_only.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/interfaces/remote_manager.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/interfaces/request.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/manifests/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/manifests/capability_builder.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/manifests/capability_manifest.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/manifests/capability_models.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/orm_interface.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/requests.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/utils/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/utils/database_interface_protocols.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/utils/errors.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/utils/history.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/interface/utils/models.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/logging.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/management/commands/chat_cleanup.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/management/commands/cleanup_upload_intents.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/management/commands/graphql_warmup.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/management/commands/graphql_warmup_refresh_due.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/management/commands/search_index.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/management/commands/search_reconcile.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/management/commands/seed_manager_landscape.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/management/commands/shell.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/management/commands/workflow_drain_outbox.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/management/commands/workflow_replay_dead_letters.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/manager/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/manager/general_manager.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/manager/group_manager.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/manager/input.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/manager/meta.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/measurement/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/measurement/measurement.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/measurement/measurement_field.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/metrics/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/metrics/graphql.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/migrations/0001_initial.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/migrations/0002_workflow_outbox_scaling_indexes.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/migrations/0003_workflow_execution_correlation_constraint.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/migrations/0004_chat_persistence_models.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/migrations/0004_search_index_state.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/migrations/0005_merge_chat_search.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/migrations/0006_chat_pending_confirmation_scoped_ids.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/migrations/0007_upload_intent.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/migrations/0008_upload_finalization_versions.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/migrations/0009_upload_cleanup_state.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/migrations/0010_chat_pending_confirmation_portable_uniqueness.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/migrations/0011_search_index_state_dirty_generation.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/migrations/0012_chat_context_watermarks.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/migrations/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/models.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/permission/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/permission/audit.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/permission/base_permission.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/permission/graphql_capabilities.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/permission/manager_based_permission.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/permission/mutation_permission.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/permission/permission_checks.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/permission/permission_data_manager.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/permission/utils.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/public_api_registry.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/py.typed +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/rule/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/rule/handler.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/rule/rule.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/search/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/search/async_tasks.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/search/backend.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/search/backend_registry.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/search/backends/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/search/backends/dev.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/search/backends/meilisearch.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/search/backends/opensearch.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/search/backends/typesense.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/search/checks.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/search/config.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/search/indexer.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/search/invalidation.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/search/m2m_invalidation.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/search/models.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/search/reconciliation.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/search/registry.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/search/tasks.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/search/utils.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/seeding/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/seeding/manager_landscape.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/uploads/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/uploads/adapters.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/uploads/checks.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/uploads/config.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/uploads/errors.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/uploads/finalization.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/uploads/graphql.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/uploads/graphql_types.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/uploads/metrics.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/uploads/models.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/uploads/public.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/uploads/s3.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/uploads/services.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/uploads/tokens.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/uploads/types.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/uploads/urls.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/uploads/views.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/utils/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/utils/_args_to_kwargs.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/utils/_cache_key_encoder.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/utils/_make_cache_key.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/utils/_none_to_zero.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/utils/filter_parser.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/utils/format_string.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/utils/json_encoder.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/utils/path_mapping.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/utils/public_api.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/utils/testing.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/utils/type_checks.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/workflow/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/workflow/actions.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/workflow/backend_registry.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/workflow/backends/__init__.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/workflow/backends/celery.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/workflow/backends/local.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/workflow/backends/n8n.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/workflow/config.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/workflow/engine.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/workflow/event_registry.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/workflow/events.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/workflow/models.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/workflow/signal_bridge.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/workflow/tasks.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/workflow/telemetry.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/tests/test_settings.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/tests/test_urls.py +0 -0
- {generalmanager-0.80.0 → generalmanager-0.80.2}/tests/testing_asgi.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GeneralManager
|
|
3
|
-
Version: 0.80.
|
|
3
|
+
Version: 0.80.2
|
|
4
4
|
Summary: Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching.
|
|
5
5
|
Author-email: Tim Kleindick <tkleindick@yahoo.de>
|
|
6
6
|
License: MIT License
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "GeneralManager"
|
|
7
|
-
version = "0.80.
|
|
7
|
+
version = "0.80.2"
|
|
8
8
|
description = "Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{ name = "Tim Kleindick", email = "tkleindick@yahoo.de" }]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GeneralManager
|
|
3
|
-
Version: 0.80.
|
|
3
|
+
Version: 0.80.2
|
|
4
4
|
Summary: Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching.
|
|
5
5
|
Author-email: Tim Kleindick <tkleindick@yahoo.de>
|
|
6
6
|
License: MIT License
|
|
@@ -67,6 +67,7 @@ src/general_manager/bucket/indexing.py
|
|
|
67
67
|
src/general_manager/bucket/projection.py
|
|
68
68
|
src/general_manager/bucket/request_bucket.py
|
|
69
69
|
src/general_manager/cache/__init__.py
|
|
70
|
+
src/general_manager/cache/_dependency_graph.py
|
|
70
71
|
src/general_manager/cache/cache_decorator.py
|
|
71
72
|
src/general_manager/cache/cache_tracker.py
|
|
72
73
|
src/general_manager/cache/data_change_context.py
|
{generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/api/graphql_mutations.py
RENAMED
|
@@ -14,7 +14,7 @@ from __future__ import annotations
|
|
|
14
14
|
from typing import TYPE_CHECKING, Protocol, cast
|
|
15
15
|
|
|
16
16
|
import graphene
|
|
17
|
-
from graphql import GraphQLError
|
|
17
|
+
from graphql import GraphQLError, Undefined
|
|
18
18
|
|
|
19
19
|
from django.db.models import NOT_PROVIDED
|
|
20
20
|
from django.db import models
|
|
@@ -309,7 +309,8 @@ def create_write_fields(
|
|
|
309
309
|
the input fields.
|
|
310
310
|
require_fields: Whether generated fields should mirror interface
|
|
311
311
|
requiredness. Create/delete helper calls use the default ``True``;
|
|
312
|
-
update mutations set this to ``False`` to support partial updates
|
|
312
|
+
update mutations set this to ``False`` to support partial updates
|
|
313
|
+
and omit model defaults from their GraphQL arguments.
|
|
313
314
|
|
|
314
315
|
Returns:
|
|
315
316
|
Mapping from attribute name to a Graphene input field instance. Returned
|
|
@@ -333,7 +334,9 @@ def create_write_fields(
|
|
|
333
334
|
|
|
334
335
|
typ = info["type"]
|
|
335
336
|
req = info["is_required"] if require_fields else False
|
|
336
|
-
|
|
337
|
+
# GraphQL injects argument defaults before the resolver sees the payload.
|
|
338
|
+
# Partial updates must preserve omission, including defaults of None.
|
|
339
|
+
default = info["default"] if require_fields else Undefined
|
|
337
340
|
|
|
338
341
|
fld: object
|
|
339
342
|
if info.get("orm_field_kind") in {"file", "image"}:
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""Private immutable dependency snapshots shared by cache computations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Iterable
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from typing import cast
|
|
8
|
+
|
|
9
|
+
from general_manager.cache.dependency_index import Dependency
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass(frozen=True, slots=True, eq=False)
|
|
13
|
+
class _DependencyBlock:
|
|
14
|
+
"""One immutable collection of directly observed dependency tuples.
|
|
15
|
+
|
|
16
|
+
Equality deliberately remains identity based. A block can be referenced by
|
|
17
|
+
several snapshot leaves (notably prefetched dependency-cache hits), and a
|
|
18
|
+
materialization must visit that shared block only once.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
dependencies: tuple[Dependency, ...] | frozenset[Dependency]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True, slots=True, eq=False)
|
|
25
|
+
class DependencySnapshot:
|
|
26
|
+
"""An immutable node containing direct dependencies and child snapshots."""
|
|
27
|
+
|
|
28
|
+
block: _DependencyBlock | None
|
|
29
|
+
children: tuple["DependencySnapshot", ...]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
_EMPTY_SNAPSHOT = DependencySnapshot(block=None, children=())
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def empty_dependency_snapshot() -> DependencySnapshot:
|
|
36
|
+
"""Return the shared empty dependency root."""
|
|
37
|
+
return _EMPTY_SNAPSHOT
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def snapshot_from_dependencies(
|
|
41
|
+
dependencies: Iterable[Dependency],
|
|
42
|
+
) -> DependencySnapshot:
|
|
43
|
+
"""Freeze direct dependencies at a boundary into a standalone leaf."""
|
|
44
|
+
# Hits already own an immutable dependency container. Retaining that
|
|
45
|
+
# container by identity is what lets independent leaf wrappers share its
|
|
46
|
+
# storage (and lets materialization/accounting charge it once). Mutable
|
|
47
|
+
# inputs must still be copied at this boundary.
|
|
48
|
+
if type(dependencies) in (tuple, frozenset):
|
|
49
|
+
frozen_dependencies = cast(
|
|
50
|
+
tuple[Dependency, ...] | frozenset[Dependency], dependencies
|
|
51
|
+
)
|
|
52
|
+
else:
|
|
53
|
+
frozen_dependencies = tuple(dependencies)
|
|
54
|
+
if not frozen_dependencies:
|
|
55
|
+
return _EMPTY_SNAPSHOT
|
|
56
|
+
return DependencySnapshot(_DependencyBlock(frozen_dependencies), ())
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class DependencyCapture:
|
|
60
|
+
"""Mutable builder used only while one cache calculation is executing."""
|
|
61
|
+
|
|
62
|
+
__slots__ = ("_child_ids", "_children", "_dependencies")
|
|
63
|
+
|
|
64
|
+
def __init__(self) -> None:
|
|
65
|
+
"""Start an empty per-calculation builder."""
|
|
66
|
+
self._dependencies: set[Dependency] = set()
|
|
67
|
+
self._children: list[DependencySnapshot] = []
|
|
68
|
+
self._child_ids: set[int] = set()
|
|
69
|
+
|
|
70
|
+
def add(self, dependency: Dependency) -> None:
|
|
71
|
+
"""Record one direct dependency in this calculation frame."""
|
|
72
|
+
self._dependencies.add(dependency)
|
|
73
|
+
|
|
74
|
+
def attach(self, snapshot: DependencySnapshot) -> None:
|
|
75
|
+
"""Attach a child snapshot once, using node identity for deduplication."""
|
|
76
|
+
if snapshot is _EMPTY_SNAPSHOT:
|
|
77
|
+
return
|
|
78
|
+
snapshot_id = id(snapshot)
|
|
79
|
+
if snapshot_id not in self._child_ids:
|
|
80
|
+
self._child_ids.add(snapshot_id)
|
|
81
|
+
self._children.append(snapshot)
|
|
82
|
+
|
|
83
|
+
def freeze(self) -> DependencySnapshot:
|
|
84
|
+
"""Build the immutable root, reusing simple child-only snapshots."""
|
|
85
|
+
if not self._dependencies:
|
|
86
|
+
if not self._children:
|
|
87
|
+
return _EMPTY_SNAPSHOT
|
|
88
|
+
if len(self._children) == 1:
|
|
89
|
+
return self._children[0]
|
|
90
|
+
return DependencySnapshot(None, tuple(self._children))
|
|
91
|
+
return DependencySnapshot(
|
|
92
|
+
_DependencyBlock(tuple(self._dependencies)),
|
|
93
|
+
tuple(self._children),
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def materialize_dependencies(snapshot: DependencySnapshot) -> set[Dependency]:
|
|
98
|
+
"""Iteratively flatten a graph, visiting nodes and direct blocks by identity."""
|
|
99
|
+
dependencies: set[Dependency] = set()
|
|
100
|
+
pending = [snapshot]
|
|
101
|
+
seen_nodes: set[int] = set()
|
|
102
|
+
seen_dependency_containers: set[int] = set()
|
|
103
|
+
while pending:
|
|
104
|
+
node = pending.pop()
|
|
105
|
+
node_id = id(node)
|
|
106
|
+
if node_id in seen_nodes:
|
|
107
|
+
continue
|
|
108
|
+
seen_nodes.add(node_id)
|
|
109
|
+
block = node.block
|
|
110
|
+
if block is not None:
|
|
111
|
+
dependency_container_id = id(block.dependencies)
|
|
112
|
+
if dependency_container_id not in seen_dependency_containers:
|
|
113
|
+
seen_dependency_containers.add(dependency_container_id)
|
|
114
|
+
dependencies.update(block.dependencies)
|
|
115
|
+
pending.extend(node.children)
|
|
116
|
+
return dependencies
|
{generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/cache/cache_decorator.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Helpers for caching GeneralManager computations with dependency tracking."""
|
|
2
2
|
|
|
3
|
-
from collections.abc import Callable, Iterable
|
|
3
|
+
from collections.abc import Callable, Iterable, Mapping
|
|
4
4
|
from functools import partial, wraps
|
|
5
5
|
from hashlib import sha256
|
|
6
6
|
import inspect
|
|
@@ -8,7 +8,10 @@ from typing import Literal, ParamSpec, Protocol, TypeVar, cast, overload
|
|
|
8
8
|
|
|
9
9
|
from django.core.cache import cache as django_cache
|
|
10
10
|
|
|
11
|
-
from general_manager.cache.cache_tracker import
|
|
11
|
+
from general_manager.cache.cache_tracker import (
|
|
12
|
+
DependencyTracker,
|
|
13
|
+
_DependencyCaptureScope,
|
|
14
|
+
)
|
|
12
15
|
from general_manager.cache.dependency_cache import (
|
|
13
16
|
DependencyCacheHit,
|
|
14
17
|
dependency_cache_prefetch_bundle_key,
|
|
@@ -170,7 +173,26 @@ def _reject_awaitable_cache_result(result: object) -> None:
|
|
|
170
173
|
|
|
171
174
|
def _replay_run_cache_entry_dependencies(entry: _RunCacheEntry) -> None:
|
|
172
175
|
"""Replay a decorated run-cache entry into every active dependency tracker."""
|
|
173
|
-
|
|
176
|
+
DependencyTracker._attach_snapshot(entry.dependency_root)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def _track_model_arguments(
|
|
180
|
+
args: tuple[object, ...],
|
|
181
|
+
kwargs: Mapping[str, object],
|
|
182
|
+
capture: _DependencyCaptureScope,
|
|
183
|
+
) -> None:
|
|
184
|
+
"""Track model argument dependencies as they are discovered.
|
|
185
|
+
|
|
186
|
+
Collector iteration can raise while serializing a later argument. Recording
|
|
187
|
+
each earlier value immediately preserves the same partial-dependency
|
|
188
|
+
behavior as ordinary source reads.
|
|
189
|
+
"""
|
|
190
|
+
for class_name, operation, identifier in ModelDependencyCollector._iter_args(
|
|
191
|
+
args, kwargs
|
|
192
|
+
):
|
|
193
|
+
dependency = (class_name, operation, identifier)
|
|
194
|
+
if capture._record_argument_dependency(dependency):
|
|
195
|
+
continue
|
|
174
196
|
DependencyTracker._track_validated(class_name, operation, identifier)
|
|
175
197
|
|
|
176
198
|
|
|
@@ -418,15 +440,16 @@ def cached(
|
|
|
418
440
|
_replay_run_cache_entry_dependencies(cached_run_value)
|
|
419
441
|
return cast(R, cached_run_value.value)
|
|
420
442
|
return cast(R, cached_run_value)
|
|
421
|
-
with DependencyTracker() as
|
|
443
|
+
with DependencyTracker._capture() as capture:
|
|
422
444
|
result = decorated_func(*args, **kwargs)
|
|
423
|
-
|
|
445
|
+
_track_model_arguments(args, kwargs, capture)
|
|
424
446
|
_reject_awaitable_cache_result(result)
|
|
447
|
+
assert capture.snapshot is not None
|
|
425
448
|
active_context.set(
|
|
426
449
|
key,
|
|
427
450
|
_RunCacheEntry(
|
|
428
451
|
value=result,
|
|
429
|
-
|
|
452
|
+
dependency_root=capture.snapshot,
|
|
430
453
|
),
|
|
431
454
|
)
|
|
432
455
|
return result
|
|
@@ -437,15 +460,16 @@ def cached(
|
|
|
437
460
|
_replay_run_cache_entry_dependencies(cached_run_value)
|
|
438
461
|
return cast(R, cached_run_value.value)
|
|
439
462
|
return cast(R, cached_run_value)
|
|
440
|
-
with DependencyTracker() as
|
|
463
|
+
with DependencyTracker._capture() as capture:
|
|
441
464
|
result = decorated_func(*args, **kwargs)
|
|
442
|
-
|
|
465
|
+
_track_model_arguments(args, kwargs, capture)
|
|
443
466
|
_reject_awaitable_cache_result(result)
|
|
467
|
+
assert capture.snapshot is not None
|
|
444
468
|
context.set(
|
|
445
469
|
key,
|
|
446
470
|
_RunCacheEntry(
|
|
447
471
|
value=result,
|
|
448
|
-
|
|
472
|
+
dependency_root=capture.snapshot,
|
|
449
473
|
),
|
|
450
474
|
)
|
|
451
475
|
return result
|
|
@@ -566,10 +590,12 @@ def cached(
|
|
|
566
590
|
return return_cached_hit(cached_hit, "cache hit")
|
|
567
591
|
|
|
568
592
|
started_generation = get_dependency_generation()
|
|
569
|
-
with DependencyTracker() as
|
|
593
|
+
with DependencyTracker._capture() as capture:
|
|
570
594
|
result = decorated_func(*args, **kwargs)
|
|
571
|
-
|
|
595
|
+
_track_model_arguments(args, kwargs, capture)
|
|
572
596
|
_reject_awaitable_cache_result(result)
|
|
597
|
+
assert capture.snapshot is not None
|
|
598
|
+
dependencies = DependencyTracker._materialize_snapshot(capture.snapshot)
|
|
573
599
|
|
|
574
600
|
def record_many(
|
|
575
601
|
entries: Iterable[tuple[str, Iterable[Dependency]]],
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"""Context manager utilities for tracking cache dependencies per thread."""
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Iterable
|
|
4
6
|
import threading
|
|
5
7
|
from types import TracebackType
|
|
6
8
|
|
|
@@ -9,6 +11,12 @@ from general_manager.cache.dependency_index import (
|
|
|
9
11
|
filter_type,
|
|
10
12
|
general_manager_name,
|
|
11
13
|
)
|
|
14
|
+
from general_manager.cache._dependency_graph import (
|
|
15
|
+
DependencyCapture,
|
|
16
|
+
DependencySnapshot,
|
|
17
|
+
materialize_dependencies,
|
|
18
|
+
snapshot_from_dependencies,
|
|
19
|
+
)
|
|
12
20
|
|
|
13
21
|
_SUPPORTED_OPERATIONS: frozenset[filter_type] = frozenset(
|
|
14
22
|
{"filter", "exclude", "identification", "request_query", "all"}
|
|
@@ -35,13 +43,18 @@ class _TrackedDependencySet(set[Dependency]):
|
|
|
35
43
|
"""Dependency set returned by DependencyTracker for framework-captured deps."""
|
|
36
44
|
|
|
37
45
|
|
|
46
|
+
class _CapturedDependencySet(_TrackedDependencySet):
|
|
47
|
+
"""Private materialization of a trusted immutable dependency graph."""
|
|
48
|
+
|
|
49
|
+
|
|
38
50
|
class _DependencyStorage(threading.local):
|
|
39
51
|
"""Thread-local dependency tracking stack."""
|
|
40
52
|
|
|
41
53
|
def __init__(self) -> None:
|
|
42
54
|
"""Initialize an inactive dependency stack for one thread."""
|
|
43
55
|
self.dependencies: list[_TrackedDependencySet] = []
|
|
44
|
-
self.
|
|
56
|
+
self.captures: list[DependencyCapture] = []
|
|
57
|
+
self.generation = 0
|
|
45
58
|
self.stack_version = 0
|
|
46
59
|
self.last_dependency: Dependency | None = None
|
|
47
60
|
self.last_dependency_stack_version = -1
|
|
@@ -50,8 +63,12 @@ class _DependencyStorage(threading.local):
|
|
|
50
63
|
|
|
51
64
|
def reset(self) -> None:
|
|
52
65
|
"""Clear all active dependency scopes for the current thread."""
|
|
66
|
+
# Capture scopes retain direct references to their old parent builders.
|
|
67
|
+
# Detaching this stack therefore prevents later ordinary reads from
|
|
68
|
+
# reaching it while still allowing each scope to finalize its own result.
|
|
53
69
|
self.dependencies.clear()
|
|
54
|
-
self.
|
|
70
|
+
self.captures.clear()
|
|
71
|
+
self.generation += 1
|
|
55
72
|
self.stack_version += 1
|
|
56
73
|
self.last_dependency = None
|
|
57
74
|
self.last_dependency_stack_version = -1
|
|
@@ -62,6 +79,79 @@ class _DependencyStorage(threading.local):
|
|
|
62
79
|
_dependency_storage = _DependencyStorage()
|
|
63
80
|
|
|
64
81
|
|
|
82
|
+
def _clear_duplicate_state(storage: _DependencyStorage) -> None:
|
|
83
|
+
"""Release duplicate-suppression references after the final scope exits."""
|
|
84
|
+
storage.last_dependency = None
|
|
85
|
+
storage.last_dependency_stack_version = -1
|
|
86
|
+
storage.seen_dependencies.clear()
|
|
87
|
+
storage.seen_dependencies_stack_version = -1
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class _DependencyCaptureScope:
|
|
91
|
+
"""Private compact dependency capture for one decorated computation."""
|
|
92
|
+
|
|
93
|
+
def __init__(self) -> None:
|
|
94
|
+
"""Create an unentered capture scope."""
|
|
95
|
+
self._capture: DependencyCapture | None = None
|
|
96
|
+
self._parent_capture: DependencyCapture | None = None
|
|
97
|
+
self._generation = -1
|
|
98
|
+
self.snapshot: DependencySnapshot | None = None
|
|
99
|
+
|
|
100
|
+
def __enter__(self) -> "_DependencyCaptureScope":
|
|
101
|
+
storage = _dependency_storage
|
|
102
|
+
self._generation = storage.generation
|
|
103
|
+
self.snapshot = None
|
|
104
|
+
capture = DependencyCapture()
|
|
105
|
+
self._capture = capture
|
|
106
|
+
self._parent_capture = storage.captures[-1] if storage.captures else None
|
|
107
|
+
storage.captures.append(capture)
|
|
108
|
+
storage.stack_version += 1
|
|
109
|
+
return self
|
|
110
|
+
|
|
111
|
+
def __exit__(
|
|
112
|
+
self,
|
|
113
|
+
exc_type: type[BaseException] | None,
|
|
114
|
+
exc_val: BaseException | None,
|
|
115
|
+
exc_tb: TracebackType | None,
|
|
116
|
+
) -> None:
|
|
117
|
+
del exc_type, exc_val, exc_tb
|
|
118
|
+
storage = _dependency_storage
|
|
119
|
+
capture = self._capture
|
|
120
|
+
if capture is None:
|
|
121
|
+
return
|
|
122
|
+
parent_capture = self._parent_capture
|
|
123
|
+
self._capture = None
|
|
124
|
+
self._parent_capture = None
|
|
125
|
+
snapshot = capture.freeze()
|
|
126
|
+
self.snapshot = snapshot
|
|
127
|
+
if (
|
|
128
|
+
storage.generation == self._generation
|
|
129
|
+
and storage.captures
|
|
130
|
+
and storage.captures[-1] is capture
|
|
131
|
+
):
|
|
132
|
+
storage.captures.pop()
|
|
133
|
+
storage.stack_version += 1
|
|
134
|
+
storage.last_dependency = None
|
|
135
|
+
storage.last_dependency_stack_version = -1
|
|
136
|
+
if not storage.dependencies and not storage.captures:
|
|
137
|
+
_clear_duplicate_state(storage)
|
|
138
|
+
if parent_capture is not None:
|
|
139
|
+
parent_capture.attach(snapshot)
|
|
140
|
+
|
|
141
|
+
def _record_argument_dependency(self, dependency: Dependency) -> bool:
|
|
142
|
+
"""Record a decorator-derived argument after this scope was detached."""
|
|
143
|
+
capture = self._capture
|
|
144
|
+
storage = _dependency_storage
|
|
145
|
+
if capture is not None and (
|
|
146
|
+
storage.generation != self._generation
|
|
147
|
+
or not storage.captures
|
|
148
|
+
or storage.captures[-1] is not capture
|
|
149
|
+
):
|
|
150
|
+
capture.add(dependency)
|
|
151
|
+
return True
|
|
152
|
+
return False
|
|
153
|
+
|
|
154
|
+
|
|
65
155
|
class DependencyTracker:
|
|
66
156
|
"""Capture dependencies touched inside a read or cache-computation scope.
|
|
67
157
|
|
|
@@ -69,6 +159,10 @@ class DependencyTracker:
|
|
|
69
159
|
tracker state if their execution is interleaved inside one active context.
|
|
70
160
|
"""
|
|
71
161
|
|
|
162
|
+
def __init__(self) -> None:
|
|
163
|
+
"""Create per-thread scope storage before the tracker can be shared."""
|
|
164
|
+
self._scope_storage = threading.local()
|
|
165
|
+
|
|
72
166
|
def __enter__(
|
|
73
167
|
self,
|
|
74
168
|
) -> set[Dependency]:
|
|
@@ -83,10 +177,17 @@ class DependencyTracker:
|
|
|
83
177
|
remains a usable snapshot after the context exits; clearing
|
|
84
178
|
thread-local storage does not mutate sets that were already returned.
|
|
85
179
|
"""
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
180
|
+
storage = _dependency_storage
|
|
181
|
+
scope_storage = self._scope_storage
|
|
182
|
+
if not hasattr(scope_storage, "scopes"):
|
|
183
|
+
scope_storage.scopes = []
|
|
184
|
+
scopes: list[tuple[int, _TrackedDependencySet]] = scope_storage.scopes
|
|
185
|
+
generation = storage.generation
|
|
186
|
+
collector = _TrackedDependencySet()
|
|
187
|
+
scopes.append((generation, collector))
|
|
188
|
+
storage.dependencies.append(collector)
|
|
189
|
+
storage.stack_version += 1
|
|
190
|
+
return collector
|
|
90
191
|
|
|
91
192
|
def __exit__(
|
|
92
193
|
self,
|
|
@@ -107,16 +208,24 @@ class DependencyTracker:
|
|
|
107
208
|
`reset_thread_local_storage()` or otherwise without an active context is
|
|
108
209
|
a no-op.
|
|
109
210
|
"""
|
|
110
|
-
|
|
211
|
+
storage = _dependency_storage
|
|
212
|
+
scope_storage = getattr(self, "_scope_storage", None)
|
|
213
|
+
scopes = getattr(scope_storage, "scopes", None)
|
|
214
|
+
if not scopes:
|
|
111
215
|
return
|
|
112
|
-
|
|
113
|
-
|
|
216
|
+
generation, collector = scopes.pop()
|
|
217
|
+
if (
|
|
218
|
+
generation != storage.generation
|
|
219
|
+
or not storage.dependencies
|
|
220
|
+
or storage.dependencies[-1] is not collector
|
|
221
|
+
):
|
|
114
222
|
return
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
223
|
+
storage.dependencies.pop()
|
|
224
|
+
storage.stack_version += 1
|
|
225
|
+
storage.last_dependency = None
|
|
226
|
+
storage.last_dependency_stack_version = -1
|
|
227
|
+
if not storage.dependencies and not storage.captures:
|
|
228
|
+
_clear_duplicate_state(storage)
|
|
120
229
|
|
|
121
230
|
@staticmethod
|
|
122
231
|
def track(
|
|
@@ -164,7 +273,7 @@ class DependencyTracker:
|
|
|
164
273
|
) -> None:
|
|
165
274
|
"""Record an already-validated dependency tuple in active collectors."""
|
|
166
275
|
storage = _dependency_storage
|
|
167
|
-
if storage.
|
|
276
|
+
if not storage.dependencies and not storage.captures:
|
|
168
277
|
return
|
|
169
278
|
if storage.last_dependency_stack_version == storage.stack_version:
|
|
170
279
|
last_dependency = storage.last_dependency
|
|
@@ -181,11 +290,10 @@ class DependencyTracker:
|
|
|
181
290
|
storage.seen_dependencies_stack_version = storage.stack_version
|
|
182
291
|
elif dependency in storage.seen_dependencies:
|
|
183
292
|
return
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
dep_set.add(dependency)
|
|
293
|
+
for dep_set in storage.dependencies:
|
|
294
|
+
dep_set.add(dependency)
|
|
295
|
+
if storage.captures:
|
|
296
|
+
storage.captures[-1].add(dependency)
|
|
189
297
|
storage.last_dependency = dependency
|
|
190
298
|
storage.last_dependency_stack_version = storage.stack_version
|
|
191
299
|
storage.seen_dependencies.add(dependency)
|
|
@@ -193,15 +301,42 @@ class DependencyTracker:
|
|
|
193
301
|
@staticmethod
|
|
194
302
|
def _track_many_validated(dependencies: Iterable[Dependency]) -> None:
|
|
195
303
|
"""Record already-validated dependency tuples in active collectors."""
|
|
196
|
-
|
|
304
|
+
storage = _dependency_storage
|
|
305
|
+
if not storage.dependencies and not storage.captures:
|
|
306
|
+
return
|
|
307
|
+
if type(dependencies) in (tuple, frozenset):
|
|
308
|
+
if storage.dependencies:
|
|
309
|
+
for dep_set in storage.dependencies:
|
|
310
|
+
dep_set.update(dependencies)
|
|
311
|
+
if storage.captures:
|
|
312
|
+
storage.captures[-1].attach(snapshot_from_dependencies(dependencies))
|
|
197
313
|
return
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
314
|
+
frozen_dependencies = tuple(dependencies)
|
|
315
|
+
for dep_set in storage.dependencies:
|
|
316
|
+
dep_set.update(frozen_dependencies)
|
|
317
|
+
if storage.captures:
|
|
318
|
+
storage.captures[-1].attach(snapshot_from_dependencies(frozen_dependencies))
|
|
319
|
+
|
|
320
|
+
@staticmethod
|
|
321
|
+
def _capture() -> _DependencyCaptureScope:
|
|
322
|
+
"""Create a private graph capture scope for cache implementations."""
|
|
323
|
+
return _DependencyCaptureScope()
|
|
324
|
+
|
|
325
|
+
@staticmethod
|
|
326
|
+
def _attach_snapshot(snapshot: DependencySnapshot) -> None:
|
|
327
|
+
"""Attach cached graph metadata without flattening private parents."""
|
|
328
|
+
storage = _dependency_storage
|
|
329
|
+
if storage.captures:
|
|
330
|
+
storage.captures[-1].attach(snapshot)
|
|
331
|
+
if storage.dependencies:
|
|
332
|
+
dependencies = materialize_dependencies(snapshot)
|
|
333
|
+
for dep_set in storage.dependencies:
|
|
334
|
+
dep_set.update(dependencies)
|
|
335
|
+
|
|
336
|
+
@staticmethod
|
|
337
|
+
def _materialize_snapshot(snapshot: DependencySnapshot) -> set[Dependency]:
|
|
338
|
+
"""Expose one trusted mutable publication set for a snapshot boundary."""
|
|
339
|
+
return _CapturedDependencySet(materialize_dependencies(snapshot))
|
|
205
340
|
|
|
206
341
|
@staticmethod
|
|
207
342
|
def _dependencies_are_tracker_captured(dependencies: object) -> bool:
|
|
@@ -211,7 +346,7 @@ class DependencyTracker:
|
|
|
211
346
|
@staticmethod
|
|
212
347
|
def is_active() -> bool:
|
|
213
348
|
"""Return whether dependency tracking is active for this execution context."""
|
|
214
|
-
return _dependency_storage.
|
|
349
|
+
return bool(_dependency_storage.dependencies or _dependency_storage.captures)
|
|
215
350
|
|
|
216
351
|
@staticmethod
|
|
217
352
|
def reset_thread_local_storage() -> None:
|
{generalmanager-0.80.0 → generalmanager-0.80.2}/src/general_manager/cache/dependency_cache.py
RENAMED
|
@@ -3,11 +3,16 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from collections.abc import Iterable, Mapping
|
|
6
|
-
from dataclasses import dataclass
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
7
|
from hashlib import sha256
|
|
8
8
|
from typing import Protocol, TypeGuard, cast
|
|
9
9
|
|
|
10
10
|
from general_manager.cache.cache_tracker import DependencyTracker
|
|
11
|
+
from general_manager.cache._dependency_graph import (
|
|
12
|
+
DependencySnapshot,
|
|
13
|
+
empty_dependency_snapshot,
|
|
14
|
+
snapshot_from_dependencies,
|
|
15
|
+
)
|
|
11
16
|
from general_manager.cache.dependency_index import Dependency
|
|
12
17
|
|
|
13
18
|
DEPENDENCY_CACHE_ENTRY_VERSION = 2
|
|
@@ -131,11 +136,41 @@ class DependencyCacheHit:
|
|
|
131
136
|
|
|
132
137
|
value: object
|
|
133
138
|
dependencies: frozenset[Dependency]
|
|
139
|
+
_dependency_root: DependencySnapshot | None = field(
|
|
140
|
+
init=False,
|
|
141
|
+
repr=False,
|
|
142
|
+
compare=False,
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
def __post_init__(self) -> None:
|
|
146
|
+
"""Freeze caller-supplied metadata before retaining a graph leaf."""
|
|
147
|
+
dependencies = frozenset(self.dependencies)
|
|
148
|
+
object.__setattr__(self, "dependencies", dependencies)
|
|
149
|
+
object.__setattr__(
|
|
150
|
+
self,
|
|
151
|
+
"_dependency_root",
|
|
152
|
+
snapshot_from_dependencies(dependencies) if dependencies else None,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
@property
|
|
156
|
+
def dependency_root(self) -> DependencySnapshot:
|
|
157
|
+
"""Return this hit's immutable dependency leaf."""
|
|
158
|
+
return self._dependency_root or empty_dependency_snapshot()
|
|
134
159
|
|
|
135
160
|
|
|
136
161
|
class _TrustedDependencyCacheHit(DependencyCacheHit):
|
|
137
162
|
"""Cache hit whose dependencies were captured by DependencyTracker."""
|
|
138
163
|
|
|
164
|
+
__slots__ = ()
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def _trusted_dependency_cache_hit(
|
|
168
|
+
value: object,
|
|
169
|
+
dependencies: frozenset[Dependency],
|
|
170
|
+
) -> DependencyCacheHit:
|
|
171
|
+
"""Build an in-process hit whose frozen graph may be attached directly."""
|
|
172
|
+
return _TrustedDependencyCacheHit(value=value, dependencies=dependencies)
|
|
173
|
+
|
|
139
174
|
|
|
140
175
|
class DependencyCacheBackend(Protocol):
|
|
141
176
|
"""Minimal cache backend shape for dependency-cache reads and writes."""
|
|
@@ -482,7 +517,7 @@ def replay_dependency_cache_hit(hit: DependencyCacheHit) -> None:
|
|
|
482
517
|
tuple uses an unsupported operation.
|
|
483
518
|
"""
|
|
484
519
|
if isinstance(hit, _TrustedDependencyCacheHit):
|
|
485
|
-
DependencyTracker.
|
|
520
|
+
DependencyTracker._attach_snapshot(hit.dependency_root)
|
|
486
521
|
return
|
|
487
522
|
for class_name, operation, identifier in hit.dependencies:
|
|
488
523
|
DependencyTracker.track(class_name, operation, identifier)
|
|
@@ -158,13 +158,17 @@ class ModelDependencyCollector:
|
|
|
158
158
|
Returns:
|
|
159
159
|
None
|
|
160
160
|
"""
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
for attr_val in inner_self.__dict__.values():
|
|
164
|
-
for dependency_tuple in ModelDependencyCollector.collect(attr_val):
|
|
165
|
-
dependencies.add(dependency_tuple)
|
|
161
|
+
for dependency in ModelDependencyCollector._iter_args(args, kwargs):
|
|
162
|
+
dependencies.add(dependency)
|
|
166
163
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
164
|
+
@staticmethod
|
|
165
|
+
def _iter_args(
|
|
166
|
+
args: tuple[object, ...],
|
|
167
|
+
kwargs: Mapping[str, object],
|
|
168
|
+
) -> Iterator[Dependency]:
|
|
169
|
+
"""Yield argument dependencies using the public ``add_args`` order."""
|
|
170
|
+
if args and isinstance(args[0], GeneralManager):
|
|
171
|
+
for attr_val in args[0].__dict__.values():
|
|
172
|
+
yield from ModelDependencyCollector.collect(attr_val)
|
|
173
|
+
yield from ModelDependencyCollector.collect(args)
|
|
174
|
+
yield from ModelDependencyCollector.collect(kwargs)
|