GeneralManager 0.59.0__tar.gz → 0.59.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.59.0/src/GeneralManager.egg-info → generalmanager-0.59.2}/PKG-INFO +2 -2
- {generalmanager-0.59.0 → generalmanager-0.59.2}/pyproject.toml +2 -2
- {generalmanager-0.59.0 → generalmanager-0.59.2/src/GeneralManager.egg-info}/PKG-INFO +2 -2
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/GeneralManager.egg-info/requires.txt +1 -1
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/factory/auto_factory.py +86 -12
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/factory/factories.py +193 -58
- {generalmanager-0.59.0 → generalmanager-0.59.2}/LICENSE +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/README.md +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/setup.cfg +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/GeneralManager.egg-info/SOURCES.txt +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/GeneralManager.egg-info/dependency_links.txt +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/GeneralManager.egg-info/top_level.txt +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/_types/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/_types/api.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/_types/bucket.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/_types/cache.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/_types/factory.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/_types/general_manager.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/_types/interface.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/_types/manager.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/_types/measurement.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/_types/permission.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/_types/rule.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/_types/search.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/_types/utils.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/graphql.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/graphql_errors.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/graphql_mutations.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/graphql_prefetch.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/graphql_resolvers.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/graphql_search.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/graphql_subscription_consumer.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/graphql_subscriptions.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/graphql_view.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/graphql_warmup.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/graphql_warmup_registry.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/graphql_warmup_tasks.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/mutation.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/property.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/registry.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/remote_api.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/remote_invalidation.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/remote_invalidation_client.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/apps.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/bootstrap.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/bucket/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/bucket/base_bucket.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/bucket/calculation_bucket.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/bucket/database_bucket.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/bucket/group_bucket.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/bucket/indexing.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/bucket/request_bucket.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/cache/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/cache/cache_decorator.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/cache/cache_tracker.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/cache/dependency_cache.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/cache/dependency_index.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/cache/dependency_matching.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/cache/dependency_publish.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/cache/dependency_shards.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/cache/model_dependency_collector.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/cache/run_context.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/cache/signals.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/audit.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/bootstrap.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/checks.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/consumer.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/errors.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/evals/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/evals/__main__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/evals/baseline.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/evals/diagnostics.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/evals/fingerprints.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/evals/fixtures.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/evals/judges/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/evals/judges/answer_quality.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/evals/judges/contract.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/evals/judges/result_accuracy.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/evals/judges/tool_sequence.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/evals/readiness.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/evals/runner.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/evals/traces.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/grounding.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/models.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/providers/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/providers/_shared.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/providers/anthropic.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/providers/base.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/providers/google.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/providers/ollama.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/providers/openai.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/rate_limits.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/routing.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/schema_index.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/settings.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/signals.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/system_prompt.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/tool_metadata.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/tools.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/chat/views.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/conf.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/factory/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/factory/factory_methods.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/base_interface.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/bundles/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/bundles/calculation.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/bundles/database.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/bundles/remote_manager.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/bundles/request.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/base.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/builtin.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/calculation/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/calculation/_compat.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/calculation/lifecycle.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/configuration.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/core/observability.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/core/utils.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/exceptions.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/existing_model/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/existing_model/_compat.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/existing_model/resolution.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/factory.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/orm/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/orm/_compat.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/orm/history.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/orm/lifecycle.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/orm/mutations.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/orm/support.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/orm_utils/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/orm_utils/django_manager_utils.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/orm_utils/field_descriptors.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/orm_utils/payload_normalizer.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/read_only/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/read_only/_compat.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/read_only/_types.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/read_only/lifecycle.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/read_only/management.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/registry.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/remote_manager.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/capabilities/request/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/infrastructure/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/infrastructure/startup_hooks.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/infrastructure/system_checks.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/interfaces/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/interfaces/calculation.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/interfaces/database.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/interfaces/existing_model.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/interfaces/read_only.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/interfaces/remote_manager.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/interfaces/request.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/manifests/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/manifests/capability_builder.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/manifests/capability_manifest.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/manifests/capability_models.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/orm_interface.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/requests.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/utils/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/utils/database_interface_protocols.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/utils/errors.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/interface/utils/models.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/logging.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/management/commands/chat_cleanup.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/management/commands/graphql_warmup.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/management/commands/graphql_warmup_refresh_due.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/management/commands/search_index.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/management/commands/search_reconcile.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/management/commands/seed_manager_landscape.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/management/commands/shell.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/management/commands/workflow_drain_outbox.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/management/commands/workflow_replay_dead_letters.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/manager/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/manager/general_manager.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/manager/group_manager.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/manager/input.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/manager/meta.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/measurement/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/measurement/measurement.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/measurement/measurement_field.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/metrics/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/metrics/graphql.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/migrations/0001_initial.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/migrations/0002_workflow_outbox_scaling_indexes.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/migrations/0003_workflow_execution_correlation_constraint.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/migrations/0004_chat_persistence_models.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/migrations/0004_search_index_state.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/migrations/0005_merge_chat_search.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/migrations/0006_chat_pending_confirmation_scoped_ids.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/migrations/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/models.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/permission/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/permission/audit.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/permission/base_permission.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/permission/graphql_capabilities.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/permission/manager_based_permission.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/permission/mutation_permission.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/permission/permission_checks.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/permission/permission_data_manager.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/permission/utils.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/public_api_registry.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/py.typed +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/rule/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/rule/handler.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/rule/rule.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/search/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/search/async_tasks.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/search/backend.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/search/backend_registry.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/search/backends/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/search/backends/dev.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/search/backends/meilisearch.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/search/backends/opensearch.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/search/backends/typesense.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/search/config.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/search/indexer.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/search/models.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/search/reconciliation.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/search/registry.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/search/tasks.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/search/utils.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/seeding/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/seeding/manager_landscape.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/utils/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/utils/args_to_kwargs.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/utils/filter_parser.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/utils/format_string.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/utils/json_encoder.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/utils/make_cache_key.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/utils/none_to_zero.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/utils/path_mapping.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/utils/public_api.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/utils/testing.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/utils/type_checks.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/workflow/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/workflow/actions.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/workflow/backend_registry.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/workflow/backends/__init__.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/workflow/backends/celery.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/workflow/backends/local.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/workflow/backends/n8n.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/workflow/config.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/workflow/engine.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/workflow/event_registry.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/workflow/events.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/workflow/models.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/workflow/signal_bridge.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/workflow/tasks.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/workflow/telemetry.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/tests/test_settings.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/tests/test_urls.py +0 -0
- {generalmanager-0.59.0 → generalmanager-0.59.2}/tests/testing_asgi.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GeneralManager
|
|
3
|
-
Version: 0.59.
|
|
3
|
+
Version: 0.59.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
|
|
@@ -47,7 +47,7 @@ License-File: LICENSE
|
|
|
47
47
|
Requires-Dist: asgiref>=3.8.1
|
|
48
48
|
Requires-Dist: celery<6.0.0,>=5.3.6
|
|
49
49
|
Requires-Dist: channels>=4.1.0
|
|
50
|
-
Requires-Dist: Django>=5.2.
|
|
50
|
+
Requires-Dist: Django>=5.2.15
|
|
51
51
|
Requires-Dist: django-simple-history>=3.8.0
|
|
52
52
|
Requires-Dist: exrex>=0.12.0
|
|
53
53
|
Requires-Dist: factory_boy>=3.3.3
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "GeneralManager"
|
|
7
|
-
version = "0.59.
|
|
7
|
+
version = "0.59.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" }]
|
|
@@ -35,7 +35,7 @@ dependencies = [
|
|
|
35
35
|
"asgiref>=3.8.1",
|
|
36
36
|
"celery>=5.3.6,<6.0.0", # async search indexing (docs/concepts/search.md)
|
|
37
37
|
"channels>=4.1.0",
|
|
38
|
-
"Django>=5.2.
|
|
38
|
+
"Django>=5.2.15",
|
|
39
39
|
"django-simple-history>=3.8.0",
|
|
40
40
|
"exrex>=0.12.0",
|
|
41
41
|
"factory_boy>=3.3.3",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GeneralManager
|
|
3
|
-
Version: 0.59.
|
|
3
|
+
Version: 0.59.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
|
|
@@ -47,7 +47,7 @@ License-File: LICENSE
|
|
|
47
47
|
Requires-Dist: asgiref>=3.8.1
|
|
48
48
|
Requires-Dist: celery<6.0.0,>=5.3.6
|
|
49
49
|
Requires-Dist: channels>=4.1.0
|
|
50
|
-
Requires-Dist: Django>=5.2.
|
|
50
|
+
Requires-Dist: Django>=5.2.15
|
|
51
51
|
Requires-Dist: django-simple-history>=3.8.0
|
|
52
52
|
Requires-Dist: exrex>=0.12.0
|
|
53
53
|
Requires-Dist: factory_boy>=3.3.3
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Auto-generating factory utilities for GeneralManager models."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
|
-
from collections.abc import Callable
|
|
4
|
+
from collections.abc import Callable, Mapping
|
|
5
5
|
from typing import (
|
|
6
6
|
TYPE_CHECKING,
|
|
7
7
|
ClassVar,
|
|
@@ -15,6 +15,7 @@ from django.db import models
|
|
|
15
15
|
from django.db import transaction
|
|
16
16
|
from factory.django import DjangoModelFactory
|
|
17
17
|
from general_manager.factory.factories import (
|
|
18
|
+
RelationGenerationMode,
|
|
18
19
|
UnableToResolveManagerInstanceError,
|
|
19
20
|
get_field_value,
|
|
20
21
|
get_many_to_many_field_value,
|
|
@@ -115,6 +116,53 @@ class AutoFactory(DjangoModelFactory[modelsModel]):
|
|
|
115
116
|
|
|
116
117
|
interface: type[OrmInterfaceBase[models.Model]]
|
|
117
118
|
_adjustmentMethod: ClassVar[AdjustmentMethod | None] = None
|
|
119
|
+
_related_factory_mode: ClassVar[RelationGenerationMode] = "reuse_existing"
|
|
120
|
+
_related_factory_modes: ClassVar[Mapping[str, RelationGenerationMode]] = {}
|
|
121
|
+
|
|
122
|
+
def __init_subclass__(cls, **kwargs: object) -> None:
|
|
123
|
+
super().__init_subclass__(**kwargs)
|
|
124
|
+
cls._related_factory_modes = dict(cls._related_factory_modes)
|
|
125
|
+
|
|
126
|
+
@classmethod
|
|
127
|
+
def _setup_next_sequence(cls) -> int:
|
|
128
|
+
"""Initialize factory_boy sequences after existing persisted rows."""
|
|
129
|
+
model = cls._meta.model
|
|
130
|
+
try:
|
|
131
|
+
is_model = isinstance(model, type) and issubclass(model, models.Model)
|
|
132
|
+
except TypeError:
|
|
133
|
+
is_model = False
|
|
134
|
+
if not is_model:
|
|
135
|
+
return cls._factory_boy_next_sequence()
|
|
136
|
+
|
|
137
|
+
model_cls = cast(type[models.Model], model)
|
|
138
|
+
manager = model_cls._default_manager
|
|
139
|
+
database_alias = cls._get_database_alias()
|
|
140
|
+
if database_alias:
|
|
141
|
+
manager = manager.using(database_alias)
|
|
142
|
+
try:
|
|
143
|
+
count = manager.count()
|
|
144
|
+
except Exception: # noqa: BLE001
|
|
145
|
+
return cls._factory_boy_next_sequence()
|
|
146
|
+
return max(cls._factory_boy_next_sequence(), count)
|
|
147
|
+
|
|
148
|
+
@classmethod
|
|
149
|
+
def _factory_boy_next_sequence(cls) -> int:
|
|
150
|
+
"""Call factory_boy's untyped sequence initializer with a typed boundary."""
|
|
151
|
+
setup_next_sequence = cast(Callable[[], int], super()._setup_next_sequence)
|
|
152
|
+
return setup_next_sequence()
|
|
153
|
+
|
|
154
|
+
@classmethod
|
|
155
|
+
def _get_related_factory_mode(cls, field_name: str) -> RelationGenerationMode:
|
|
156
|
+
"""Return the relation generation mode configured for a model field."""
|
|
157
|
+
return cls._related_factory_modes.get(field_name, cls._related_factory_mode)
|
|
158
|
+
|
|
159
|
+
@classmethod
|
|
160
|
+
def _get_database_alias(cls) -> str | None:
|
|
161
|
+
"""Return the interface database alias, when the interface defines one."""
|
|
162
|
+
if not hasattr(cls.interface, "_get_database_alias"):
|
|
163
|
+
return None
|
|
164
|
+
database_alias = cls.interface._get_database_alias()
|
|
165
|
+
return database_alias or None
|
|
118
166
|
|
|
119
167
|
@classmethod
|
|
120
168
|
def _generate(
|
|
@@ -158,6 +206,8 @@ class AutoFactory(DjangoModelFactory[modelsModel]):
|
|
|
158
206
|
if not is_model:
|
|
159
207
|
raise InvalidAutoFactoryModelError
|
|
160
208
|
field_name_list, to_ignore_list = cls.interface.handle_custom_fields(model)
|
|
209
|
+
supplied_field_names = set(params)
|
|
210
|
+
database_alias = cls._get_database_alias()
|
|
161
211
|
|
|
162
212
|
fields = [
|
|
163
213
|
field
|
|
@@ -186,6 +236,16 @@ class AutoFactory(DjangoModelFactory[modelsModel]):
|
|
|
186
236
|
if declared_default is not None:
|
|
187
237
|
params[field.name] = declared_default
|
|
188
238
|
continue
|
|
239
|
+
if getattr(field, "is_relation", False) and (
|
|
240
|
+
getattr(field, "many_to_one", False)
|
|
241
|
+
or getattr(field, "one_to_one", False)
|
|
242
|
+
):
|
|
243
|
+
params[field.name] = get_field_value(
|
|
244
|
+
field,
|
|
245
|
+
relation_generation=cls._get_related_factory_mode(field.name),
|
|
246
|
+
database_alias=database_alias,
|
|
247
|
+
)
|
|
248
|
+
continue
|
|
189
249
|
params[field.name] = get_field_value(field)
|
|
190
250
|
|
|
191
251
|
generate = cast(
|
|
@@ -201,16 +261,23 @@ class AutoFactory(DjangoModelFactory[modelsModel]):
|
|
|
201
261
|
raise InvalidGeneratedObjectError()
|
|
202
262
|
if strategy == "create":
|
|
203
263
|
for item in obj:
|
|
204
|
-
cls._handle_many_to_many_fields_after_creation(
|
|
264
|
+
cls._handle_many_to_many_fields_after_creation(
|
|
265
|
+
item, params, supplied_field_names
|
|
266
|
+
)
|
|
205
267
|
elif strategy == "create":
|
|
206
|
-
cls._handle_many_to_many_fields_after_creation(
|
|
268
|
+
cls._handle_many_to_many_fields_after_creation(
|
|
269
|
+
obj, params, supplied_field_names
|
|
270
|
+
)
|
|
207
271
|
if strategy == "create":
|
|
208
272
|
return cls._wrap_generated_objects(obj)
|
|
209
273
|
return obj
|
|
210
274
|
|
|
211
275
|
@classmethod
|
|
212
276
|
def _handle_many_to_many_fields_after_creation(
|
|
213
|
-
cls,
|
|
277
|
+
cls,
|
|
278
|
+
obj: models.Model,
|
|
279
|
+
attrs: FactoryParams,
|
|
280
|
+
supplied_field_names: set[str] | None = None,
|
|
214
281
|
) -> None:
|
|
215
282
|
"""
|
|
216
283
|
Assign related objects to many-to-many fields after saved creation.
|
|
@@ -223,11 +290,20 @@ class AutoFactory(DjangoModelFactory[modelsModel]):
|
|
|
223
290
|
obj (models.Model): Instance whose many-to-many relations should be populated.
|
|
224
291
|
attrs: Original attributes passed to the factory.
|
|
225
292
|
"""
|
|
293
|
+
if supplied_field_names is None:
|
|
294
|
+
supplied_field_names = set(attrs)
|
|
226
295
|
for field in obj._meta.many_to_many:
|
|
227
|
-
|
|
296
|
+
relation_generation = cls._get_related_factory_mode(field.name)
|
|
297
|
+
if field.name in attrs and field.name in supplied_field_names:
|
|
228
298
|
m2m_values = attrs[field.name]
|
|
299
|
+
elif relation_generation == "reuse_existing" and field.blank:
|
|
300
|
+
continue
|
|
229
301
|
else:
|
|
230
|
-
m2m_values = get_many_to_many_field_value(
|
|
302
|
+
m2m_values = get_many_to_many_field_value(
|
|
303
|
+
field,
|
|
304
|
+
relation_generation=relation_generation,
|
|
305
|
+
database_alias=cls._get_database_alias(),
|
|
306
|
+
)
|
|
231
307
|
if m2m_values:
|
|
232
308
|
normalized_values = cls._coerce_many_to_many_values(m2m_values)
|
|
233
309
|
getattr(obj, field.name).set(normalized_values)
|
|
@@ -317,10 +393,10 @@ class AutoFactory(DjangoModelFactory[modelsModel]):
|
|
|
317
393
|
obj = model_class()
|
|
318
394
|
for field, value in kwargs.items():
|
|
319
395
|
setattr(obj, field, value)
|
|
396
|
+
database_alias = cls._get_database_alias()
|
|
397
|
+
if database_alias:
|
|
398
|
+
obj._state.db = database_alias
|
|
320
399
|
obj.full_clean()
|
|
321
|
-
database_alias: str | None = None
|
|
322
|
-
if hasattr(cls.interface, "_get_database_alias"):
|
|
323
|
-
database_alias = cls.interface._get_database_alias()
|
|
324
400
|
|
|
325
401
|
if database_alias:
|
|
326
402
|
obj.save(using=database_alias)
|
|
@@ -373,9 +449,7 @@ class AutoFactory(DjangoModelFactory[modelsModel]):
|
|
|
373
449
|
|
|
374
450
|
created_objects: list[models.Model] = []
|
|
375
451
|
if use_creation_method:
|
|
376
|
-
database_alias
|
|
377
|
-
if hasattr(cls.interface, "_get_database_alias"):
|
|
378
|
-
database_alias = cls.interface._get_database_alias()
|
|
452
|
+
database_alias = cls._get_database_alias()
|
|
379
453
|
with transaction.atomic(using=database_alias):
|
|
380
454
|
for record in records:
|
|
381
455
|
created_objects.append(cls._model_creation(model_cls, **record))
|
|
@@ -4,14 +4,14 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from collections.abc import Callable
|
|
6
6
|
import string
|
|
7
|
-
from typing import Protocol, cast
|
|
7
|
+
from typing import Any, Literal, Protocol, cast
|
|
8
8
|
|
|
9
9
|
from factory.declarations import LazyFunction
|
|
10
10
|
from factory.faker import Faker
|
|
11
11
|
import exrex
|
|
12
12
|
from django.apps import apps
|
|
13
13
|
from django.core.validators import RegexValidator
|
|
14
|
-
from django.db import models
|
|
14
|
+
from django.db import DatabaseError, models
|
|
15
15
|
from datetime import timezone
|
|
16
16
|
from decimal import Decimal
|
|
17
17
|
from random import SystemRandom
|
|
@@ -24,6 +24,7 @@ _RNG = SystemRandom()
|
|
|
24
24
|
_NO_DEFAULT = object()
|
|
25
25
|
type DjangoField = models.Field[object, object]
|
|
26
26
|
type RelatedFactory = Callable[[], object]
|
|
27
|
+
type RelationGenerationMode = Literal["reuse_existing", "create", "random"]
|
|
27
28
|
|
|
28
29
|
_LazyFunctionConstructor = cast(
|
|
29
30
|
Callable[[Callable[[], object]], LazyFunction],
|
|
@@ -137,6 +138,9 @@ class UnableToResolveManagerInstanceError(ValueError):
|
|
|
137
138
|
|
|
138
139
|
def get_field_value(
|
|
139
140
|
field: DjangoField | models.ForeignObjectRel,
|
|
141
|
+
*,
|
|
142
|
+
relation_generation: RelationGenerationMode = "reuse_existing",
|
|
143
|
+
database_alias: str | None = None,
|
|
140
144
|
) -> object:
|
|
141
145
|
"""
|
|
142
146
|
Generate a realistic sample value appropriate for the given Django model field or relation.
|
|
@@ -164,6 +168,10 @@ def get_field_value(
|
|
|
164
168
|
relation descriptor to generate a value for. Many-to-many fields are
|
|
165
169
|
accepted by the broad type shape but intentionally return `None`
|
|
166
170
|
here; pass them to `get_many_to_many_field_value()` instead.
|
|
171
|
+
relation_generation: Strategy for relation fields. Defaults to reusing
|
|
172
|
+
existing related rows before creating new related rows.
|
|
173
|
+
database_alias: Optional Django database alias used when querying
|
|
174
|
+
existing related rows.
|
|
167
175
|
|
|
168
176
|
Returns:
|
|
169
177
|
A value suitable for assignment to the field (scalar, string, Measurement-producing LazyFunction, model instance, LazyFunction that yields a related instance, or `None`).
|
|
@@ -173,14 +181,16 @@ def get_field_value(
|
|
|
173
181
|
MissingRelatedModelError: When a relational field does not declare a related model.
|
|
174
182
|
InvalidRelatedModelTypeError: When a relational field's related value is not a Django model class.
|
|
175
183
|
"""
|
|
184
|
+
field_is_relation = _is_relation_field(field)
|
|
176
185
|
if (
|
|
177
|
-
|
|
186
|
+
relation_generation != "create"
|
|
187
|
+
and getattr(field, "null", False)
|
|
178
188
|
and getattr(field, "default", _NO_DEFAULT) is None
|
|
179
|
-
and
|
|
189
|
+
and field_is_relation
|
|
180
190
|
):
|
|
181
191
|
return None
|
|
182
192
|
|
|
183
|
-
if field
|
|
193
|
+
if relation_generation != "create" and getattr(field, "null", False):
|
|
184
194
|
if _RNG.choice([True] + 9 * [False]):
|
|
185
195
|
return None
|
|
186
196
|
|
|
@@ -269,39 +279,65 @@ def get_field_value(
|
|
|
269
279
|
return _faker("text", max_nb_chars=max_length)
|
|
270
280
|
elif isinstance(field, models.OneToOneField):
|
|
271
281
|
related_model = get_related_model(field)
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
if
|
|
279
|
-
return
|
|
282
|
+
related_factory = (
|
|
283
|
+
_get_related_factory(related_model)
|
|
284
|
+
if hasattr(related_model, "_general_manager_class")
|
|
285
|
+
else None
|
|
286
|
+
)
|
|
287
|
+
if relation_generation == "create":
|
|
288
|
+
if related_factory is not None:
|
|
289
|
+
return _ensure_model_instance(related_factory())
|
|
280
290
|
if field.null:
|
|
281
291
|
return None
|
|
282
292
|
raise MissingFactoryOrInstancesError(related_model)
|
|
293
|
+
related_instances = _existing_related_instances(
|
|
294
|
+
field,
|
|
295
|
+
related_model,
|
|
296
|
+
database_alias=database_alias,
|
|
297
|
+
)
|
|
298
|
+
if related_instances:
|
|
299
|
+
return _lazy_existing_choice(related_instances)
|
|
300
|
+
if related_factory is not None:
|
|
301
|
+
return _ensure_model_instance(related_factory())
|
|
302
|
+
if field.null:
|
|
303
|
+
return None
|
|
304
|
+
raise MissingFactoryOrInstancesError(related_model)
|
|
283
305
|
elif isinstance(field, models.ForeignKey):
|
|
284
306
|
related_model = get_related_model(field)
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
related_factory = _get_related_factory(related_model)
|
|
295
|
-
return _ensure_model_instance(related_factory())
|
|
296
|
-
|
|
297
|
-
else:
|
|
298
|
-
# If no factory exists, pick a random existing instance
|
|
299
|
-
related_instances = list(related_model.objects.all())
|
|
300
|
-
if related_instances:
|
|
301
|
-
return _lazy_function(lambda: _RNG.choice(related_instances))
|
|
307
|
+
related_factory = (
|
|
308
|
+
_get_related_factory(related_model)
|
|
309
|
+
if hasattr(related_model, "_general_manager_class")
|
|
310
|
+
else None
|
|
311
|
+
)
|
|
312
|
+
if relation_generation == "create":
|
|
313
|
+
if related_factory is not None:
|
|
314
|
+
return _ensure_model_instance(related_factory())
|
|
302
315
|
if field.null:
|
|
303
316
|
return None
|
|
304
317
|
raise MissingFactoryOrInstancesError(related_model)
|
|
318
|
+
if relation_generation == "random" and related_factory is not None:
|
|
319
|
+
create_a_new_instance = _RNG.choice([True, True, False])
|
|
320
|
+
if not create_a_new_instance:
|
|
321
|
+
related_instances = _existing_related_instances(
|
|
322
|
+
field,
|
|
323
|
+
related_model,
|
|
324
|
+
database_alias=database_alias,
|
|
325
|
+
)
|
|
326
|
+
if related_instances:
|
|
327
|
+
return _lazy_existing_choice(related_instances)
|
|
328
|
+
return _ensure_model_instance(related_factory())
|
|
329
|
+
related_instances = _existing_related_instances(
|
|
330
|
+
field,
|
|
331
|
+
related_model,
|
|
332
|
+
database_alias=database_alias,
|
|
333
|
+
)
|
|
334
|
+
if related_instances:
|
|
335
|
+
return _lazy_existing_choice(related_instances)
|
|
336
|
+
if related_factory is not None:
|
|
337
|
+
return _ensure_model_instance(related_factory())
|
|
338
|
+
if field.null:
|
|
339
|
+
return None
|
|
340
|
+
raise MissingFactoryOrInstancesError(related_model)
|
|
305
341
|
else:
|
|
306
342
|
return None
|
|
307
343
|
|
|
@@ -372,19 +408,26 @@ def _resolve_related_model_string(
|
|
|
372
408
|
|
|
373
409
|
def get_many_to_many_field_value(
|
|
374
410
|
field: models.ManyToManyField[models.Model, models.Model],
|
|
411
|
+
*,
|
|
412
|
+
relation_generation: RelationGenerationMode = "reuse_existing",
|
|
413
|
+
database_alias: str | None = None,
|
|
375
414
|
) -> list[models.Model]:
|
|
376
415
|
"""
|
|
377
416
|
Generate a list of related model instances suitable for assigning to a ManyToManyField.
|
|
378
417
|
|
|
379
418
|
The function selects a random number of related objects (at least one when
|
|
380
|
-
the field is not blank, up to 10).
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
least one related instance.
|
|
419
|
+
the field is not blank, up to 10). Default generation samples existing
|
|
420
|
+
related rows when they are available and creates through the related model's
|
|
421
|
+
factory only when no existing rows are available. Create mode bypasses
|
|
422
|
+
existing rows and uses the related factory. `blank=True` allows an empty
|
|
423
|
+
result; `blank=False` requires at least one related instance.
|
|
385
424
|
|
|
386
425
|
Parameters:
|
|
387
426
|
field (models.ManyToManyField): The ManyToMany field to generate values for.
|
|
427
|
+
relation_generation: Strategy for relation values. Defaults to reusing
|
|
428
|
+
existing related rows before creating new related rows.
|
|
429
|
+
database_alias: Optional Django database alias used when querying
|
|
430
|
+
existing related rows.
|
|
388
431
|
|
|
389
432
|
Returns:
|
|
390
433
|
list[models.Model]: A list of related model instances to assign to the field.
|
|
@@ -400,37 +443,129 @@ def get_many_to_many_field_value(
|
|
|
400
443
|
"""
|
|
401
444
|
related_factory: RelatedFactory | None = None
|
|
402
445
|
related_model = get_related_model(field)
|
|
403
|
-
related_instances: list[models.Model] = list(related_model.objects.all())
|
|
404
446
|
if hasattr(related_model, "_general_manager_class"):
|
|
405
447
|
related_factory = _get_related_factory(related_model)
|
|
406
448
|
|
|
407
449
|
min_required = 0 if field.blank else 1
|
|
408
450
|
number_of_instances = _RNG.randint(min_required, 10)
|
|
409
|
-
if
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
]
|
|
424
|
-
return new_instances
|
|
425
|
-
elif related_instances:
|
|
426
|
-
number_to_create = 0
|
|
451
|
+
if relation_generation == "create":
|
|
452
|
+
if related_factory:
|
|
453
|
+
return [
|
|
454
|
+
_ensure_model_instance(related_factory())
|
|
455
|
+
for _ in range(number_of_instances)
|
|
456
|
+
]
|
|
457
|
+
raise MissingFactoryOrInstancesError(related_model)
|
|
458
|
+
|
|
459
|
+
related_instances = _existing_related_instances(
|
|
460
|
+
field,
|
|
461
|
+
related_model,
|
|
462
|
+
database_alias=database_alias,
|
|
463
|
+
)
|
|
464
|
+
if related_instances:
|
|
427
465
|
number_to_pick = number_of_instances
|
|
428
466
|
if number_to_pick > len(related_instances):
|
|
429
467
|
number_to_pick = len(related_instances)
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
468
|
+
return _RNG.sample(related_instances, number_to_pick)
|
|
469
|
+
if related_factory:
|
|
470
|
+
return [
|
|
471
|
+
_ensure_model_instance(related_factory())
|
|
472
|
+
for _ in range(number_of_instances)
|
|
473
|
+
]
|
|
474
|
+
raise MissingFactoryOrInstancesError(related_model)
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
def _is_relation_field(field: object) -> bool:
|
|
478
|
+
return (
|
|
479
|
+
isinstance(field, models.OneToOneField)
|
|
480
|
+
or isinstance(field, models.ForeignKey)
|
|
481
|
+
or getattr(field, "is_relation", False) is True
|
|
482
|
+
or getattr(field, "many_to_one", False) is True
|
|
483
|
+
or getattr(field, "one_to_one", False) is True
|
|
484
|
+
or getattr(field, "many_to_many", False) is True
|
|
485
|
+
)
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
def _existing_related_instances(
|
|
489
|
+
field: object,
|
|
490
|
+
related_model: type[models.Model] | None = None,
|
|
491
|
+
*,
|
|
492
|
+
database_alias: str | None = None,
|
|
493
|
+
) -> list[models.Model]:
|
|
494
|
+
"""Return existing related rows that are reusable for this relation field."""
|
|
495
|
+
field_obj = cast(Any, field)
|
|
496
|
+
if related_model is None:
|
|
497
|
+
related_model = cast(type[models.Model], field_obj.related_model)
|
|
498
|
+
related_instances = list(
|
|
499
|
+
_get_model_manager(related_model, database_alias=database_alias).all()
|
|
500
|
+
)
|
|
501
|
+
if not (
|
|
502
|
+
isinstance(field, models.OneToOneField)
|
|
503
|
+
or getattr(field, "one_to_one", False) is True
|
|
504
|
+
):
|
|
505
|
+
return related_instances
|
|
506
|
+
|
|
507
|
+
model = field_obj.model
|
|
508
|
+
attname = getattr(field_obj, "attname", field_obj.name)
|
|
509
|
+
try:
|
|
510
|
+
linked_values = set(
|
|
511
|
+
_get_model_manager(
|
|
512
|
+
model,
|
|
513
|
+
prefer_base=True,
|
|
514
|
+
database_alias=database_alias,
|
|
515
|
+
)
|
|
516
|
+
.exclude(**{attname: None})
|
|
517
|
+
.values_list(attname, flat=True)
|
|
518
|
+
)
|
|
519
|
+
except DatabaseError:
|
|
520
|
+
if getattr(getattr(model, "_meta", None), "managed", True) is not False:
|
|
521
|
+
raise
|
|
522
|
+
linked_values = set()
|
|
523
|
+
return [
|
|
524
|
+
instance
|
|
525
|
+
for instance in related_instances
|
|
526
|
+
if _related_target_value(instance, getattr(field_obj, "target_field", None))
|
|
527
|
+
not in linked_values
|
|
528
|
+
]
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
def _lazy_existing_choice(instances: list[models.Model]) -> LazyFunction:
|
|
532
|
+
return _lazy_function(lambda: _RNG.choice(instances))
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
def _related_target_value(instance: object, target_field: object | None) -> object:
|
|
536
|
+
if target_field is not None:
|
|
537
|
+
target_attr = getattr(
|
|
538
|
+
target_field,
|
|
539
|
+
"attname",
|
|
540
|
+
getattr(target_field, "name", None),
|
|
541
|
+
)
|
|
542
|
+
if target_attr is not None and hasattr(instance, target_attr):
|
|
543
|
+
return getattr(instance, target_attr)
|
|
544
|
+
return getattr(instance, "pk", None)
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
def _get_model_manager(
|
|
548
|
+
model: object,
|
|
549
|
+
*,
|
|
550
|
+
prefer_base: bool = False,
|
|
551
|
+
database_alias: str | None = None,
|
|
552
|
+
) -> Any:
|
|
553
|
+
model_obj = cast(Any, model)
|
|
554
|
+
if prefer_base:
|
|
555
|
+
base_manager = getattr(model_obj, "_base_manager", None)
|
|
556
|
+
if base_manager is not None:
|
|
557
|
+
if database_alias:
|
|
558
|
+
return base_manager.using(database_alias)
|
|
559
|
+
return base_manager
|
|
560
|
+
default_manager = getattr(model_obj, "_default_manager", None)
|
|
561
|
+
if default_manager is not None:
|
|
562
|
+
if database_alias:
|
|
563
|
+
return default_manager.using(database_alias)
|
|
564
|
+
return default_manager
|
|
565
|
+
objects_manager = model_obj.objects
|
|
566
|
+
if database_alias:
|
|
567
|
+
return objects_manager.using(database_alias)
|
|
568
|
+
return objects_manager
|
|
434
569
|
|
|
435
570
|
|
|
436
571
|
def _get_related_factory(related_model: type[models.Model]) -> RelatedFactory:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{generalmanager-0.59.0 → generalmanager-0.59.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
|
{generalmanager-0.59.0 → generalmanager-0.59.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.59.0 → generalmanager-0.59.2}/src/general_manager/api/graphql_mutations.py
RENAMED
|
File without changes
|
|
File without changes
|
{generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/graphql_resolvers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/graphql_subscriptions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/graphql_warmup_registry.py
RENAMED
|
File without changes
|
{generalmanager-0.59.0 → generalmanager-0.59.2}/src/general_manager/api/graphql_warmup_tasks.py
RENAMED
|
File without changes
|
|
File without changes
|