GeneralManager 0.63.0__tar.gz → 0.63.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.63.0/src/GeneralManager.egg-info → generalmanager-0.63.2}/PKG-INFO +1 -1
- {generalmanager-0.63.0 → generalmanager-0.63.2}/pyproject.toml +1 -3
- {generalmanager-0.63.0 → generalmanager-0.63.2/src/GeneralManager.egg-info}/PKG-INFO +1 -1
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/GeneralManager.egg-info/SOURCES.txt +1 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/existing_model/resolution.py +31 -4
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/orm/__init__.py +3 -1
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/orm/_compat.py +2 -2
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/orm/mutations.py +70 -27
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/orm/support.py +35 -8
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/interfaces/existing_model.py +9 -7
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/utils/errors.py +12 -0
- generalmanager-0.63.2/src/general_manager/interface/utils/history.py +139 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/utils/models.py +3 -2
- {generalmanager-0.63.0 → generalmanager-0.63.2}/LICENSE +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/README.md +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/setup.cfg +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/GeneralManager.egg-info/dependency_links.txt +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/GeneralManager.egg-info/requires.txt +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/GeneralManager.egg-info/top_level.txt +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/_types/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/_types/api.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/_types/bucket.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/_types/cache.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/_types/dataframes.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/_types/factory.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/_types/general_manager.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/_types/interface.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/_types/manager.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/_types/measurement.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/_types/permission.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/_types/rule.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/_types/search.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/_types/utils.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/graphql.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/graphql_errors.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/graphql_mutations.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/graphql_prefetch.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/graphql_resolvers.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/graphql_search.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/graphql_subscription_consumer.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/graphql_subscriptions.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/graphql_view.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/graphql_warmup.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/graphql_warmup_registry.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/graphql_warmup_tasks.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/mutation.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/property.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/registry.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/remote_api.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/remote_invalidation.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/remote_invalidation_client.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/apps.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/bootstrap.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/bucket/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/bucket/base_bucket.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/bucket/calculation_bucket.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/bucket/database_bucket.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/bucket/group_bucket.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/bucket/indexing.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/bucket/request_bucket.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/cache/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/cache/cache_decorator.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/cache/cache_tracker.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/cache/dependency_cache.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/cache/dependency_index.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/cache/dependency_matching.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/cache/dependency_publish.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/cache/dependency_shards.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/cache/model_dependency_collector.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/cache/run_context.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/cache/signals.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/audit.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/bootstrap.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/checks.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/consumer.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/errors.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/evals/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/evals/__main__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/evals/baseline.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/evals/datasets/basic_queries.yaml +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/evals/datasets/demo_readiness.yaml +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/evals/datasets/edge_cases.yaml +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/evals/datasets/follow_ups.yaml +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/evals/datasets/large_schema.yaml +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/evals/datasets/multi_hop.yaml +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/evals/diagnostics.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/evals/fingerprints.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/evals/fixtures.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/evals/judges/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/evals/judges/answer_quality.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/evals/judges/contract.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/evals/judges/result_accuracy.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/evals/judges/tool_sequence.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/evals/readiness.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/evals/runner.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/evals/traces.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/grounding.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/models.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/providers/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/providers/_shared.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/providers/anthropic.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/providers/base.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/providers/google.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/providers/ollama.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/providers/openai.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/rate_limits.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/routing.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/schema_index.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/settings.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/signals.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/system_prompt.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/tool_metadata.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/tools.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/chat/views.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/conf.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/dataframes/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/dataframes/measurements.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/factory/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/factory/auto_factory.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/factory/factories.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/factory/factory_methods.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/base_interface.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/bundles/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/bundles/calculation.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/bundles/database.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/bundles/remote_manager.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/bundles/request.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/base.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/builtin.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/calculation/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/calculation/_compat.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/calculation/lifecycle.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/configuration.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/core/observability.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/core/utils.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/exceptions.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/existing_model/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/existing_model/_compat.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/factory.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/orm/history.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/orm/lifecycle.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/orm_utils/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/orm_utils/django_manager_utils.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/orm_utils/field_descriptors.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/orm_utils/payload_normalizer.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/read_only/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/read_only/_compat.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/read_only/_types.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/read_only/lifecycle.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/read_only/management.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/registry.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/remote_manager.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/capabilities/request/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/infrastructure/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/infrastructure/startup_hooks.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/infrastructure/system_checks.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/interfaces/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/interfaces/calculation.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/interfaces/database.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/interfaces/read_only.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/interfaces/remote_manager.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/interfaces/request.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/manifests/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/manifests/capability_builder.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/manifests/capability_manifest.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/manifests/capability_models.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/orm_interface.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/requests.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/utils/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/utils/database_interface_protocols.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/logging.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/management/commands/chat_cleanup.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/management/commands/cleanup_upload_intents.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/management/commands/graphql_warmup.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/management/commands/graphql_warmup_refresh_due.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/management/commands/search_index.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/management/commands/search_reconcile.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/management/commands/seed_manager_landscape.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/management/commands/shell.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/management/commands/workflow_drain_outbox.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/management/commands/workflow_replay_dead_letters.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/manager/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/manager/general_manager.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/manager/group_manager.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/manager/input.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/manager/meta.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/measurement/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/measurement/measurement.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/measurement/measurement_field.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/metrics/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/metrics/graphql.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/migrations/0001_initial.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/migrations/0002_workflow_outbox_scaling_indexes.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/migrations/0003_workflow_execution_correlation_constraint.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/migrations/0004_chat_persistence_models.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/migrations/0004_search_index_state.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/migrations/0005_merge_chat_search.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/migrations/0006_chat_pending_confirmation_scoped_ids.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/migrations/0007_upload_intent.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/migrations/0008_upload_finalization_versions.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/migrations/0009_upload_cleanup_state.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/migrations/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/models.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/permission/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/permission/audit.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/permission/base_permission.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/permission/graphql_capabilities.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/permission/manager_based_permission.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/permission/mutation_permission.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/permission/permission_checks.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/permission/permission_data_manager.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/permission/utils.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/public_api_registry.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/py.typed +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/rule/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/rule/handler.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/rule/rule.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/search/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/search/async_tasks.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/search/backend.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/search/backend_registry.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/search/backends/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/search/backends/dev.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/search/backends/meilisearch.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/search/backends/opensearch.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/search/backends/typesense.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/search/config.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/search/indexer.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/search/models.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/search/reconciliation.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/search/registry.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/search/tasks.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/search/utils.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/seeding/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/seeding/manager_landscape.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/uploads/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/uploads/adapters.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/uploads/checks.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/uploads/config.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/uploads/errors.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/uploads/finalization.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/uploads/graphql.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/uploads/graphql_types.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/uploads/metrics.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/uploads/models.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/uploads/public.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/uploads/s3.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/uploads/services.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/uploads/tokens.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/uploads/types.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/uploads/urls.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/uploads/views.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/utils/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/utils/args_to_kwargs.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/utils/filter_parser.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/utils/format_string.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/utils/json_encoder.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/utils/make_cache_key.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/utils/none_to_zero.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/utils/path_mapping.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/utils/public_api.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/utils/testing.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/utils/type_checks.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/workflow/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/workflow/actions.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/workflow/backend_registry.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/workflow/backends/__init__.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/workflow/backends/celery.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/workflow/backends/local.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/workflow/backends/n8n.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/workflow/config.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/workflow/engine.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/workflow/event_registry.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/workflow/events.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/workflow/models.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/workflow/signal_bridge.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/workflow/tasks.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/workflow/telemetry.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/tests/test_settings.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/tests/test_urls.py +0 -0
- {generalmanager-0.63.0 → generalmanager-0.63.2}/tests/testing_asgi.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GeneralManager
|
|
3
|
-
Version: 0.63.
|
|
3
|
+
Version: 0.63.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.63.
|
|
7
|
+
version = "0.63.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" }]
|
|
@@ -93,8 +93,6 @@ major_on_zero = false
|
|
|
93
93
|
version_toml = ["pyproject.toml:project.version"]
|
|
94
94
|
branch = "main"
|
|
95
95
|
build_command = "python -m build"
|
|
96
|
-
upload_to_PyPI = true
|
|
97
|
-
upload_to_release = true
|
|
98
96
|
|
|
99
97
|
[tool.semantic_release.remote]
|
|
100
98
|
ignore_token_for_push = true
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GeneralManager
|
|
3
|
-
Version: 0.63.
|
|
3
|
+
Version: 0.63.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
|
|
@@ -173,6 +173,7 @@ src/general_manager/interface/manifests/capability_models.py
|
|
|
173
173
|
src/general_manager/interface/utils/__init__.py
|
|
174
174
|
src/general_manager/interface/utils/database_interface_protocols.py
|
|
175
175
|
src/general_manager/interface/utils/errors.py
|
|
176
|
+
src/general_manager/interface/utils/history.py
|
|
176
177
|
src/general_manager/interface/utils/models.py
|
|
177
178
|
src/general_manager/management/commands/chat_cleanup.py
|
|
178
179
|
src/general_manager/management/commands/cleanup_upload_intents.py
|
|
@@ -6,13 +6,18 @@ from dataclasses import dataclass
|
|
|
6
6
|
from typing import TYPE_CHECKING, ClassVar, cast
|
|
7
7
|
|
|
8
8
|
from django.apps import apps
|
|
9
|
-
from django.db import models
|
|
9
|
+
from django.db import DEFAULT_DB_ALIAS, models
|
|
10
10
|
from simple_history import register
|
|
11
11
|
|
|
12
12
|
from general_manager.factory.auto_factory import AutoFactory
|
|
13
13
|
from general_manager.interface.utils.errors import (
|
|
14
14
|
InvalidModelReferenceError,
|
|
15
15
|
MissingModelConfigurationError,
|
|
16
|
+
UnsafeHistoryConfigurationError,
|
|
17
|
+
)
|
|
18
|
+
from general_manager.interface.utils.history import (
|
|
19
|
+
DATABASE_AWARE_HISTORY_MARKER,
|
|
20
|
+
DatabaseAwareHistoricalRecords,
|
|
16
21
|
)
|
|
17
22
|
from general_manager.interface.utils.models import get_full_clean_methode
|
|
18
23
|
|
|
@@ -127,14 +132,36 @@ class ExistingModelResolutionCapability(BaseCapability):
|
|
|
127
132
|
|
|
128
133
|
def _perform() -> None:
|
|
129
134
|
"""
|
|
130
|
-
|
|
135
|
+
Ensure the captured model has history tracking compatible with its interface database alias.
|
|
131
136
|
|
|
132
|
-
|
|
137
|
+
An untracked model is registered with database-aware history and all local many-to-many fields. An existing tracker is accepted for the default alias; a non-default alias requires GeneralManager's database-aware marker and otherwise raises `UnsafeHistoryConfigurationError`.
|
|
133
138
|
"""
|
|
134
139
|
if hasattr(model._meta, "simple_history_manager_attribute"):
|
|
140
|
+
database_alias = (
|
|
141
|
+
getattr(interface_cls, "database", None) if interface_cls else None
|
|
142
|
+
)
|
|
143
|
+
if database_alias and database_alias != DEFAULT_DB_ALIAS:
|
|
144
|
+
assert interface_cls is not None
|
|
145
|
+
manager_name = model._meta.simple_history_manager_attribute
|
|
146
|
+
history_model = getattr(model, manager_name).model
|
|
147
|
+
if not getattr(
|
|
148
|
+
history_model,
|
|
149
|
+
DATABASE_AWARE_HISTORY_MARKER,
|
|
150
|
+
False,
|
|
151
|
+
):
|
|
152
|
+
raise UnsafeHistoryConfigurationError(
|
|
153
|
+
model.__name__,
|
|
154
|
+
interface_cls.__name__,
|
|
155
|
+
database_alias,
|
|
156
|
+
)
|
|
135
157
|
return
|
|
136
158
|
m2m_fields = [field.name for field in model._meta.local_many_to_many]
|
|
137
|
-
register(
|
|
159
|
+
register(
|
|
160
|
+
model,
|
|
161
|
+
m2m_fields=m2m_fields,
|
|
162
|
+
records_class=DatabaseAwareHistoricalRecords,
|
|
163
|
+
use_base_model_db=True,
|
|
164
|
+
)
|
|
138
165
|
|
|
139
166
|
target = interface_cls or model
|
|
140
167
|
return call_with_observability(
|
|
@@ -5,7 +5,9 @@ from __future__ import annotations
|
|
|
5
5
|
from general_manager.interface.capabilities.core.utils import (
|
|
6
6
|
with_observability as with_observability,
|
|
7
7
|
)
|
|
8
|
-
from
|
|
8
|
+
from general_manager.interface.utils.history import (
|
|
9
|
+
update_change_reason as update_change_reason,
|
|
10
|
+
)
|
|
9
11
|
|
|
10
12
|
from .history import HistoryNotSupportedError, OrmHistoryCapability
|
|
11
13
|
from .lifecycle import OrmLifecycleCapability
|
|
@@ -52,8 +52,8 @@ def call_update_change_reason(instance: models.Model, reason: str) -> None:
|
|
|
52
52
|
Delegate invocation to the package-level `update_change_reason` callable.
|
|
53
53
|
|
|
54
54
|
This resolves the callable from `general_manager.interface.capabilities.orm` at call time so that runtime patches to that attribute are respected.
|
|
55
|
-
The default package-level callable is
|
|
56
|
-
|
|
55
|
+
The default package-level callable is GeneralManager's database-aware
|
|
56
|
+
change-reason wrapper. If simple-history is absent from the model, if a
|
|
57
57
|
patched callable is missing expected behavior, or if the callable raises,
|
|
58
58
|
that exception propagates unchanged.
|
|
59
59
|
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from collections.abc import Iterator
|
|
6
|
+
from contextlib import contextmanager
|
|
7
|
+
from contextvars import ContextVar
|
|
5
8
|
from typing import TYPE_CHECKING, Any, ClassVar, cast
|
|
6
9
|
|
|
7
10
|
from django.contrib.auth import get_user_model
|
|
@@ -48,6 +51,21 @@ type MutationPayload = dict[str, object]
|
|
|
48
51
|
type ManyToManyPayload = dict[str, list[object]]
|
|
49
52
|
type MutationResult = dict[str, object]
|
|
50
53
|
|
|
54
|
+
_save_with_history_savepoint = ContextVar(
|
|
55
|
+
"save_with_history_savepoint",
|
|
56
|
+
default=True,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@contextmanager
|
|
61
|
+
def _without_save_with_history_savepoint() -> Iterator[None]:
|
|
62
|
+
"""Suppress the nested savepoint within an encompassing mutation atomic."""
|
|
63
|
+
token = _save_with_history_savepoint.set(False)
|
|
64
|
+
try:
|
|
65
|
+
yield
|
|
66
|
+
finally:
|
|
67
|
+
_save_with_history_savepoint.reset(token)
|
|
68
|
+
|
|
51
69
|
|
|
52
70
|
class OrmMutationCapability(BaseCapability):
|
|
53
71
|
"""Common utilities to modify ORM instances."""
|
|
@@ -156,11 +174,19 @@ class OrmMutationCapability(BaseCapability):
|
|
|
156
174
|
database_alias = support.get_database_alias(interface_cls)
|
|
157
175
|
if database_alias:
|
|
158
176
|
instance._state.db = database_alias
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
177
|
+
savepoint = _save_with_history_savepoint.get()
|
|
178
|
+
if database_alias:
|
|
179
|
+
atomic_context = (
|
|
180
|
+
transaction.atomic(using=database_alias)
|
|
181
|
+
if savepoint
|
|
182
|
+
else transaction.atomic(using=database_alias, savepoint=False)
|
|
183
|
+
)
|
|
184
|
+
else:
|
|
185
|
+
atomic_context = (
|
|
186
|
+
transaction.atomic()
|
|
187
|
+
if savepoint
|
|
188
|
+
else transaction.atomic(savepoint=False)
|
|
189
|
+
)
|
|
164
190
|
with atomic_context:
|
|
165
191
|
_assign_history_actor(
|
|
166
192
|
instance,
|
|
@@ -360,18 +386,27 @@ class OrmCreateCapability(BaseCapability):
|
|
|
360
386
|
instance = mutation.assign_simple_attributes(
|
|
361
387
|
interface_cls, interface_cls._model(), normalized_simple
|
|
362
388
|
)
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
mutation.apply_many_to_many(
|
|
370
|
-
interface_cls,
|
|
371
|
-
instance,
|
|
372
|
-
many_to_many_kwargs=normalized_many,
|
|
373
|
-
history_comment=history_comment,
|
|
389
|
+
support = get_support_capability(interface_cls)
|
|
390
|
+
database_alias = support.get_database_alias(interface_cls)
|
|
391
|
+
atomic_context = (
|
|
392
|
+
transaction.atomic(using=database_alias)
|
|
393
|
+
if database_alias
|
|
394
|
+
else transaction.atomic()
|
|
374
395
|
)
|
|
396
|
+
with atomic_context:
|
|
397
|
+
with _without_save_with_history_savepoint():
|
|
398
|
+
pk = mutation.save_with_history(
|
|
399
|
+
interface_cls,
|
|
400
|
+
instance,
|
|
401
|
+
creator_id=creator_id,
|
|
402
|
+
history_comment=history_comment,
|
|
403
|
+
)
|
|
404
|
+
mutation.apply_many_to_many(
|
|
405
|
+
interface_cls,
|
|
406
|
+
instance,
|
|
407
|
+
many_to_many_kwargs=normalized_many,
|
|
408
|
+
history_comment=history_comment,
|
|
409
|
+
)
|
|
375
410
|
return {"id": pk}
|
|
376
411
|
|
|
377
412
|
return call_with_observability(
|
|
@@ -502,19 +537,27 @@ class OrmUpdateCapability(BaseCapability):
|
|
|
502
537
|
instance = mutation.assign_simple_attributes(
|
|
503
538
|
interface_instance.__class__, instance, normalized_simple
|
|
504
539
|
)
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
540
|
+
database_alias = support.get_database_alias(interface_instance.__class__)
|
|
541
|
+
atomic_context = (
|
|
542
|
+
transaction.atomic(using=database_alias)
|
|
543
|
+
if database_alias
|
|
544
|
+
else transaction.atomic()
|
|
510
545
|
)
|
|
546
|
+
with atomic_context:
|
|
547
|
+
with _without_save_with_history_savepoint():
|
|
548
|
+
pk = mutation.save_with_history(
|
|
549
|
+
interface_instance.__class__,
|
|
550
|
+
instance,
|
|
551
|
+
creator_id=creator_id,
|
|
552
|
+
history_comment=history_comment,
|
|
553
|
+
)
|
|
554
|
+
mutation.apply_many_to_many(
|
|
555
|
+
interface_instance.__class__,
|
|
556
|
+
instance,
|
|
557
|
+
many_to_many_kwargs=normalized_many,
|
|
558
|
+
history_comment=history_comment,
|
|
559
|
+
)
|
|
511
560
|
discard_orm_instance_cache(interface_instance.__class__, pk)
|
|
512
|
-
mutation.apply_many_to_many(
|
|
513
|
-
interface_instance.__class__,
|
|
514
|
-
instance,
|
|
515
|
-
many_to_many_kwargs=normalized_many,
|
|
516
|
-
history_comment=history_comment,
|
|
517
|
-
)
|
|
518
561
|
return {"id": pk}
|
|
519
562
|
|
|
520
563
|
return call_with_observability(
|
|
@@ -9,7 +9,7 @@ from functools import lru_cache
|
|
|
9
9
|
from typing import TYPE_CHECKING, Any, Callable, ClassVar, Type, cast
|
|
10
10
|
|
|
11
11
|
from django.core.exceptions import FieldDoesNotExist
|
|
12
|
-
from django.db import models
|
|
12
|
+
from django.db import DEFAULT_DB_ALIAS, connections, models
|
|
13
13
|
from django.db.models import Subquery
|
|
14
14
|
from django.utils import timezone
|
|
15
15
|
from general_manager.bucket.database_bucket import DatabaseBucket
|
|
@@ -303,14 +303,22 @@ class OrmReadCapability(BaseCapability):
|
|
|
303
303
|
raise model_cls.DoesNotExist
|
|
304
304
|
|
|
305
305
|
context = current_calculation_run_context()
|
|
306
|
-
|
|
307
|
-
_perform
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
306
|
+
if context is None:
|
|
307
|
+
read_func = _perform
|
|
308
|
+
else:
|
|
309
|
+
interface_cls = interface_instance.__class__
|
|
310
|
+
support = get_support_capability(interface_cls)
|
|
311
|
+
database_alias = (
|
|
312
|
+
support.get_database_alias(interface_cls) or DEFAULT_DB_ALIAS
|
|
313
|
+
)
|
|
314
|
+
read_func = (
|
|
315
|
+
_perform
|
|
316
|
+
if _connection_has_application_atomic_block(database_alias)
|
|
317
|
+
else lambda: context.get_or_set(
|
|
318
|
+
_orm_instance_cache_key(interface_instance),
|
|
319
|
+
_perform,
|
|
320
|
+
)
|
|
312
321
|
)
|
|
313
|
-
)
|
|
314
322
|
|
|
315
323
|
return call_with_observability(
|
|
316
324
|
interface_instance,
|
|
@@ -1072,6 +1080,25 @@ def _orm_instance_cache_key(
|
|
|
1072
1080
|
)
|
|
1073
1081
|
|
|
1074
1082
|
|
|
1083
|
+
def _connection_has_application_atomic_block(database_alias: str) -> bool:
|
|
1084
|
+
"""Return whether a connection is inside a non-TestCase atomic block."""
|
|
1085
|
+
connection = connections[database_alias]
|
|
1086
|
+
try:
|
|
1087
|
+
blocks = getattr(connection, "atomic_blocks") # noqa: B009
|
|
1088
|
+
except (AttributeError, TypeError):
|
|
1089
|
+
return bool(getattr(connection, "in_atomic_block", False))
|
|
1090
|
+
if not isinstance(blocks, (list, tuple)) or not blocks:
|
|
1091
|
+
return bool(getattr(connection, "in_atomic_block", False))
|
|
1092
|
+
|
|
1093
|
+
def _is_testcase_wrapper(block: object) -> bool:
|
|
1094
|
+
try:
|
|
1095
|
+
return getattr(block, "_from_testcase") is True # noqa: B009
|
|
1096
|
+
except (AttributeError, TypeError):
|
|
1097
|
+
return False
|
|
1098
|
+
|
|
1099
|
+
return any(not _is_testcase_wrapper(block) for block in blocks)
|
|
1100
|
+
|
|
1101
|
+
|
|
1075
1102
|
def discard_orm_instance_cache(
|
|
1076
1103
|
interface_cls: OrmInterfaceClass,
|
|
1077
1104
|
pk: object,
|
|
@@ -28,13 +28,15 @@ class ExistingModelInterface(OrmInterfaceBase[ExistingModelT]):
|
|
|
28
28
|
string accepted by ``django.apps.apps.get_model()``, such as
|
|
29
29
|
``settings.AUTH_USER_MODEL``. During manager class creation the
|
|
30
30
|
``existing_model_resolution`` lifecycle capability resolves that reference,
|
|
31
|
-
caches the resolved model on the concrete interface, registers
|
|
32
|
-
needed, applies interface rules, and builds a
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
caches the resolved model on the concrete interface, auto-registers
|
|
32
|
+
database-aware history when needed, applies interface rules, and builds a
|
|
33
|
+
factory for the legacy model. Auto-registration includes local many-to-many
|
|
34
|
+
fields. A pre-registered tracker remains compatible on the default database;
|
|
35
|
+
on a configured non-default alias, its generated history model must carry
|
|
36
|
+
GeneralManager's database-aware marker or manager creation raises
|
|
37
|
+
``UnsafeHistoryConfigurationError``. Interface rules are the optional
|
|
38
|
+
``Meta.rules`` sequence on the interface. Soft delete is enabled when the
|
|
39
|
+
resolved model exposes an ``is_active`` attribute.
|
|
38
40
|
|
|
39
41
|
Construction and row loading are inherited from ``OrmInterfaceBase``: the
|
|
40
42
|
default public input is the wrapped row ``id`` parsed by ``Input(int)`` plus
|
{generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/utils/errors.py
RENAMED
|
@@ -16,6 +16,7 @@ __all__ = [
|
|
|
16
16
|
"MissingUniqueFieldError",
|
|
17
17
|
"ReadOnlyRelationLookupError",
|
|
18
18
|
"UnknownFieldError",
|
|
19
|
+
"UnsafeHistoryConfigurationError",
|
|
19
20
|
]
|
|
20
21
|
|
|
21
22
|
|
|
@@ -226,3 +227,14 @@ class InvalidModelReferenceError(TypeError):
|
|
|
226
227
|
`Invalid model reference '{reference}'.`
|
|
227
228
|
"""
|
|
228
229
|
super().__init__(f"Invalid model reference '{reference}'.")
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
class UnsafeHistoryConfigurationError(ValueError):
|
|
233
|
+
"""Raised when pre-registered history cannot follow an interface alias."""
|
|
234
|
+
|
|
235
|
+
def __init__(self, model_name: str, interface_name: str, alias: str) -> None:
|
|
236
|
+
"""Build guidance for replacing an unsafe simple-history tracker."""
|
|
237
|
+
super().__init__(
|
|
238
|
+
f"{model_name} must use DatabaseAwareHistoricalRecords before "
|
|
239
|
+
f"{interface_name} configures non-default database alias '{alias}'."
|
|
240
|
+
)
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"""Database-aware django-simple-history integration helpers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, cast
|
|
6
|
+
|
|
7
|
+
from django.db import DEFAULT_DB_ALIAS, models
|
|
8
|
+
from django.db.models.fields.related import ForeignKey
|
|
9
|
+
from simple_history import utils as simple_history_utils
|
|
10
|
+
from simple_history.models import HistoricalRecords
|
|
11
|
+
from simple_history.signals import (
|
|
12
|
+
post_create_historical_m2m_records,
|
|
13
|
+
pre_create_historical_m2m_records,
|
|
14
|
+
)
|
|
15
|
+
from simple_history.utils import get_history_manager_for_model
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
DATABASE_AWARE_HISTORY_MARKER = "_general_manager_database_aware_history"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class DatabaseAwareHistoricalRecords(HistoricalRecords): # type: ignore[misc]
|
|
22
|
+
"""Store generated history records on the base model's database alias."""
|
|
23
|
+
|
|
24
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
25
|
+
kwargs["use_base_model_db"] = True
|
|
26
|
+
super().__init__(*args, **kwargs)
|
|
27
|
+
|
|
28
|
+
def create_history_model(
|
|
29
|
+
self,
|
|
30
|
+
model: type[models.Model],
|
|
31
|
+
inherited: bool,
|
|
32
|
+
) -> type[models.Model]:
|
|
33
|
+
"""Mark the generated model as safe for non-default database aliases."""
|
|
34
|
+
history_model = cast(
|
|
35
|
+
type[models.Model],
|
|
36
|
+
super().create_history_model(model, inherited),
|
|
37
|
+
)
|
|
38
|
+
setattr(history_model, DATABASE_AWARE_HISTORY_MARKER, True)
|
|
39
|
+
return history_model
|
|
40
|
+
|
|
41
|
+
def create_historical_record(
|
|
42
|
+
self,
|
|
43
|
+
instance: models.Model,
|
|
44
|
+
history_type: str,
|
|
45
|
+
using: str | None = None,
|
|
46
|
+
) -> None:
|
|
47
|
+
"""Route base history even when an M2M signal omits ``using``."""
|
|
48
|
+
database_alias = using or instance._state.db or DEFAULT_DB_ALIAS
|
|
49
|
+
super().create_historical_record(
|
|
50
|
+
instance,
|
|
51
|
+
history_type,
|
|
52
|
+
using=database_alias,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
def create_historical_record_m2ms(
|
|
56
|
+
self,
|
|
57
|
+
history_instance: models.Model,
|
|
58
|
+
instance: models.Model,
|
|
59
|
+
) -> None:
|
|
60
|
+
"""Snapshot tracked many-to-many rows on the base instance alias."""
|
|
61
|
+
database_alias = instance._state.db or history_instance._state.db
|
|
62
|
+
database_alias = database_alias or DEFAULT_DB_ALIAS
|
|
63
|
+
history_fields = cast(
|
|
64
|
+
list[Any],
|
|
65
|
+
history_instance._history_m2m_fields, # type: ignore[attr-defined]
|
|
66
|
+
)
|
|
67
|
+
for field in history_fields:
|
|
68
|
+
m2m_history_model = self.m2m_models[field]
|
|
69
|
+
original_instance = history_instance.instance # type: ignore[attr-defined]
|
|
70
|
+
through_model = getattr(original_instance, field.name).through
|
|
71
|
+
through_model_field_names = [
|
|
72
|
+
model_field.name for model_field in through_model._meta.fields
|
|
73
|
+
]
|
|
74
|
+
through_model_fk_field_names = [
|
|
75
|
+
model_field.name
|
|
76
|
+
for model_field in through_model._meta.fields
|
|
77
|
+
if isinstance(model_field, ForeignKey)
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
through_field_name = simple_history_utils.get_m2m_field_name(field)
|
|
81
|
+
rows = through_model.objects.using(database_alias).filter(
|
|
82
|
+
**{through_field_name: instance}
|
|
83
|
+
)
|
|
84
|
+
rows = rows.select_related(*through_model_fk_field_names)
|
|
85
|
+
insert_rows = []
|
|
86
|
+
for row in rows:
|
|
87
|
+
insert_row = m2m_history_model(
|
|
88
|
+
history_id=history_instance.pk,
|
|
89
|
+
**{
|
|
90
|
+
field_name: getattr(row, field_name)
|
|
91
|
+
for field_name in through_model_field_names
|
|
92
|
+
},
|
|
93
|
+
)
|
|
94
|
+
insert_row._state.db = database_alias
|
|
95
|
+
insert_rows.append(insert_row)
|
|
96
|
+
|
|
97
|
+
pre_create_historical_m2m_records.send(
|
|
98
|
+
sender=m2m_history_model,
|
|
99
|
+
rows=insert_rows,
|
|
100
|
+
history_instance=history_instance,
|
|
101
|
+
instance=instance,
|
|
102
|
+
field=field,
|
|
103
|
+
)
|
|
104
|
+
created_rows = m2m_history_model.objects.using(database_alias).bulk_create(
|
|
105
|
+
insert_rows
|
|
106
|
+
)
|
|
107
|
+
post_create_historical_m2m_records.send(
|
|
108
|
+
sender=m2m_history_model,
|
|
109
|
+
created_rows=created_rows,
|
|
110
|
+
history_instance=history_instance,
|
|
111
|
+
instance=instance,
|
|
112
|
+
field=field,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def update_change_reason(instance: models.Model, reason: str) -> None:
|
|
117
|
+
"""Update the latest history row on the model instance's database alias."""
|
|
118
|
+
manager_owner: models.Model | type[models.Model]
|
|
119
|
+
manager_owner = instance if instance.pk is not None else type(instance)
|
|
120
|
+
history = get_history_manager_for_model(manager_owner)
|
|
121
|
+
database_alias = instance._state.db
|
|
122
|
+
if database_alias:
|
|
123
|
+
history = history.using(database_alias)
|
|
124
|
+
|
|
125
|
+
history_fields = {field.attname for field in history.model._meta.fields}
|
|
126
|
+
attrs: dict[str, object] = {}
|
|
127
|
+
for field in instance._meta.fields:
|
|
128
|
+
if field.attname not in history_fields:
|
|
129
|
+
continue
|
|
130
|
+
value = getattr(instance, field.attname)
|
|
131
|
+
if not field.primary_key or value is not None:
|
|
132
|
+
attrs[field.attname] = value
|
|
133
|
+
|
|
134
|
+
record = history.filter(**attrs).order_by("-history_date").first()
|
|
135
|
+
record.history_change_reason = reason
|
|
136
|
+
if database_alias:
|
|
137
|
+
record.save(using=database_alias)
|
|
138
|
+
else:
|
|
139
|
+
record.save()
|
{generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/interface/utils/models.py
RENAMED
|
@@ -7,9 +7,10 @@ from typing import TYPE_CHECKING, Callable, ClassVar, Protocol, TypeVar, cast
|
|
|
7
7
|
from django.db import models
|
|
8
8
|
from django.contrib.auth.models import AbstractBaseUser
|
|
9
9
|
from django.core.exceptions import FieldDoesNotExist
|
|
10
|
-
from simple_history.models import HistoricalRecords
|
|
11
10
|
from django.core.exceptions import ValidationError
|
|
12
11
|
|
|
12
|
+
from general_manager.interface.utils.history import DatabaseAwareHistoricalRecords
|
|
13
|
+
|
|
13
14
|
|
|
14
15
|
if TYPE_CHECKING:
|
|
15
16
|
from django.core.exceptions import ValidationErrorMessageArg
|
|
@@ -201,7 +202,7 @@ class GeneralManagerBasisModel(models.Model):
|
|
|
201
202
|
"""
|
|
202
203
|
|
|
203
204
|
_general_manager_class: ClassVar[type[GeneralManager]]
|
|
204
|
-
history =
|
|
205
|
+
history = DatabaseAwareHistoricalRecords(inherit=True)
|
|
205
206
|
|
|
206
207
|
class Meta:
|
|
207
208
|
abstract = True
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{generalmanager-0.63.0 → generalmanager-0.63.2}/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.63.0 → generalmanager-0.63.2}/src/general_manager/_types/general_manager.py
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
|
|
File without changes
|
{generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/graphql_mutations.py
RENAMED
|
File without changes
|
|
File without changes
|
{generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/graphql_resolvers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/graphql_subscriptions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/graphql_warmup_registry.py
RENAMED
|
File without changes
|
{generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/graphql_warmup_tasks.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{generalmanager-0.63.0 → generalmanager-0.63.2}/src/general_manager/api/remote_invalidation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|