GeneralManager 0.60.3__tar.gz → 0.60.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {generalmanager-0.60.3/src/GeneralManager.egg-info → generalmanager-0.60.5}/PKG-INFO +1 -1
- {generalmanager-0.60.3 → generalmanager-0.60.5}/pyproject.toml +1 -1
- {generalmanager-0.60.3 → generalmanager-0.60.5/src/GeneralManager.egg-info}/PKG-INFO +1 -1
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/system_prompt.py +15 -10
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/measurement/measurement.py +78 -7
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/utils/path_mapping.py +225 -73
- {generalmanager-0.60.3 → generalmanager-0.60.5}/LICENSE +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/README.md +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/setup.cfg +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/GeneralManager.egg-info/SOURCES.txt +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/GeneralManager.egg-info/dependency_links.txt +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/GeneralManager.egg-info/requires.txt +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/GeneralManager.egg-info/top_level.txt +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/_types/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/_types/api.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/_types/bucket.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/_types/cache.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/_types/dataframes.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/_types/factory.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/_types/general_manager.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/_types/interface.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/_types/manager.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/_types/measurement.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/_types/permission.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/_types/rule.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/_types/search.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/_types/utils.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/api/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/api/graphql.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/api/graphql_errors.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/api/graphql_mutations.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/api/graphql_prefetch.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/api/graphql_resolvers.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/api/graphql_search.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/api/graphql_subscription_consumer.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/api/graphql_subscriptions.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/api/graphql_view.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/api/graphql_warmup.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/api/graphql_warmup_registry.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/api/graphql_warmup_tasks.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/api/mutation.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/api/property.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/api/registry.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/api/remote_api.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/api/remote_invalidation.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/api/remote_invalidation_client.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/apps.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/bootstrap.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/bucket/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/bucket/base_bucket.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/bucket/calculation_bucket.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/bucket/database_bucket.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/bucket/group_bucket.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/bucket/indexing.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/bucket/request_bucket.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/cache/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/cache/cache_decorator.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/cache/cache_tracker.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/cache/dependency_cache.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/cache/dependency_index.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/cache/dependency_matching.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/cache/dependency_publish.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/cache/dependency_shards.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/cache/model_dependency_collector.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/cache/run_context.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/cache/signals.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/audit.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/bootstrap.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/checks.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/consumer.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/errors.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/evals/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/evals/__main__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/evals/baseline.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/evals/diagnostics.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/evals/fingerprints.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/evals/fixtures.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/evals/judges/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/evals/judges/answer_quality.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/evals/judges/contract.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/evals/judges/result_accuracy.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/evals/judges/tool_sequence.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/evals/readiness.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/evals/runner.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/evals/traces.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/grounding.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/models.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/providers/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/providers/_shared.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/providers/anthropic.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/providers/base.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/providers/google.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/providers/ollama.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/providers/openai.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/rate_limits.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/routing.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/schema_index.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/settings.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/signals.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/tool_metadata.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/tools.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/chat/views.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/conf.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/dataframes/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/dataframes/measurements.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/factory/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/factory/auto_factory.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/factory/factories.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/factory/factory_methods.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/base_interface.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/bundles/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/bundles/calculation.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/bundles/database.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/bundles/remote_manager.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/bundles/request.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/base.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/builtin.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/calculation/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/calculation/_compat.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/calculation/lifecycle.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/configuration.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/core/observability.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/core/utils.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/exceptions.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/existing_model/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/existing_model/_compat.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/existing_model/resolution.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/factory.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/orm/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/orm/_compat.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/orm/history.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/orm/lifecycle.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/orm/mutations.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/orm/support.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/orm_utils/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/orm_utils/django_manager_utils.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/orm_utils/field_descriptors.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/orm_utils/payload_normalizer.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/read_only/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/read_only/_compat.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/read_only/_types.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/read_only/lifecycle.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/read_only/management.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/registry.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/remote_manager.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/capabilities/request/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/infrastructure/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/infrastructure/startup_hooks.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/infrastructure/system_checks.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/interfaces/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/interfaces/calculation.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/interfaces/database.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/interfaces/existing_model.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/interfaces/read_only.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/interfaces/remote_manager.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/interfaces/request.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/manifests/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/manifests/capability_builder.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/manifests/capability_manifest.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/manifests/capability_models.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/orm_interface.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/requests.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/utils/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/utils/database_interface_protocols.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/utils/errors.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/interface/utils/models.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/logging.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/management/commands/chat_cleanup.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/management/commands/graphql_warmup.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/management/commands/graphql_warmup_refresh_due.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/management/commands/search_index.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/management/commands/search_reconcile.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/management/commands/seed_manager_landscape.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/management/commands/shell.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/management/commands/workflow_drain_outbox.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/management/commands/workflow_replay_dead_letters.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/manager/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/manager/general_manager.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/manager/group_manager.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/manager/input.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/manager/meta.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/measurement/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/measurement/measurement_field.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/metrics/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/metrics/graphql.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/migrations/0001_initial.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/migrations/0002_workflow_outbox_scaling_indexes.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/migrations/0003_workflow_execution_correlation_constraint.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/migrations/0004_chat_persistence_models.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/migrations/0004_search_index_state.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/migrations/0005_merge_chat_search.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/migrations/0006_chat_pending_confirmation_scoped_ids.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/migrations/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/models.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/permission/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/permission/audit.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/permission/base_permission.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/permission/graphql_capabilities.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/permission/manager_based_permission.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/permission/mutation_permission.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/permission/permission_checks.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/permission/permission_data_manager.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/permission/utils.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/public_api_registry.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/py.typed +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/rule/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/rule/handler.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/rule/rule.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/search/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/search/async_tasks.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/search/backend.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/search/backend_registry.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/search/backends/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/search/backends/dev.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/search/backends/meilisearch.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/search/backends/opensearch.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/search/backends/typesense.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/search/config.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/search/indexer.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/search/models.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/search/reconciliation.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/search/registry.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/search/tasks.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/search/utils.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/seeding/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/seeding/manager_landscape.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/utils/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/utils/args_to_kwargs.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/utils/filter_parser.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/utils/format_string.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/utils/json_encoder.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/utils/make_cache_key.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/utils/none_to_zero.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/utils/public_api.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/utils/testing.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/utils/type_checks.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/workflow/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/workflow/actions.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/workflow/backend_registry.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/workflow/backends/__init__.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/workflow/backends/celery.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/workflow/backends/local.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/workflow/backends/n8n.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/workflow/config.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/workflow/engine.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/workflow/event_registry.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/workflow/events.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/workflow/models.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/workflow/signal_bridge.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/workflow/tasks.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/workflow/telemetry.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/tests/test_settings.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/tests/test_urls.py +0 -0
- {generalmanager-0.60.3 → generalmanager-0.60.5}/tests/testing_asgi.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GeneralManager
|
|
3
|
-
Version: 0.60.
|
|
3
|
+
Version: 0.60.5
|
|
4
4
|
Summary: Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching.
|
|
5
5
|
Author-email: Tim Kleindick <tkleindick@yahoo.de>
|
|
6
6
|
License: MIT License
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "GeneralManager"
|
|
7
|
-
version = "0.60.
|
|
7
|
+
version = "0.60.5"
|
|
8
8
|
description = "Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{ name = "Tim Kleindick", email = "tkleindick@yahoo.de" }]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GeneralManager
|
|
3
|
-
Version: 0.60.
|
|
3
|
+
Version: 0.60.5
|
|
4
4
|
Summary: Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching.
|
|
5
5
|
Author-email: Tim Kleindick <tkleindick@yahoo.de>
|
|
6
6
|
License: MIT License
|
|
@@ -255,16 +255,21 @@ def _relationship_lines(
|
|
|
255
255
|
index: dict[str, dict[str, object]], manager_names: list[str]
|
|
256
256
|
) -> list[str]:
|
|
257
257
|
relationship_lines: list[str] = []
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
)
|
|
258
|
+
exposed_names = [name for name in manager_names if name in index]
|
|
259
|
+
if len(exposed_names) > PROMPT_MANAGER_DETAIL_LIMIT:
|
|
260
|
+
# Bound lazy path resolution to avoid reintroducing CPU-bound O(n^2) work.
|
|
261
|
+
return relationship_lines
|
|
262
|
+
for from_manager in exposed_names:
|
|
263
|
+
path_map = PathMap(from_manager)
|
|
264
|
+
for to_manager in exposed_names:
|
|
265
|
+
if from_manager == to_manager:
|
|
266
|
+
continue
|
|
267
|
+
tracer = path_map.to(to_manager)
|
|
268
|
+
path = getattr(tracer, "path", None) if tracer is not None else None
|
|
269
|
+
if path:
|
|
270
|
+
relationship_lines.append(
|
|
271
|
+
f"{from_manager} -> {to_manager}: {' -> '.join(path)}"
|
|
272
|
+
)
|
|
268
273
|
return relationship_lines
|
|
269
274
|
|
|
270
275
|
|
{generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/measurement/measurement.py
RENAMED
|
@@ -91,6 +91,7 @@ def _unit_uses_offset_for_unit_string(unit: str) -> bool:
|
|
|
91
91
|
return False
|
|
92
92
|
|
|
93
93
|
|
|
94
|
+
@lru_cache(maxsize=512)
|
|
94
95
|
def _pint_unit_components(unit: str) -> tuple[tuple[str, object], ...]:
|
|
95
96
|
"""Return Pint unit component names and powers for one unit expression."""
|
|
96
97
|
|
|
@@ -98,6 +99,13 @@ def _pint_unit_components(unit: str) -> tuple[tuple[str, object], ...]:
|
|
|
98
99
|
return tuple(parsed_unit._units.items())
|
|
99
100
|
|
|
100
101
|
|
|
102
|
+
@lru_cache(maxsize=512)
|
|
103
|
+
def _unit_dimensionality(unit: str) -> object:
|
|
104
|
+
"""Return Pint dimensionality metadata for one unit expression."""
|
|
105
|
+
|
|
106
|
+
return _parse_unit(unit).dimensionality
|
|
107
|
+
|
|
108
|
+
|
|
101
109
|
def _pint_unit_component_uses_offset(unit_name: str) -> bool:
|
|
102
110
|
"""Return whether a Pint unit component has offset conversion semantics."""
|
|
103
111
|
|
|
@@ -187,12 +195,12 @@ def _convert_quantity(
|
|
|
187
195
|
return source_quantity.to(target_unit)
|
|
188
196
|
|
|
189
197
|
|
|
198
|
+
@lru_cache(maxsize=512)
|
|
190
199
|
def _currency_component(unit: str) -> tuple[str, int] | None:
|
|
191
200
|
"""Return the single configured currency component in a unit expression."""
|
|
192
201
|
|
|
193
|
-
parsed_unit = ureg.parse_units(str(unit))
|
|
194
202
|
currency_components: list[tuple[str, int]] = []
|
|
195
|
-
for unit_name, power in
|
|
203
|
+
for unit_name, power in _pint_unit_components(unit):
|
|
196
204
|
currency_power = _integer_unit_power(power)
|
|
197
205
|
if currency_power is not None and unit_name in currency_units:
|
|
198
206
|
currency_components.append((unit_name, currency_power))
|
|
@@ -213,13 +221,69 @@ def _integer_unit_power(power: object) -> int | None:
|
|
|
213
221
|
return None
|
|
214
222
|
|
|
215
223
|
|
|
224
|
+
@lru_cache(maxsize=512)
|
|
216
225
|
def _unit_without_currency(unit: str, currency: str, power: int) -> str:
|
|
217
226
|
"""Return a unit expression with one currency component removed."""
|
|
218
227
|
|
|
219
|
-
stripped_unit =
|
|
228
|
+
stripped_unit = _parse_unit(unit) / (_parse_unit(currency) ** power)
|
|
220
229
|
return str(stripped_unit)
|
|
221
230
|
|
|
222
231
|
|
|
232
|
+
def _is_implicit_cross_currency_conversion(
|
|
233
|
+
source_unit: str,
|
|
234
|
+
target_unit: str,
|
|
235
|
+
) -> bool:
|
|
236
|
+
"""Return whether a conversion would require an explicit exchange rate."""
|
|
237
|
+
|
|
238
|
+
source_currency = _currency_component(source_unit)
|
|
239
|
+
target_currency = _currency_component(target_unit)
|
|
240
|
+
return (
|
|
241
|
+
source_currency is not None
|
|
242
|
+
and target_currency is not None
|
|
243
|
+
and source_currency[0] != target_currency[0]
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
@lru_cache(maxsize=1024)
|
|
248
|
+
def _multiplicative_conversion_factor(
|
|
249
|
+
source_unit: str,
|
|
250
|
+
target_unit: str,
|
|
251
|
+
) -> Decimal | None:
|
|
252
|
+
"""Return a cached Decimal factor for safe multiplicative conversions."""
|
|
253
|
+
|
|
254
|
+
try:
|
|
255
|
+
if (
|
|
256
|
+
_unit_uses_offset_for_unit_string(source_unit)
|
|
257
|
+
or _unit_uses_offset_for_unit_string(target_unit)
|
|
258
|
+
or _is_implicit_cross_currency_conversion(source_unit, target_unit)
|
|
259
|
+
):
|
|
260
|
+
return None
|
|
261
|
+
converted_quantity = ureg.Quantity(
|
|
262
|
+
Decimal("1"),
|
|
263
|
+
_parse_unit(source_unit),
|
|
264
|
+
).to(_parse_unit(target_unit))
|
|
265
|
+
except pint.errors.PintError:
|
|
266
|
+
return None
|
|
267
|
+
return _decimal_from_magnitude(converted_quantity.magnitude)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def _cached_multiplicative_conversion_factor(
|
|
271
|
+
source_unit: str,
|
|
272
|
+
target_unit: str,
|
|
273
|
+
) -> Decimal | None:
|
|
274
|
+
"""Return a cached factor keyed by canonical source and target units."""
|
|
275
|
+
|
|
276
|
+
try:
|
|
277
|
+
source_canonical_unit = _canonical_unit_string(source_unit)
|
|
278
|
+
target_canonical_unit = _canonical_unit_string(target_unit)
|
|
279
|
+
except pint.errors.PintError:
|
|
280
|
+
return None
|
|
281
|
+
return _multiplicative_conversion_factor(
|
|
282
|
+
source_canonical_unit,
|
|
283
|
+
target_canonical_unit,
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
|
|
223
287
|
def convert_magnitude(value: Decimal, source_unit: str, target_unit: str) -> Decimal:
|
|
224
288
|
"""
|
|
225
289
|
Convert a magnitude between units while keeping offset-unit math away from Decimal.
|
|
@@ -230,6 +294,13 @@ def convert_magnitude(value: Decimal, source_unit: str, target_unit: str) -> Dec
|
|
|
230
294
|
round-trip back to ``Decimal`` via ``str``.
|
|
231
295
|
"""
|
|
232
296
|
|
|
297
|
+
conversion_factor = _cached_multiplicative_conversion_factor(
|
|
298
|
+
source_unit,
|
|
299
|
+
target_unit,
|
|
300
|
+
)
|
|
301
|
+
if conversion_factor is not None:
|
|
302
|
+
return _decimal_from_magnitude(value * conversion_factor)
|
|
303
|
+
|
|
233
304
|
converted_quantity = _convert_quantity(
|
|
234
305
|
_build_quantity(value, source_unit), target_unit
|
|
235
306
|
)
|
|
@@ -830,10 +901,10 @@ class Measurement:
|
|
|
830
901
|
)
|
|
831
902
|
elif not self.is_currency() and not other.is_currency():
|
|
832
903
|
# Both are physical units
|
|
904
|
+
if _unit_dimensionality(left_unit) != _unit_dimensionality(right_unit):
|
|
905
|
+
raise IncompatibleUnitsError("addition")
|
|
833
906
|
left_quantity = self.__current_quantity()
|
|
834
907
|
right_quantity = other.__current_quantity()
|
|
835
|
-
if left_quantity.dimensionality != right_quantity.dimensionality:
|
|
836
|
-
raise IncompatibleUnitsError("addition")
|
|
837
908
|
left_quantity, right_quantity = _prepare_quantities_for_binary_operation(
|
|
838
909
|
left_quantity,
|
|
839
910
|
right_quantity,
|
|
@@ -883,10 +954,10 @@ class Measurement:
|
|
|
883
954
|
return Measurement(Decimal(str(result_quantity.magnitude)), str(self.unit))
|
|
884
955
|
elif not self.is_currency() and not other.is_currency():
|
|
885
956
|
# Both are physical units
|
|
957
|
+
if _unit_dimensionality(left_unit) != _unit_dimensionality(right_unit):
|
|
958
|
+
raise IncompatibleUnitsError("subtraction")
|
|
886
959
|
left_quantity = self.__current_quantity()
|
|
887
960
|
right_quantity = other.__current_quantity()
|
|
888
|
-
if left_quantity.dimensionality != right_quantity.dimensionality:
|
|
889
|
-
raise IncompatibleUnitsError("subtraction")
|
|
890
961
|
left_quantity, right_quantity = _prepare_quantities_for_binary_operation(
|
|
891
962
|
left_quantity,
|
|
892
963
|
right_quantity,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Utilities for tracing relationships between GeneralManager classes."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
|
+
from collections import deque
|
|
4
5
|
from collections.abc import Mapping
|
|
5
6
|
from typing import ClassVar, cast, get_args
|
|
6
7
|
from general_manager.manager.meta import GeneralManagerMeta
|
|
@@ -12,6 +13,8 @@ from general_manager.manager.general_manager import GeneralManager
|
|
|
12
13
|
|
|
13
14
|
type PathStart = str
|
|
14
15
|
type PathDestination = str
|
|
16
|
+
type PathEdge = tuple[str, PathDestination]
|
|
17
|
+
type PathClassEdge = tuple[str, type[GeneralManager]]
|
|
15
18
|
type TraversalValue = GeneralManager | Bucket[GeneralManager]
|
|
16
19
|
|
|
17
20
|
|
|
@@ -36,47 +39,196 @@ class InvalidPathTraversalValueError(TypeError):
|
|
|
36
39
|
)
|
|
37
40
|
|
|
38
41
|
|
|
42
|
+
def _as_manager_class(value: object) -> type[GeneralManager] | None:
|
|
43
|
+
"""Return value when it is a GeneralManager subclass."""
|
|
44
|
+
if value is None or not isinstance(value, type):
|
|
45
|
+
return None
|
|
46
|
+
if not issubclass(value, GeneralManager):
|
|
47
|
+
return None
|
|
48
|
+
return value
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _iter_manager_connections(
|
|
52
|
+
manager_class: type[GeneralManager],
|
|
53
|
+
) -> list[tuple[str, type[GeneralManager]]]:
|
|
54
|
+
"""Return traversable manager edges declared by interface fields and GraphQL properties."""
|
|
55
|
+
current_connections: dict[str, object] = {}
|
|
56
|
+
for attr_name, attr_value in manager_class.Interface.get_attribute_types().items():
|
|
57
|
+
if isinstance(attr_value, Mapping):
|
|
58
|
+
current_connections[attr_name] = attr_value.get("type")
|
|
59
|
+
seen_attrs: set[str] = set()
|
|
60
|
+
for mro_class in manager_class.__mro__:
|
|
61
|
+
for attr_name, attr_value in mro_class.__dict__.items():
|
|
62
|
+
if attr_name in seen_attrs:
|
|
63
|
+
continue
|
|
64
|
+
seen_attrs.add(attr_name)
|
|
65
|
+
if not isinstance(attr_value, GraphQLProperty):
|
|
66
|
+
continue
|
|
67
|
+
type_hints = get_args(attr_value.graphql_type_hint)
|
|
68
|
+
field_type = (
|
|
69
|
+
type_hints[0]
|
|
70
|
+
if type_hints
|
|
71
|
+
else cast(type[object], attr_value.graphql_type_hint)
|
|
72
|
+
)
|
|
73
|
+
current_connections[attr_name] = field_type
|
|
74
|
+
|
|
75
|
+
connections: list[tuple[str, type[GeneralManager]]] = []
|
|
76
|
+
for attr_name, attr_type in current_connections.items():
|
|
77
|
+
manager_type = _as_manager_class(attr_type)
|
|
78
|
+
if manager_type is not None:
|
|
79
|
+
connections.append((attr_name, manager_type))
|
|
80
|
+
return connections
|
|
81
|
+
|
|
82
|
+
|
|
39
83
|
class PathMap:
|
|
40
84
|
"""
|
|
41
85
|
Maintain cached traversal paths between GeneralManager classes.
|
|
42
86
|
|
|
43
|
-
The class-level mapping stores
|
|
44
|
-
start/destination class-name
|
|
45
|
-
when the classes are known but no route exists.
|
|
87
|
+
The class-level mapping stores lazily resolved PathTracer objects for
|
|
88
|
+
requested start/destination class-name pairs. A cached tracer may have
|
|
89
|
+
``path is None`` when the classes are known but no route exists.
|
|
46
90
|
"""
|
|
47
91
|
|
|
48
92
|
instance: PathMap
|
|
49
93
|
mapping: ClassVar[dict[tuple[PathStart, PathDestination], PathTracer]] = {}
|
|
94
|
+
_registry_signature: ClassVar[tuple[type[GeneralManager], ...]] = ()
|
|
95
|
+
_classes_by_name: ClassVar[dict[str, type[GeneralManager]]] = {}
|
|
96
|
+
_adjacency: ClassVar[dict[PathStart, tuple[PathEdge, ...]]] = {}
|
|
97
|
+
_class_adjacency: ClassVar[
|
|
98
|
+
dict[type[GeneralManager], tuple[PathClassEdge, ...]]
|
|
99
|
+
] = {}
|
|
50
100
|
|
|
51
101
|
def __new__(cls, *args: object, **kwargs: object) -> PathMap:
|
|
52
102
|
"""
|
|
53
|
-
Obtain the singleton PathMap,
|
|
103
|
+
Obtain the singleton PathMap, refreshing graph metadata on each construction.
|
|
54
104
|
|
|
55
105
|
Returns:
|
|
56
106
|
PathMap: The singleton PathMap instance.
|
|
57
107
|
"""
|
|
108
|
+
force_refresh = False
|
|
58
109
|
if not hasattr(cls, "instance"):
|
|
59
110
|
cls.instance = super().__new__(cls)
|
|
60
|
-
cls.
|
|
111
|
+
force_refresh = not cls.mapping
|
|
112
|
+
cls._ensure_graph_current(force=force_refresh)
|
|
61
113
|
return cls.instance
|
|
62
114
|
|
|
63
115
|
@classmethod
|
|
64
116
|
def create_path_mapping(cls) -> None:
|
|
65
117
|
"""
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
The generated tracers capture the attribute sequence needed to navigate from the start class to the destination class and are cached on the singleton instance.
|
|
118
|
+
Refresh path graph metadata without eagerly creating all pair tracers.
|
|
69
119
|
|
|
70
120
|
Returns:
|
|
71
121
|
None
|
|
72
122
|
"""
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
123
|
+
cls._ensure_graph_current(force=True)
|
|
124
|
+
|
|
125
|
+
@classmethod
|
|
126
|
+
def _ensure_graph_current(cls, *, force: bool = False) -> None:
|
|
127
|
+
"""Refresh class and adjacency caches when the manager registry changes."""
|
|
128
|
+
registry_signature = tuple(GeneralManagerMeta.all_classes)
|
|
129
|
+
if not force and cls._registry_signature == registry_signature:
|
|
130
|
+
return
|
|
131
|
+
|
|
132
|
+
cls._registry_signature = registry_signature
|
|
133
|
+
cls._classes_by_name = {
|
|
134
|
+
manager_class.__name__: manager_class
|
|
135
|
+
for manager_class in registry_signature
|
|
136
|
+
}
|
|
137
|
+
cls._class_adjacency = {
|
|
138
|
+
manager_class: tuple(_iter_manager_connections(manager_class))
|
|
139
|
+
for manager_class in registry_signature
|
|
140
|
+
}
|
|
141
|
+
cls._adjacency = {
|
|
142
|
+
manager_class.__name__: tuple(
|
|
143
|
+
(attr, target_class.__name__)
|
|
144
|
+
for attr, target_class in cls._class_adjacency[manager_class]
|
|
145
|
+
)
|
|
146
|
+
for manager_class in registry_signature
|
|
147
|
+
}
|
|
148
|
+
cls.mapping.clear()
|
|
149
|
+
|
|
150
|
+
@classmethod
|
|
151
|
+
def _edges_for_class(
|
|
152
|
+
cls,
|
|
153
|
+
manager_class: type[GeneralManager],
|
|
154
|
+
) -> tuple[PathClassEdge, ...]:
|
|
155
|
+
"""Return cached outgoing edges for registered or discovered manager classes."""
|
|
156
|
+
edges = cls._class_adjacency.get(manager_class)
|
|
157
|
+
if edges is not None:
|
|
158
|
+
return edges
|
|
159
|
+
|
|
160
|
+
edges = tuple(_iter_manager_connections(manager_class))
|
|
161
|
+
cls._class_adjacency[manager_class] = edges
|
|
162
|
+
cls._adjacency.setdefault(
|
|
163
|
+
manager_class.__name__,
|
|
164
|
+
tuple((attr, target_class.__name__) for attr, target_class in edges),
|
|
165
|
+
)
|
|
166
|
+
return edges
|
|
167
|
+
|
|
168
|
+
@classmethod
|
|
169
|
+
def _find_path(
|
|
170
|
+
cls,
|
|
171
|
+
start_class_name: PathStart,
|
|
172
|
+
destination_class_name: PathDestination,
|
|
173
|
+
) -> list[str] | None:
|
|
174
|
+
"""Find the shortest attribute path between two registered managers."""
|
|
175
|
+
if start_class_name == destination_class_name:
|
|
176
|
+
return []
|
|
177
|
+
|
|
178
|
+
start_class = cls._classes_by_name.get(start_class_name)
|
|
179
|
+
destination_class = cls._classes_by_name.get(destination_class_name)
|
|
180
|
+
if start_class is None or destination_class is None:
|
|
181
|
+
return None
|
|
182
|
+
|
|
183
|
+
visited = {start_class}
|
|
184
|
+
queue: deque[tuple[type[GeneralManager], list[str]]] = deque(
|
|
185
|
+
[(start_class, [])]
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
while queue:
|
|
189
|
+
current_class, current_path = queue.popleft()
|
|
190
|
+
for attr, next_class in cls._edges_for_class(current_class):
|
|
191
|
+
if next_class in visited:
|
|
192
|
+
continue
|
|
193
|
+
next_path = [*current_path, attr]
|
|
194
|
+
if next_class == destination_class:
|
|
195
|
+
return next_path
|
|
196
|
+
visited.add(next_class)
|
|
197
|
+
queue.append((next_class, next_path))
|
|
198
|
+
|
|
199
|
+
return None
|
|
200
|
+
|
|
201
|
+
@staticmethod
|
|
202
|
+
def _destination_name(
|
|
203
|
+
path_destination: PathDestination | type[GeneralManager] | str,
|
|
204
|
+
) -> PathDestination:
|
|
205
|
+
"""Return the class-name key for a path destination input."""
|
|
206
|
+
if isinstance(path_destination, type):
|
|
207
|
+
return path_destination.__name__
|
|
208
|
+
return path_destination
|
|
209
|
+
|
|
210
|
+
def _get_or_create_tracer(
|
|
211
|
+
self,
|
|
212
|
+
destination_class_name: PathDestination,
|
|
213
|
+
) -> PathTracer | None:
|
|
214
|
+
"""Return the cached tracer for one pair, computing only that pair when needed."""
|
|
215
|
+
if self.start_class_name == destination_class_name:
|
|
216
|
+
return None
|
|
217
|
+
|
|
218
|
+
key = (self.start_class_name, destination_class_name)
|
|
219
|
+
tracer = self.mapping.get(key)
|
|
220
|
+
if tracer is not None:
|
|
221
|
+
return tracer
|
|
222
|
+
|
|
223
|
+
start_class = self._classes_by_name.get(self.start_class_name)
|
|
224
|
+
destination_class = self._classes_by_name.get(destination_class_name)
|
|
225
|
+
if start_class is None or destination_class is None:
|
|
226
|
+
return None
|
|
227
|
+
|
|
228
|
+
path = self._find_path(self.start_class_name, destination_class_name)
|
|
229
|
+
tracer = PathTracer(start_class, destination_class, path, search=False)
|
|
230
|
+
self.mapping[key] = tracer
|
|
231
|
+
return tracer
|
|
80
232
|
|
|
81
233
|
def __init__(
|
|
82
234
|
self,
|
|
@@ -113,23 +265,18 @@ class PathMap:
|
|
|
113
265
|
"""
|
|
114
266
|
Retrieve the cached path tracer from the start class to the desired destination.
|
|
115
267
|
|
|
116
|
-
``None`` means
|
|
117
|
-
|
|
118
|
-
|
|
268
|
+
``None`` means either the start or destination class name is not
|
|
269
|
+
registered, or the requested pair uses the same start and destination
|
|
270
|
+
class. A non-``None`` tracer can still be unreachable; inspect
|
|
271
|
+
``tracer.path`` for ``None`` before treating it as a usable route.
|
|
119
272
|
|
|
120
273
|
Parameters:
|
|
121
274
|
path_destination (PathDestination | type[GeneralManager] | str): Target manager identifier, either as a manager class or string class name. Destination instances are not accepted.
|
|
122
275
|
|
|
123
276
|
Returns:
|
|
124
|
-
PathTracer | None: The cached tracer for the registered class-name pair, or None when no mapping key
|
|
277
|
+
PathTracer | None: The cached tracer for the registered class-name pair, or None when no mapping key can be created.
|
|
125
278
|
"""
|
|
126
|
-
|
|
127
|
-
path_destination = path_destination.__name__
|
|
128
|
-
|
|
129
|
-
tracer = self.mapping.get((self.start_class_name, path_destination), None)
|
|
130
|
-
if not tracer:
|
|
131
|
-
return None
|
|
132
|
-
return tracer
|
|
279
|
+
return self._get_or_create_tracer(self._destination_name(path_destination))
|
|
133
280
|
|
|
134
281
|
def go_to(
|
|
135
282
|
self, path_destination: PathDestination | type[GeneralManager] | str
|
|
@@ -137,11 +284,11 @@ class PathMap:
|
|
|
137
284
|
"""
|
|
138
285
|
Traverse the cached path from the configured start to the given destination.
|
|
139
286
|
|
|
140
|
-
The lookup
|
|
141
|
-
tracers with ``path is None`` return ``None``. A tracer
|
|
142
|
-
path also returns ``None`` because no traversal is
|
|
143
|
-
traversable path exists but this PathMap was created from
|
|
144
|
-
string start, MissingStartInstanceError is raised.
|
|
287
|
+
The lookup lazily resolves and caches the requested tracer. Missing
|
|
288
|
+
tracer keys and tracers with ``path is None`` return ``None``. A tracer
|
|
289
|
+
with an empty path also returns ``None`` because no traversal is
|
|
290
|
+
required. If a traversable path exists but this PathMap was created from
|
|
291
|
+
a class or string start, MissingStartInstanceError is raised.
|
|
145
292
|
|
|
146
293
|
Parameters:
|
|
147
294
|
path_destination (PathDestination | type[GeneralManager] | str): Destination specified as a manager class or string class name. Destination instances are not accepted.
|
|
@@ -152,10 +299,7 @@ class PathMap:
|
|
|
152
299
|
Raises:
|
|
153
300
|
MissingStartInstanceError: If the cached path requires a concrete start instance but the PathMap was constructed without one.
|
|
154
301
|
"""
|
|
155
|
-
|
|
156
|
-
path_destination = path_destination.__name__
|
|
157
|
-
|
|
158
|
-
tracer = self.mapping.get((self.start_class_name, path_destination), None)
|
|
302
|
+
tracer = self._get_or_create_tracer(self._destination_name(path_destination))
|
|
159
303
|
if not tracer:
|
|
160
304
|
return None
|
|
161
305
|
if not tracer.path:
|
|
@@ -166,18 +310,29 @@ class PathMap:
|
|
|
166
310
|
|
|
167
311
|
def get_all_connected(self) -> set[str]:
|
|
168
312
|
"""
|
|
169
|
-
Return the set of destination class names
|
|
313
|
+
Return the set of destination class names reachable from the configured start.
|
|
170
314
|
|
|
171
315
|
Returns:
|
|
172
316
|
set[str]: Destination class names reachable from the current start_class_name.
|
|
173
317
|
"""
|
|
318
|
+
start_class = self._classes_by_name.get(self.start_class_name)
|
|
319
|
+
if start_class is None:
|
|
320
|
+
return set()
|
|
321
|
+
|
|
174
322
|
connected_classes: set[str] = set()
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
323
|
+
visited = {start_class}
|
|
324
|
+
queue: deque[type[GeneralManager]] = deque([start_class])
|
|
325
|
+
|
|
326
|
+
while queue:
|
|
327
|
+
current_class = queue.popleft()
|
|
328
|
+
for _attr, next_class in self._edges_for_class(current_class):
|
|
329
|
+
if next_class in visited:
|
|
179
330
|
continue
|
|
180
|
-
|
|
331
|
+
visited.add(next_class)
|
|
332
|
+
if self._classes_by_name.get(next_class.__name__) is next_class:
|
|
333
|
+
connected_classes.add(next_class.__name__)
|
|
334
|
+
queue.append(next_class)
|
|
335
|
+
|
|
181
336
|
return connected_classes
|
|
182
337
|
|
|
183
338
|
|
|
@@ -191,7 +346,12 @@ class PathTracer:
|
|
|
191
346
|
"""
|
|
192
347
|
|
|
193
348
|
def __init__(
|
|
194
|
-
self,
|
|
349
|
+
self,
|
|
350
|
+
start_class: type[GeneralManager],
|
|
351
|
+
destination_class: type[GeneralManager],
|
|
352
|
+
path: list[str] | None = None,
|
|
353
|
+
*,
|
|
354
|
+
search: bool = True,
|
|
195
355
|
) -> None:
|
|
196
356
|
"""
|
|
197
357
|
Initialise a path tracer between two manager classes.
|
|
@@ -199,63 +359,55 @@ class PathTracer:
|
|
|
199
359
|
Parameters:
|
|
200
360
|
start_class (type[GeneralManager]): Origin manager class where traversal begins.
|
|
201
361
|
destination_class (type[GeneralManager]): Target manager class to reach.
|
|
362
|
+
path (list[str] | None): Precomputed path used by lazy PathMap lookup when search is False.
|
|
363
|
+
search (bool): Whether to compute the path during construction.
|
|
202
364
|
|
|
203
365
|
Returns:
|
|
204
366
|
None
|
|
205
367
|
"""
|
|
206
368
|
self.start_class = start_class
|
|
207
369
|
self.destination_class = destination_class
|
|
208
|
-
if
|
|
209
|
-
self.path
|
|
370
|
+
if not search:
|
|
371
|
+
self.path = path
|
|
372
|
+
elif self.start_class == self.destination_class:
|
|
373
|
+
self.path = []
|
|
210
374
|
else:
|
|
211
|
-
self.path = self.create_path(start_class, [])
|
|
375
|
+
self.path = self.create_path(start_class, [], {start_class})
|
|
212
376
|
|
|
213
377
|
def create_path(
|
|
214
|
-
self,
|
|
378
|
+
self,
|
|
379
|
+
current_manager: type[GeneralManager],
|
|
380
|
+
path: list[str],
|
|
381
|
+
visited_managers: set[type[GeneralManager]] | None = None,
|
|
215
382
|
) -> list[str] | None:
|
|
216
383
|
"""
|
|
217
384
|
Recursively compute the traversal path from `current_manager` to the destination class.
|
|
218
385
|
|
|
219
386
|
Candidate edges come from `Interface.get_attribute_types()` entries that
|
|
220
387
|
expose a `type` key and from `@GraphQLProperty` return annotations. Only
|
|
221
|
-
GeneralManager subclasses are traversed.
|
|
222
|
-
|
|
223
|
-
class to avoid cycles.
|
|
388
|
+
GeneralManager subclasses are traversed. Each manager class is expanded
|
|
389
|
+
at most once, which bounds missing-path and cyclic graph searches.
|
|
224
390
|
|
|
225
391
|
Parameters:
|
|
226
392
|
current_manager (type[GeneralManager]): Manager class used as the current traversal node.
|
|
227
393
|
path (list[str]): Sequence of attribute names accumulated along the traversal.
|
|
394
|
+
visited_managers (set[type[GeneralManager]] | None): Manager classes already expanded during this search.
|
|
228
395
|
|
|
229
396
|
Returns:
|
|
230
397
|
list[str] | None: Updated list of attribute names leading to the destination, or None if no route exists.
|
|
231
398
|
"""
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
if isinstance(attr_value, Mapping):
|
|
238
|
-
current_connections[attr_name] = attr_value.get("type")
|
|
239
|
-
for attr_name, attr_value in current_manager.__dict__.items():
|
|
240
|
-
if not isinstance(attr_value, GraphQLProperty):
|
|
241
|
-
continue
|
|
242
|
-
type_hints = get_args(attr_value.graphql_type_hint)
|
|
243
|
-
field_type = (
|
|
244
|
-
type_hints[0]
|
|
245
|
-
if type_hints
|
|
246
|
-
else cast(type[object], attr_value.graphql_type_hint)
|
|
247
|
-
)
|
|
248
|
-
current_connections[attr_name] = field_type
|
|
249
|
-
for attr, attr_type in current_connections.items():
|
|
250
|
-
if attr in path or attr_type == self.start_class:
|
|
251
|
-
continue
|
|
252
|
-
if attr_type is None or not isinstance(attr_type, type):
|
|
253
|
-
continue
|
|
254
|
-
if not issubclass(attr_type, GeneralManager):
|
|
399
|
+
if visited_managers is None:
|
|
400
|
+
visited_managers = {current_manager}
|
|
401
|
+
|
|
402
|
+
for attr, attr_type in _iter_manager_connections(current_manager):
|
|
403
|
+
if attr_type == self.start_class:
|
|
255
404
|
continue
|
|
256
405
|
if attr_type == self.destination_class:
|
|
257
406
|
return [*path, attr]
|
|
258
|
-
|
|
407
|
+
if attr_type in visited_managers:
|
|
408
|
+
continue
|
|
409
|
+
visited_managers.add(attr_type)
|
|
410
|
+
result = self.create_path(attr_type, [*path, attr], visited_managers)
|
|
259
411
|
if result:
|
|
260
412
|
return result
|
|
261
413
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{generalmanager-0.60.3 → generalmanager-0.60.5}/src/GeneralManager.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{generalmanager-0.60.3 → generalmanager-0.60.5}/src/general_manager/_types/general_manager.py
RENAMED
|
File without changes
|