GeneralManager 0.59.2__tar.gz → 0.60.0__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.2/src/GeneralManager.egg-info → generalmanager-0.60.0}/PKG-INFO +1 -1
- {generalmanager-0.59.2 → generalmanager-0.60.0}/pyproject.toml +1 -1
- {generalmanager-0.59.2 → generalmanager-0.60.0/src/GeneralManager.egg-info}/PKG-INFO +1 -1
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/GeneralManager.egg-info/SOURCES.txt +3 -0
- generalmanager-0.60.0/src/general_manager/_types/dataframes.py +31 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/cache/cache_tracker.py +5 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/cache/dependency_matching.py +6 -0
- generalmanager-0.60.0/src/general_manager/dataframes/__init__.py +29 -0
- generalmanager-0.60.0/src/general_manager/dataframes/measurements.py +398 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/base_interface.py +132 -49
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/core/observability.py +36 -20
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/manager/general_manager.py +12 -10
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/manager/meta.py +16 -4
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/measurement/measurement.py +31 -8
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/public_api_registry.py +35 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/LICENSE +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/README.md +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/setup.cfg +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/GeneralManager.egg-info/dependency_links.txt +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/GeneralManager.egg-info/requires.txt +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/GeneralManager.egg-info/top_level.txt +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/_types/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/_types/api.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/_types/bucket.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/_types/cache.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/_types/factory.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/_types/general_manager.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/_types/interface.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/_types/manager.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/_types/measurement.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/_types/permission.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/_types/rule.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/_types/search.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/_types/utils.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/api/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/api/graphql.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/api/graphql_errors.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/api/graphql_mutations.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/api/graphql_prefetch.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/api/graphql_resolvers.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/api/graphql_search.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/api/graphql_subscription_consumer.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/api/graphql_subscriptions.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/api/graphql_view.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/api/graphql_warmup.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/api/graphql_warmup_registry.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/api/graphql_warmup_tasks.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/api/mutation.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/api/property.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/api/registry.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/api/remote_api.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/api/remote_invalidation.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/api/remote_invalidation_client.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/apps.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/bootstrap.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/bucket/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/bucket/base_bucket.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/bucket/calculation_bucket.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/bucket/database_bucket.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/bucket/group_bucket.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/bucket/indexing.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/bucket/request_bucket.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/cache/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/cache/cache_decorator.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/cache/dependency_cache.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/cache/dependency_index.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/cache/dependency_publish.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/cache/dependency_shards.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/cache/model_dependency_collector.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/cache/run_context.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/cache/signals.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/audit.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/bootstrap.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/checks.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/consumer.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/errors.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/evals/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/evals/__main__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/evals/baseline.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/evals/diagnostics.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/evals/fingerprints.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/evals/fixtures.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/evals/judges/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/evals/judges/answer_quality.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/evals/judges/contract.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/evals/judges/result_accuracy.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/evals/judges/tool_sequence.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/evals/readiness.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/evals/runner.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/evals/traces.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/grounding.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/models.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/providers/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/providers/_shared.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/providers/anthropic.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/providers/base.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/providers/google.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/providers/ollama.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/providers/openai.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/rate_limits.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/routing.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/schema_index.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/settings.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/signals.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/system_prompt.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/tool_metadata.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/tools.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/chat/views.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/conf.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/factory/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/factory/auto_factory.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/factory/factories.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/factory/factory_methods.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/bundles/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/bundles/calculation.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/bundles/database.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/bundles/remote_manager.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/bundles/request.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/base.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/builtin.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/calculation/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/calculation/_compat.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/calculation/lifecycle.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/configuration.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/core/utils.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/exceptions.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/existing_model/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/existing_model/_compat.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/existing_model/resolution.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/factory.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/orm/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/orm/_compat.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/orm/history.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/orm/lifecycle.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/orm/mutations.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/orm/support.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/orm_utils/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/orm_utils/django_manager_utils.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/orm_utils/field_descriptors.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/orm_utils/payload_normalizer.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/read_only/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/read_only/_compat.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/read_only/_types.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/read_only/lifecycle.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/read_only/management.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/registry.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/remote_manager.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/capabilities/request/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/infrastructure/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/infrastructure/startup_hooks.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/infrastructure/system_checks.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/interfaces/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/interfaces/calculation.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/interfaces/database.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/interfaces/existing_model.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/interfaces/read_only.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/interfaces/remote_manager.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/interfaces/request.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/manifests/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/manifests/capability_builder.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/manifests/capability_manifest.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/manifests/capability_models.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/orm_interface.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/requests.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/utils/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/utils/database_interface_protocols.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/utils/errors.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/interface/utils/models.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/logging.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/management/commands/chat_cleanup.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/management/commands/graphql_warmup.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/management/commands/graphql_warmup_refresh_due.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/management/commands/search_index.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/management/commands/search_reconcile.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/management/commands/seed_manager_landscape.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/management/commands/shell.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/management/commands/workflow_drain_outbox.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/management/commands/workflow_replay_dead_letters.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/manager/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/manager/group_manager.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/manager/input.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/measurement/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/measurement/measurement_field.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/metrics/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/metrics/graphql.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/migrations/0001_initial.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/migrations/0002_workflow_outbox_scaling_indexes.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/migrations/0003_workflow_execution_correlation_constraint.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/migrations/0004_chat_persistence_models.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/migrations/0004_search_index_state.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/migrations/0005_merge_chat_search.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/migrations/0006_chat_pending_confirmation_scoped_ids.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/migrations/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/models.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/permission/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/permission/audit.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/permission/base_permission.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/permission/graphql_capabilities.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/permission/manager_based_permission.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/permission/mutation_permission.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/permission/permission_checks.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/permission/permission_data_manager.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/permission/utils.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/py.typed +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/rule/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/rule/handler.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/rule/rule.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/search/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/search/async_tasks.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/search/backend.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/search/backend_registry.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/search/backends/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/search/backends/dev.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/search/backends/meilisearch.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/search/backends/opensearch.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/search/backends/typesense.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/search/config.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/search/indexer.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/search/models.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/search/reconciliation.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/search/registry.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/search/tasks.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/search/utils.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/seeding/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/seeding/manager_landscape.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/utils/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/utils/args_to_kwargs.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/utils/filter_parser.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/utils/format_string.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/utils/json_encoder.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/utils/make_cache_key.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/utils/none_to_zero.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/utils/path_mapping.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/utils/public_api.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/utils/testing.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/utils/type_checks.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/workflow/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/workflow/actions.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/workflow/backend_registry.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/workflow/backends/__init__.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/workflow/backends/celery.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/workflow/backends/local.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/workflow/backends/n8n.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/workflow/config.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/workflow/engine.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/workflow/event_registry.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/workflow/events.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/workflow/models.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/workflow/signal_bridge.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/workflow/tasks.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/workflow/telemetry.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/tests/test_settings.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/tests/test_urls.py +0 -0
- {generalmanager-0.59.2 → generalmanager-0.60.0}/tests/testing_asgi.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GeneralManager
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.60.0
|
|
4
4
|
Summary: Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching.
|
|
5
5
|
Author-email: Tim Kleindick <tkleindick@yahoo.de>
|
|
6
6
|
License: MIT License
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "GeneralManager"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.60.0"
|
|
8
8
|
description = "Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{ name = "Tim Kleindick", email = "tkleindick@yahoo.de" }]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GeneralManager
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.60.0
|
|
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
|
|
@@ -18,6 +18,7 @@ src/general_manager/_types/__init__.py
|
|
|
18
18
|
src/general_manager/_types/api.py
|
|
19
19
|
src/general_manager/_types/bucket.py
|
|
20
20
|
src/general_manager/_types/cache.py
|
|
21
|
+
src/general_manager/_types/dataframes.py
|
|
21
22
|
src/general_manager/_types/factory.py
|
|
22
23
|
src/general_manager/_types/general_manager.py
|
|
23
24
|
src/general_manager/_types/interface.py
|
|
@@ -102,6 +103,8 @@ src/general_manager/chat/providers/base.py
|
|
|
102
103
|
src/general_manager/chat/providers/google.py
|
|
103
104
|
src/general_manager/chat/providers/ollama.py
|
|
104
105
|
src/general_manager/chat/providers/openai.py
|
|
106
|
+
src/general_manager/dataframes/__init__.py
|
|
107
|
+
src/general_manager/dataframes/measurements.py
|
|
105
108
|
src/general_manager/factory/__init__.py
|
|
106
109
|
src/general_manager/factory/auto_factory.py
|
|
107
110
|
src/general_manager/factory/factories.py
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""Type-only imports for public API re-exports."""
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"DataFrameMeasurementError",
|
|
7
|
+
"InvalidDataFrameMeasurementValueError",
|
|
8
|
+
"MeasurementDataFrameColumnCollisionError",
|
|
9
|
+
"MissingMeasurementDataFrameColumnError",
|
|
10
|
+
"PandasNotInstalledError",
|
|
11
|
+
"collapse_measurements",
|
|
12
|
+
"expand_measurements",
|
|
13
|
+
"from_dataframe",
|
|
14
|
+
"to_dataframe",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
from general_manager.dataframes.measurements import DataFrameMeasurementError
|
|
18
|
+
from general_manager.dataframes.measurements import (
|
|
19
|
+
InvalidDataFrameMeasurementValueError,
|
|
20
|
+
)
|
|
21
|
+
from general_manager.dataframes.measurements import (
|
|
22
|
+
MeasurementDataFrameColumnCollisionError,
|
|
23
|
+
)
|
|
24
|
+
from general_manager.dataframes.measurements import (
|
|
25
|
+
MissingMeasurementDataFrameColumnError,
|
|
26
|
+
)
|
|
27
|
+
from general_manager.dataframes.measurements import PandasNotInstalledError
|
|
28
|
+
from general_manager.dataframes.measurements import collapse_measurements
|
|
29
|
+
from general_manager.dataframes.measurements import expand_measurements
|
|
30
|
+
from general_manager.dataframes.measurements import from_dataframe
|
|
31
|
+
from general_manager.dataframes.measurements import to_dataframe
|
|
@@ -142,6 +142,11 @@ class DependencyTracker:
|
|
|
142
142
|
]:
|
|
143
143
|
dep_set.add((class_name, operation, identifier))
|
|
144
144
|
|
|
145
|
+
@staticmethod
|
|
146
|
+
def is_active() -> bool:
|
|
147
|
+
"""Return whether dependency tracking is active for this execution context."""
|
|
148
|
+
return _dependency_storage.depth >= 0
|
|
149
|
+
|
|
145
150
|
@staticmethod
|
|
146
151
|
def reset_thread_local_storage() -> None:
|
|
147
152
|
"""Clear all dependency tracking data for the current thread.
|
{generalmanager-0.59.2 → generalmanager-0.60.0}/src/general_manager/cache/dependency_matching.py
RENAMED
|
@@ -101,6 +101,12 @@ def normalize_dependency_value(value: object) -> NormalizedDependencyValue:
|
|
|
101
101
|
|
|
102
102
|
def serialize_normalized_value(value: object) -> str:
|
|
103
103
|
"""Serialize dependency values in the canonical dependency format."""
|
|
104
|
+
if isinstance(value, str):
|
|
105
|
+
return json.dumps(value)
|
|
106
|
+
if value is None or isinstance(value, (int, float, bool)):
|
|
107
|
+
return json.dumps(value)
|
|
108
|
+
if isinstance(value, date):
|
|
109
|
+
return json.dumps(value.isoformat())
|
|
104
110
|
return json.dumps(normalize_dependency_value(value), sort_keys=True)
|
|
105
111
|
|
|
106
112
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Dataframe import/export helpers for GeneralManager values."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from general_manager.public_api_registry import DATAFRAME_EXPORTS
|
|
8
|
+
from general_manager.utils.public_api import build_module_dir, resolve_export
|
|
9
|
+
|
|
10
|
+
__all__ = list(DATAFRAME_EXPORTS)
|
|
11
|
+
|
|
12
|
+
_MODULE_MAP = DATAFRAME_EXPORTS
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from general_manager._types.dataframes import * # noqa: F403
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def __getattr__(name: str) -> object:
|
|
19
|
+
"""Dynamically resolve dataframe helper exports."""
|
|
20
|
+
return resolve_export(
|
|
21
|
+
name,
|
|
22
|
+
module_all=__all__,
|
|
23
|
+
module_map=_MODULE_MAP,
|
|
24
|
+
module_globals=globals(),
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def __dir__() -> list[str]:
|
|
29
|
+
return build_module_dir(module_all=__all__, module_globals=globals())
|
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
"""Helpers for expanding row-level Measurement values into dataframe columns."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Iterable, Mapping
|
|
6
|
+
from decimal import Decimal, InvalidOperation
|
|
7
|
+
import importlib
|
|
8
|
+
import math
|
|
9
|
+
from typing import Any, Protocol, cast
|
|
10
|
+
|
|
11
|
+
import pint
|
|
12
|
+
|
|
13
|
+
from general_manager.measurement import Measurement
|
|
14
|
+
|
|
15
|
+
Row = Mapping[str, object]
|
|
16
|
+
MutableRow = dict[str, object]
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"DataFrameMeasurementError",
|
|
20
|
+
"InvalidDataFrameMeasurementValueError",
|
|
21
|
+
"MeasurementDataFrameColumnCollisionError",
|
|
22
|
+
"MissingMeasurementDataFrameColumnError",
|
|
23
|
+
"PandasNotInstalledError",
|
|
24
|
+
"collapse_measurements",
|
|
25
|
+
"expand_measurements",
|
|
26
|
+
"from_dataframe",
|
|
27
|
+
"to_dataframe",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class DataFrameLike(Protocol):
|
|
32
|
+
"""Minimal dataframe interface needed to collapse measurement columns."""
|
|
33
|
+
|
|
34
|
+
def to_dict(self, orient: str = "dict") -> Any:
|
|
35
|
+
"""Return dataframe rows as dictionaries."""
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class DataFrameMeasurementError(ValueError):
|
|
39
|
+
"""Base error for dataframe measurement expansion failures."""
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class PandasNotInstalledError(ImportError):
|
|
43
|
+
"""Raised when pandas-specific dataframe helpers are used without pandas."""
|
|
44
|
+
|
|
45
|
+
def __init__(self) -> None:
|
|
46
|
+
super().__init__(
|
|
47
|
+
"pandas is required to create dataframes; install pandas to use "
|
|
48
|
+
"to_dataframe()."
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class _InvalidDataFrameRecordsError(TypeError):
|
|
53
|
+
"""Raised when dataframe records are not list[Mapping[str, object]]."""
|
|
54
|
+
|
|
55
|
+
def __init__(self) -> None:
|
|
56
|
+
super().__init__(
|
|
57
|
+
"dataframe.to_dict(orient='records') must return a list of mapping rows."
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class InvalidDataFrameMeasurementValueError(DataFrameMeasurementError):
|
|
62
|
+
"""Raised when a configured measurement field contains an invalid value."""
|
|
63
|
+
|
|
64
|
+
def __init__(
|
|
65
|
+
self,
|
|
66
|
+
field: str,
|
|
67
|
+
*,
|
|
68
|
+
value_type: str | None = None,
|
|
69
|
+
allows_strings: bool = False,
|
|
70
|
+
) -> None:
|
|
71
|
+
expected = "Measurement values or nulls"
|
|
72
|
+
if allows_strings:
|
|
73
|
+
expected = "Measurement values, parseable measurement strings, or nulls"
|
|
74
|
+
details = f"; got {value_type}" if value_type else ""
|
|
75
|
+
super().__init__(f"Field {field!r} must contain {expected}{details}.")
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class MeasurementDataFrameColumnCollisionError(DataFrameMeasurementError):
|
|
79
|
+
"""Raised when measurement expansion or collapse would overwrite row data."""
|
|
80
|
+
|
|
81
|
+
def __init__(
|
|
82
|
+
self,
|
|
83
|
+
field: str,
|
|
84
|
+
generated_field: str,
|
|
85
|
+
*,
|
|
86
|
+
operation: str = "Expanding",
|
|
87
|
+
) -> None:
|
|
88
|
+
super().__init__(
|
|
89
|
+
f"{operation} measurement field "
|
|
90
|
+
f"{field!r} would overwrite existing column {generated_field!r}."
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class MissingMeasurementDataFrameColumnError(DataFrameMeasurementError):
|
|
95
|
+
"""Raised when a generated measurement column is required but absent."""
|
|
96
|
+
|
|
97
|
+
def __init__(self, column: str) -> None:
|
|
98
|
+
super().__init__(
|
|
99
|
+
f"Collapsing measurement dataframe rows requires column {column!r}."
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def expand_measurements(
|
|
104
|
+
rows: Iterable[Row],
|
|
105
|
+
*,
|
|
106
|
+
measurement_fields: Iterable[str] | None = None,
|
|
107
|
+
) -> list[MutableRow]:
|
|
108
|
+
"""Expand Measurement values in mapping-like rows into value/unit columns."""
|
|
109
|
+
|
|
110
|
+
copied_rows = [dict(row) for row in rows]
|
|
111
|
+
explicit_fields = _ordered_unique(
|
|
112
|
+
() if measurement_fields is None else measurement_fields
|
|
113
|
+
)
|
|
114
|
+
inferred_fields = _infer_measurement_fields(copied_rows)
|
|
115
|
+
expanded_fields = _ordered_unique((*explicit_fields, *inferred_fields))
|
|
116
|
+
if not expanded_fields:
|
|
117
|
+
return copied_rows
|
|
118
|
+
|
|
119
|
+
_check_generated_column_collisions(copied_rows, expanded_fields)
|
|
120
|
+
explicit_field_names = set(explicit_fields)
|
|
121
|
+
expanded_field_names = set(expanded_fields)
|
|
122
|
+
return [
|
|
123
|
+
_expand_row(
|
|
124
|
+
row,
|
|
125
|
+
expanded_fields=expanded_fields,
|
|
126
|
+
expanded_field_names=expanded_field_names,
|
|
127
|
+
explicit_field_names=explicit_field_names,
|
|
128
|
+
)
|
|
129
|
+
for row in copied_rows
|
|
130
|
+
]
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def collapse_measurements(
|
|
134
|
+
rows: Iterable[Row],
|
|
135
|
+
*,
|
|
136
|
+
measurement_fields: Iterable[str],
|
|
137
|
+
) -> list[MutableRow]:
|
|
138
|
+
"""Collapse value/unit dataframe columns back into Measurement values."""
|
|
139
|
+
|
|
140
|
+
collapsed_fields = _ordered_unique(measurement_fields)
|
|
141
|
+
value_columns: dict[str, str] = {}
|
|
142
|
+
unit_columns: set[str] = set()
|
|
143
|
+
for field in collapsed_fields:
|
|
144
|
+
value_field, unit_field = _generated_field_names(field)
|
|
145
|
+
value_columns[value_field] = field
|
|
146
|
+
unit_columns.add(unit_field)
|
|
147
|
+
|
|
148
|
+
return [
|
|
149
|
+
_collapse_row(
|
|
150
|
+
dict(row),
|
|
151
|
+
collapsed_fields=collapsed_fields,
|
|
152
|
+
value_columns=value_columns,
|
|
153
|
+
unit_columns=unit_columns,
|
|
154
|
+
)
|
|
155
|
+
for row in rows
|
|
156
|
+
]
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def to_dataframe(
|
|
160
|
+
rows: Iterable[Row],
|
|
161
|
+
*,
|
|
162
|
+
measurement_fields: Iterable[str] | None = None,
|
|
163
|
+
**dataframe_kwargs: object,
|
|
164
|
+
) -> Any:
|
|
165
|
+
"""Expand measurement values and build a pandas DataFrame."""
|
|
166
|
+
|
|
167
|
+
expanded_rows = expand_measurements(rows, measurement_fields=measurement_fields)
|
|
168
|
+
pandas = _import_pandas()
|
|
169
|
+
return pandas.DataFrame(expanded_rows, **dataframe_kwargs)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def from_dataframe(
|
|
173
|
+
dataframe: DataFrameLike,
|
|
174
|
+
*,
|
|
175
|
+
measurement_fields: Iterable[str],
|
|
176
|
+
) -> list[MutableRow]:
|
|
177
|
+
"""Collapse measurement value/unit columns from a dataframe-like object."""
|
|
178
|
+
|
|
179
|
+
records = dataframe.to_dict(orient="records")
|
|
180
|
+
if not isinstance(records, list):
|
|
181
|
+
raise _InvalidDataFrameRecordsError
|
|
182
|
+
|
|
183
|
+
row_records: list[Row] = []
|
|
184
|
+
for record in records:
|
|
185
|
+
if not isinstance(record, Mapping):
|
|
186
|
+
raise _InvalidDataFrameRecordsError
|
|
187
|
+
row_records.append(record)
|
|
188
|
+
|
|
189
|
+
return collapse_measurements(row_records, measurement_fields=measurement_fields)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def _import_pandas() -> Any:
|
|
193
|
+
try:
|
|
194
|
+
return importlib.import_module("pandas")
|
|
195
|
+
except ModuleNotFoundError as error:
|
|
196
|
+
if error.name != "pandas":
|
|
197
|
+
raise
|
|
198
|
+
raise PandasNotInstalledError from error
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def _ordered_unique(fields: Iterable[str]) -> tuple[str, ...]:
|
|
202
|
+
seen: set[str] = set()
|
|
203
|
+
ordered_fields: list[str] = []
|
|
204
|
+
for field in fields:
|
|
205
|
+
if field in seen:
|
|
206
|
+
continue
|
|
207
|
+
seen.add(field)
|
|
208
|
+
ordered_fields.append(field)
|
|
209
|
+
return tuple(ordered_fields)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def _infer_measurement_fields(rows: Iterable[Row]) -> tuple[str, ...]:
|
|
213
|
+
return _ordered_unique(
|
|
214
|
+
field
|
|
215
|
+
for row in rows
|
|
216
|
+
for field, value in row.items()
|
|
217
|
+
if isinstance(value, Measurement)
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def _check_generated_column_collisions(
|
|
222
|
+
rows: Iterable[Row], measurement_fields: Iterable[str]
|
|
223
|
+
) -> None:
|
|
224
|
+
for field in measurement_fields:
|
|
225
|
+
generated_fields = _generated_field_names(field)
|
|
226
|
+
for row in rows:
|
|
227
|
+
for generated_field in generated_fields:
|
|
228
|
+
if generated_field in row and generated_field != field:
|
|
229
|
+
raise MeasurementDataFrameColumnCollisionError(
|
|
230
|
+
field, generated_field
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def _generated_field_names(field: str) -> tuple[str, str]:
|
|
235
|
+
return (f"{field}_value", f"{field}_unit")
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def _expand_row(
|
|
239
|
+
row: Row,
|
|
240
|
+
*,
|
|
241
|
+
expanded_fields: tuple[str, ...],
|
|
242
|
+
expanded_field_names: set[str],
|
|
243
|
+
explicit_field_names: set[str],
|
|
244
|
+
) -> MutableRow:
|
|
245
|
+
expanded_row: MutableRow = {}
|
|
246
|
+
seen_measurement_fields: set[str] = set()
|
|
247
|
+
|
|
248
|
+
for field, value in row.items():
|
|
249
|
+
if field not in expanded_field_names:
|
|
250
|
+
expanded_row[field] = value
|
|
251
|
+
continue
|
|
252
|
+
|
|
253
|
+
seen_measurement_fields.add(field)
|
|
254
|
+
value_field, unit_field = _generated_field_names(field)
|
|
255
|
+
measurement = _coerce_measurement_value(
|
|
256
|
+
field,
|
|
257
|
+
value,
|
|
258
|
+
explicit_field_names=explicit_field_names,
|
|
259
|
+
)
|
|
260
|
+
expanded_row[value_field] = (
|
|
261
|
+
measurement.magnitude if measurement is not None else None
|
|
262
|
+
)
|
|
263
|
+
expanded_row[unit_field] = measurement.unit if measurement is not None else None
|
|
264
|
+
|
|
265
|
+
for field in expanded_fields:
|
|
266
|
+
if field in seen_measurement_fields:
|
|
267
|
+
continue
|
|
268
|
+
value_field, unit_field = _generated_field_names(field)
|
|
269
|
+
expanded_row[value_field] = None
|
|
270
|
+
expanded_row[unit_field] = None
|
|
271
|
+
|
|
272
|
+
return expanded_row
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def _collapse_row(
|
|
276
|
+
row: MutableRow,
|
|
277
|
+
*,
|
|
278
|
+
collapsed_fields: tuple[str, ...],
|
|
279
|
+
value_columns: Mapping[str, str],
|
|
280
|
+
unit_columns: set[str],
|
|
281
|
+
) -> MutableRow:
|
|
282
|
+
for field in collapsed_fields:
|
|
283
|
+
value_field, unit_field = _generated_field_names(field)
|
|
284
|
+
if value_field not in row:
|
|
285
|
+
raise MissingMeasurementDataFrameColumnError(value_field)
|
|
286
|
+
if unit_field not in row:
|
|
287
|
+
raise MissingMeasurementDataFrameColumnError(unit_field)
|
|
288
|
+
if field in row:
|
|
289
|
+
raise MeasurementDataFrameColumnCollisionError(
|
|
290
|
+
field,
|
|
291
|
+
field,
|
|
292
|
+
operation="Collapsing",
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
collapsed_row: MutableRow = {}
|
|
296
|
+
for column, value in row.items():
|
|
297
|
+
if column in value_columns:
|
|
298
|
+
field = value_columns[column]
|
|
299
|
+
_value_field, unit_field = _generated_field_names(field)
|
|
300
|
+
collapsed_row[field] = _build_collapsed_measurement(
|
|
301
|
+
field,
|
|
302
|
+
value,
|
|
303
|
+
row[unit_field],
|
|
304
|
+
)
|
|
305
|
+
continue
|
|
306
|
+
if column in unit_columns:
|
|
307
|
+
continue
|
|
308
|
+
collapsed_row[column] = value
|
|
309
|
+
|
|
310
|
+
return collapsed_row
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
def _coerce_measurement_value(
|
|
314
|
+
field: str,
|
|
315
|
+
value: object,
|
|
316
|
+
*,
|
|
317
|
+
explicit_field_names: set[str],
|
|
318
|
+
) -> Measurement | None:
|
|
319
|
+
if _is_null_measurement_value(value):
|
|
320
|
+
return None
|
|
321
|
+
if isinstance(value, Measurement):
|
|
322
|
+
return value
|
|
323
|
+
if isinstance(value, str) and field in explicit_field_names:
|
|
324
|
+
try:
|
|
325
|
+
return Measurement.from_string(value)
|
|
326
|
+
except ValueError as error:
|
|
327
|
+
raise InvalidDataFrameMeasurementValueError(
|
|
328
|
+
field, allows_strings=True
|
|
329
|
+
) from error
|
|
330
|
+
|
|
331
|
+
raise InvalidDataFrameMeasurementValueError(field, value_type=type(value).__name__)
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def _build_collapsed_measurement(
|
|
335
|
+
field: str,
|
|
336
|
+
value: object,
|
|
337
|
+
unit: object,
|
|
338
|
+
) -> Measurement | None:
|
|
339
|
+
value_is_null = _is_null_measurement_value(value)
|
|
340
|
+
unit_is_null = _is_null_measurement_value(unit)
|
|
341
|
+
if value_is_null and unit_is_null:
|
|
342
|
+
return None
|
|
343
|
+
if value_is_null or unit_is_null:
|
|
344
|
+
raise InvalidDataFrameMeasurementValueError(field)
|
|
345
|
+
if not isinstance(unit, str):
|
|
346
|
+
raise InvalidDataFrameMeasurementValueError(
|
|
347
|
+
field,
|
|
348
|
+
value_type=type(unit).__name__,
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
try:
|
|
352
|
+
magnitude = Decimal(str(value))
|
|
353
|
+
except (InvalidOperation, TypeError, ValueError) as error:
|
|
354
|
+
raise InvalidDataFrameMeasurementValueError(
|
|
355
|
+
field,
|
|
356
|
+
value_type=type(value).__name__,
|
|
357
|
+
) from error
|
|
358
|
+
try:
|
|
359
|
+
return Measurement(magnitude, unit)
|
|
360
|
+
except pint.errors.PintError as error:
|
|
361
|
+
raise InvalidDataFrameMeasurementValueError(
|
|
362
|
+
field,
|
|
363
|
+
value_type=type(unit).__name__,
|
|
364
|
+
) from error
|
|
365
|
+
except (TypeError, ValueError) as error:
|
|
366
|
+
raise InvalidDataFrameMeasurementValueError(
|
|
367
|
+
field,
|
|
368
|
+
value_type=type(value).__name__,
|
|
369
|
+
) from error
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
def _is_null_measurement_value(value: object) -> bool:
|
|
373
|
+
if value is None:
|
|
374
|
+
return True
|
|
375
|
+
if _is_nan_like(value):
|
|
376
|
+
return True
|
|
377
|
+
return _is_pandas_null_sentinel(value)
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
def _is_nan_like(value: object) -> bool:
|
|
381
|
+
try:
|
|
382
|
+
if math.isnan(cast(Any, value)):
|
|
383
|
+
return True
|
|
384
|
+
except (TypeError, ValueError):
|
|
385
|
+
pass
|
|
386
|
+
|
|
387
|
+
try:
|
|
388
|
+
return bool(value != value)
|
|
389
|
+
except (TypeError, ValueError):
|
|
390
|
+
return False
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def _is_pandas_null_sentinel(value: object) -> bool:
|
|
394
|
+
value_type = type(value)
|
|
395
|
+
return value_type.__name__ in {
|
|
396
|
+
"NAType",
|
|
397
|
+
"NaTType",
|
|
398
|
+
} and value_type.__module__.startswith("pandas.")
|