cognite-neat 1.0.28__tar.gz → 1.0.30__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.
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/PKG-INFO +1 -1
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_config.py +3 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/_analysis.py +441 -9
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/_constants.py +1 -0
- cognite_neat-1.0.30/cognite/neat/_data_model/importers/__init__.py +5 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/importers/_api_importer.py +168 -3
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/validation/dms/__init__.py +8 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/validation/dms/_containers.py +15 -1
- cognite_neat-1.0.30/cognite/neat/_data_model/validation/dms/_performance.py +194 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_exceptions.py +13 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_physical.py +55 -1
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_wrappers.py +20 -2
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_store/_store.py +4 -1
- cognite_neat-1.0.30/cognite/neat/_version.py +2 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/pyproject.toml +1 -1
- cognite_neat-1.0.28/cognite/neat/_data_model/importers/__init__.py +0 -5
- cognite_neat-1.0.28/cognite/neat/_version.py +0 -2
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/README.md +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_client/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_client/api.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_client/client.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_client/config.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_client/containers_api.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_client/data_classes.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_client/data_model_api.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_client/filters.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_client/init/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_client/init/credentials.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_client/init/env_vars.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_client/init/interactive.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_client/init/main.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_client/spaces_api.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_client/statistics_api.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_client/views_api.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/_identifiers.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/_shared.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/_snapshot.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/deployer/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/deployer/_differ.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/deployer/_differ_container.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/deployer/_differ_data_model.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/deployer/_differ_space.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/deployer/_differ_view.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/deployer/data_classes.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/deployer/deployer.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/exporters/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/exporters/_api_exporter.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/exporters/_base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/exporters/_table_exporter/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/exporters/_table_exporter/exporter.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/exporters/_table_exporter/workbook.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/exporters/_table_exporter/writer.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/importers/_base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/importers/_table_importer/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/importers/_table_importer/data_classes.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/importers/_table_importer/importer.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/importers/_table_importer/reader.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/importers/_table_importer/source.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/conceptual/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/conceptual/_base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/conceptual/_concept.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/conceptual/_data_model.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/conceptual/_properties.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/conceptual/_property.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/dms/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/dms/_base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/dms/_constants.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/dms/_constraints.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/dms/_container.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/dms/_data_model.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/dms/_data_types.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/dms/_http.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/dms/_indexes.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/dms/_limits.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/dms/_references.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/dms/_schema.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/dms/_space.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/dms/_types.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/dms/_view_filter.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/dms/_view_property.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/dms/_views.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/entities/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/entities/_base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/entities/_constants.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/entities/_data_types.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/entities/_identifiers.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/models/entities/_parser.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/validation/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/validation/dms/_ai_readiness.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/validation/dms/_base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/validation/dms/_connections.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/validation/dms/_consistency.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/validation/dms/_limits.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/validation/dms/_orchestrator.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_data_model/validation/dms/_views.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_issues.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_cdf.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_html/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_html/_render.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_html/static/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_html/static/deployment.css +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_html/static/deployment.js +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_html/static/issues.css +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_html/static/issues.js +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_html/static/shared.css +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_html/static/statistics.css +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_html/static/statistics.js +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_html/templates/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_html/templates/deployment.html +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_html/templates/issues.html +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_html/templates/statistics.html +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_issues.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_result/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_result/_deployment/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_result/_deployment/_physical/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_result/_deployment/_physical/_changes.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_result/_deployment/_physical/_statistics.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_result/_deployment/_physical/serializer.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_result/_result.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_session.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_usage_analytics/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_usage_analytics/_collector.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_usage_analytics/_constants.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_session/_usage_analytics/_storage.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_state_machine/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_state_machine/_base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_state_machine/_states.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_store/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_store/_provenance.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_utils/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_utils/_reader.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_utils/auxiliary.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_utils/collection.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_utils/http_client/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_utils/http_client/_client.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_utils/http_client/_config.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_utils/http_client/_data_classes.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_utils/http_client/_tracker.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_utils/repo.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_utils/text.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_utils/useful_types.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_utils/validation.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_client/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_client/_api/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_client/_api/data_modeling_loaders.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_client/_api/neat_instances.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_client/_api/schema.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_client/_api/statistics.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_client/_api_client.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_client/data_classes/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_client/data_classes/data_modeling.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_client/data_classes/neat_sequence.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_client/data_classes/schema.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_client/data_classes/statistics.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_client/testing.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_config.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_constants.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/_constants.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/_shared.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/analysis/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/analysis/_base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/catalog/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/catalog/classic_model.xlsx +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/catalog/conceptual-imf-data-model.xlsx +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/catalog/hello_world_pump.xlsx +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/exporters/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/exporters/_base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/exporters/_data_model2dms.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/exporters/_data_model2excel.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/exporters/_data_model2instance_template.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/exporters/_data_model2semantic_model.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/exporters/_data_model2yaml.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/importers/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/importers/_base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/importers/_base_file_reader.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/importers/_dict2data_model.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/importers/_dms2data_model.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/importers/_graph2data_model.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/importers/_rdf/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/importers/_rdf/_base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/importers/_rdf/_inference2rdata_model.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/importers/_rdf/_owl2data_model.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/importers/_rdf/_shared.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/importers/_spreadsheet2data_model.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/_base_unverified.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/_base_verified.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/_import_contexts.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/_types.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/conceptual/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/conceptual/_unverified.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/conceptual/_validation.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/conceptual/_verified.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/data_types.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/entities/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/entities/_constants.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/entities/_loaders.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/entities/_multi_value.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/entities/_restrictions.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/entities/_single_value.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/entities/_types.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/entities/_wrapped.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/mapping/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/mapping/_classic2core.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/mapping/_classic2core.yaml +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/physical/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/physical/_exporter.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/physical/_unverified.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/physical/_validation.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/models/physical/_verified.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/transformers/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/transformers/_base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/transformers/_converters.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/transformers/_mapping.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/transformers/_union_conceptual.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_data_model/transformers/_verification.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/_shared.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/_tracking/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/_tracking/base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/_tracking/log.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/examples/Knowledge-Graph-Nordic44-dirty.xml +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/examples/Knowledge-Graph-Nordic44.xml +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/examples/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/examples/skos-capturing-sheet-wind-topics.xlsx +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/extractors/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/extractors/_base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/extractors/_classic_cdf/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/extractors/_classic_cdf/_assets.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/extractors/_classic_cdf/_base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/extractors/_classic_cdf/_classic.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/extractors/_classic_cdf/_data_sets.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/extractors/_classic_cdf/_events.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/extractors/_classic_cdf/_files.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/extractors/_classic_cdf/_labels.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/extractors/_classic_cdf/_relationships.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/extractors/_classic_cdf/_sequences.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/extractors/_classic_cdf/_timeseries.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/extractors/_dict.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/extractors/_dms.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/extractors/_dms_graph.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/extractors/_mock_graph_generator.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/extractors/_raw.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/extractors/_rdf_file.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/loaders/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/loaders/_base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/loaders/_rdf2dms.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/loaders/_rdf_to_instance_space.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/queries/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/queries/_base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/queries/_queries.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/queries/_select.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/queries/_update.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/transformers/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/transformers/_base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/transformers/_classic_cdf.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/transformers/_prune_graph.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/transformers/_rdfpath.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_instances/transformers/_value_type.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_issues/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_issues/_base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_issues/_contextmanagers.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_issues/_factory.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_issues/errors/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_issues/errors/_external.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_issues/errors/_general.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_issues/errors/_properties.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_issues/errors/_resources.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_issues/errors/_wrapper.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_issues/formatters.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_issues/warnings/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_issues/warnings/_external.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_issues/warnings/_general.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_issues/warnings/_models.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_issues/warnings/_properties.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_issues/warnings/_resources.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_issues/warnings/user_modeling.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_shared.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_store/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_store/_data_model.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_store/_instance.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_store/_provenance.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_store/exceptions.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_utils/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_utils/auth.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_utils/auxiliary.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_utils/collection_.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_utils/graph_transformations_report.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_utils/io_.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_utils/rdf_.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_utils/reader/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_utils/reader/_base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_utils/spreadsheet.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_utils/tarjan.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_utils/text.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_utils/time_.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_utils/upload.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/core/_utils/xml_.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/engine/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/engine/_import.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/engine/_interface.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/engine/_load.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/plugins/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/plugins/_base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/plugins/_data_model.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/plugins/_issues.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/plugins/_manager.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/__init__.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/_base.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/_collector.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/_diff.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/_drop.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/_experimental.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/_explore.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/_fix.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/_inspect.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/_mapping.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/_plugin.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/_prepare.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/_read.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/_set.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/_show.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/_state/README.md +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/_state.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/_subset.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/_template.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/_to.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/_wizard.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/_v0/session/exceptions.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/legacy.py +0 -0
- {cognite_neat-1.0.28 → cognite_neat-1.0.30}/cognite/neat/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cognite-neat
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.30
|
|
4
4
|
Summary: Knowledge graph transformation
|
|
5
5
|
Author: Nikola Vasiljevic, Anders Albert
|
|
6
6
|
Author-email: Nikola Vasiljevic <nikola.vasiljevic@cognite.com>, Anders Albert <anders.albert@cognite.com>
|
|
@@ -105,6 +105,9 @@ class AlphaFlagConfig(ConfigModel):
|
|
|
105
105
|
default=False,
|
|
106
106
|
description="If enabled, Neat will run experimental validators that are still in alpha stage.",
|
|
107
107
|
)
|
|
108
|
+
enable_solution_model_creation: bool = Field(
|
|
109
|
+
default=False, description="If enabled, neat.physical_data_model.create() will be available"
|
|
110
|
+
)
|
|
108
111
|
enable_cdf_analysis: bool = Field(default=False, description="If enabled, neat.cdf endpoint will be available.")
|
|
109
112
|
|
|
110
113
|
def __setattr__(self, key: str, value: Any) -> None:
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
import math
|
|
1
2
|
from collections import defaultdict
|
|
2
|
-
from
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from itertools import chain, combinations
|
|
3
6
|
from typing import Literal, TypeAlias, TypeVar
|
|
4
7
|
|
|
5
8
|
import networkx as nx
|
|
6
9
|
from pyparsing import cached_property
|
|
7
10
|
|
|
11
|
+
from cognite.neat._data_model._constants import COGNITE_SPACES
|
|
8
12
|
from cognite.neat._data_model._snapshot import SchemaSnapshot
|
|
9
13
|
from cognite.neat._data_model.models.dms._constraints import RequiresConstraintDefinition
|
|
10
14
|
from cognite.neat._data_model.models.dms._container import ContainerRequest
|
|
@@ -41,12 +45,34 @@ ResourceSource = Literal["auto", "merged", "cdf", "both"]
|
|
|
41
45
|
_NodeT = TypeVar("_NodeT", ContainerReference, ViewReference)
|
|
42
46
|
|
|
43
47
|
|
|
48
|
+
class RequiresChangeStatus(Enum):
|
|
49
|
+
"""Status of requires constraint changes for a view."""
|
|
50
|
+
|
|
51
|
+
OPTIMAL = "optimal" # Already optimized, no changes needed
|
|
52
|
+
CHANGES_AVAILABLE = "changes_available" # Recommendations available
|
|
53
|
+
UNSOLVABLE = "unsolvable" # Structural issue - can't create connected hierarchy
|
|
54
|
+
NO_MODIFIABLE_CONTAINERS = "no_modifiable_containers" # All containers are immutable
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@dataclass
|
|
58
|
+
class RequiresChangesForView:
|
|
59
|
+
"""Result of computing requires constraint changes for a view."""
|
|
60
|
+
|
|
61
|
+
to_add: set[tuple[ContainerReference, ContainerReference]]
|
|
62
|
+
to_remove: set[tuple[ContainerReference, ContainerReference]]
|
|
63
|
+
status: RequiresChangeStatus
|
|
64
|
+
|
|
65
|
+
|
|
44
66
|
class ValidationResources:
|
|
45
67
|
def __init__(
|
|
46
|
-
self,
|
|
68
|
+
self,
|
|
69
|
+
modus_operandi: ModusOperandi,
|
|
70
|
+
local: SchemaSnapshot,
|
|
71
|
+
cdf: SchemaSnapshot,
|
|
72
|
+
limits: SchemaLimits | None = None,
|
|
47
73
|
) -> None:
|
|
48
74
|
self._modus_operandi = modus_operandi
|
|
49
|
-
self.limits = limits
|
|
75
|
+
self.limits = limits or SchemaLimits()
|
|
50
76
|
|
|
51
77
|
self.local = local
|
|
52
78
|
self.cdf = cdf
|
|
@@ -385,6 +411,18 @@ class ValidationResources:
|
|
|
385
411
|
|
|
386
412
|
return connection_end_node_types
|
|
387
413
|
|
|
414
|
+
@staticmethod
|
|
415
|
+
def is_explicit_connection(property_: ViewRequestProperty) -> bool:
|
|
416
|
+
"""Check if a property is an explicit connection property, meaning end node type is explicitly defined.
|
|
417
|
+
|
|
418
|
+
Args:
|
|
419
|
+
property_: The property to check.
|
|
420
|
+
|
|
421
|
+
Returns:
|
|
422
|
+
True if the property is a connection property, False otherwise.
|
|
423
|
+
"""
|
|
424
|
+
return True if property_.source else False
|
|
425
|
+
|
|
388
426
|
@cached_property
|
|
389
427
|
def views_by_container(self) -> dict[ContainerReference, set[ViewReference]]:
|
|
390
428
|
"""Get a mapping from containers to the views that use them.
|
|
@@ -512,17 +550,84 @@ class ValidationResources:
|
|
|
512
550
|
graph.add_node(container_ref)
|
|
513
551
|
|
|
514
552
|
# Add edges for requires constraints from all known containers
|
|
515
|
-
for container_ref in graph.nodes():
|
|
553
|
+
for container_ref in list(graph.nodes()):
|
|
516
554
|
container = self.select_container(container_ref)
|
|
517
555
|
if not container or not container.constraints:
|
|
518
556
|
continue
|
|
519
|
-
for constraint in container.constraints.
|
|
557
|
+
for constraint_id, constraint in container.constraints.items():
|
|
520
558
|
if not isinstance(constraint, RequiresConstraintDefinition):
|
|
521
559
|
continue
|
|
522
|
-
|
|
560
|
+
is_auto = constraint_id.endswith("__auto")
|
|
561
|
+
graph.add_edge(container_ref, constraint.require, is_auto=is_auto)
|
|
523
562
|
|
|
524
563
|
return graph
|
|
525
564
|
|
|
565
|
+
@cached_property
|
|
566
|
+
def modifiable_containers(self) -> set[ContainerReference]:
|
|
567
|
+
"""Containers whose requires constraints can be modified in this session.
|
|
568
|
+
|
|
569
|
+
A container is modifiable if:
|
|
570
|
+
- It's NOT in a CDF built-in space (CDM, IDM, etc.)
|
|
571
|
+
- It's a user container brought in through the loaded data model scope or view implements chain
|
|
572
|
+
"""
|
|
573
|
+
return {container_ref for container_ref in self.merged.containers if container_ref.space not in COGNITE_SPACES}
|
|
574
|
+
|
|
575
|
+
@cached_property
|
|
576
|
+
def immutable_requires_constraint_graph(self) -> nx.DiGraph:
|
|
577
|
+
"""Subgraph of requires constraints from non-modifiable (CDM) containers.
|
|
578
|
+
|
|
579
|
+
Used to check reachability via existing immutable constraints.
|
|
580
|
+
"""
|
|
581
|
+
return nx.subgraph_view(
|
|
582
|
+
self.requires_constraint_graph,
|
|
583
|
+
filter_edge=lambda src, _: src not in self.modifiable_containers,
|
|
584
|
+
)
|
|
585
|
+
|
|
586
|
+
@cached_property
|
|
587
|
+
def _fixed_constraint_graph(self) -> nx.DiGraph:
|
|
588
|
+
"""Graph of all fixed constraints (immutable + user-intentional).
|
|
589
|
+
|
|
590
|
+
Both are "fixed" from the optimizer's perspective - existing paths that can't be changed.
|
|
591
|
+
"""
|
|
592
|
+
G = nx.DiGraph()
|
|
593
|
+
G.add_edges_from(self.immutable_requires_constraint_graph.edges())
|
|
594
|
+
G.add_edges_from(self._user_intentional_constraints)
|
|
595
|
+
return G
|
|
596
|
+
|
|
597
|
+
@cached_property
|
|
598
|
+
def _fixed_descendants(self) -> defaultdict[ContainerReference, set[ContainerReference]]:
|
|
599
|
+
"""Pre-compute descendants via fixed constraints. Missing keys return empty set."""
|
|
600
|
+
result: defaultdict[ContainerReference, set[ContainerReference]] = defaultdict(set)
|
|
601
|
+
for container in self._fixed_constraint_graph.nodes():
|
|
602
|
+
result[container] = nx.descendants(self._fixed_constraint_graph, container)
|
|
603
|
+
return result
|
|
604
|
+
|
|
605
|
+
@cached_property
|
|
606
|
+
def _existing_requires_edges(self) -> set[tuple[ContainerReference, ContainerReference]]:
|
|
607
|
+
"""Cached set of existing requires constraint edges."""
|
|
608
|
+
return set(self.requires_constraint_graph.edges())
|
|
609
|
+
|
|
610
|
+
@cached_property
|
|
611
|
+
def _user_intentional_constraints(self) -> set[tuple[ContainerReference, ContainerReference]]:
|
|
612
|
+
"""Constraints that appear to be user-intentional and should not be auto-removed
|
|
613
|
+
|
|
614
|
+
A constraint is user-intentional if:
|
|
615
|
+
1. The constraint identifier does NOT have '__auto' postfix
|
|
616
|
+
2. Neither src nor dst is part of a cycle (cyclic constraints are errors)
|
|
617
|
+
|
|
618
|
+
These constraints are preserved even if they're not in the optimal structure, because
|
|
619
|
+
they may be used for data integrity purposes.
|
|
620
|
+
We DON'T consider manual-created constraints as user-intended if they form part of a cycle,
|
|
621
|
+
because that indicates a problem with the data model where we likely can provide a better solution.
|
|
622
|
+
"""
|
|
623
|
+
containers_in_cycles = {container for cycle in self.requires_constraint_cycles for container in cycle}
|
|
624
|
+
|
|
625
|
+
return {
|
|
626
|
+
(src, dst)
|
|
627
|
+
for src, dst, data in self.requires_constraint_graph.edges(data=True)
|
|
628
|
+
if not data.get("is_auto", False) and src not in containers_in_cycles and dst not in containers_in_cycles
|
|
629
|
+
}
|
|
630
|
+
|
|
526
631
|
@staticmethod
|
|
527
632
|
def forms_directed_path(nodes: set[_NodeT], graph: nx.DiGraph) -> bool:
|
|
528
633
|
"""Check if nodes form an uninterrupted directed path in the graph.
|
|
@@ -549,8 +654,14 @@ class ValidationResources:
|
|
|
549
654
|
if len(nodes) <= 1:
|
|
550
655
|
return True
|
|
551
656
|
|
|
552
|
-
|
|
553
|
-
|
|
657
|
+
# Filter to nodes that are actually in the graph
|
|
658
|
+
nodes_in_graph = {n for n in nodes if n in graph}
|
|
659
|
+
if len(nodes_in_graph) < len(nodes):
|
|
660
|
+
# Some nodes aren't in the graph, so we can't form a complete path
|
|
661
|
+
return False
|
|
662
|
+
|
|
663
|
+
for candidate in nodes_in_graph:
|
|
664
|
+
others = nodes_in_graph - {candidate}
|
|
554
665
|
if others.issubset(nx.descendants(graph, candidate)):
|
|
555
666
|
return True
|
|
556
667
|
|
|
@@ -562,10 +673,331 @@ class ValidationResources:
|
|
|
562
673
|
Returns:
|
|
563
674
|
List of lists, where each list contains the ordered containers involved in forming the requires cycle.
|
|
564
675
|
"""
|
|
565
|
-
|
|
566
676
|
return self.graph_cycles(self.requires_constraint_graph)
|
|
567
677
|
|
|
568
678
|
@staticmethod
|
|
569
679
|
def graph_cycles(graph: nx.DiGraph) -> list[list[T_Reference]]:
|
|
570
680
|
"""Returns cycles in the graph otherwise empty list"""
|
|
571
681
|
return [candidate for candidate in nx.simple_cycles(graph) if len(candidate) > 1]
|
|
682
|
+
|
|
683
|
+
@cached_property
|
|
684
|
+
def optimized_requires_constraint_graph(self) -> nx.DiGraph:
|
|
685
|
+
"""Target state of requires constraints after optimizing (MST + fixed constraints)."""
|
|
686
|
+
graph = nx.DiGraph()
|
|
687
|
+
graph.add_edges_from(self.oriented_mst_edges)
|
|
688
|
+
graph.add_edges_from(self._fixed_constraint_graph.edges())
|
|
689
|
+
return graph
|
|
690
|
+
|
|
691
|
+
@cached_property
|
|
692
|
+
def _requires_candidate_graph(self) -> nx.Graph:
|
|
693
|
+
"""Build weighted candidate graph for requires constraints.
|
|
694
|
+
|
|
695
|
+
Contains all container pairs that appear together in any view, with:
|
|
696
|
+
- weight: minimum directional weight (for MST computation)
|
|
697
|
+
- preferred_direction: direction with lower weight (for tie-breaking)
|
|
698
|
+
|
|
699
|
+
This graph is used to compute per-view MSTs.
|
|
700
|
+
"""
|
|
701
|
+
G = nx.Graph()
|
|
702
|
+
|
|
703
|
+
for view_ref in self.merged.views:
|
|
704
|
+
containers = self.containers_by_view.get(view_ref, set())
|
|
705
|
+
if len(containers) < 2:
|
|
706
|
+
continue # Need at least 2 containers to form a requires constraint
|
|
707
|
+
|
|
708
|
+
# Sort for deterministic preferred_direction when weights are equal
|
|
709
|
+
for src, dst in combinations(sorted(containers, key=str), 2):
|
|
710
|
+
if G.has_edge(src, dst):
|
|
711
|
+
continue # Already added from another view
|
|
712
|
+
|
|
713
|
+
w1 = self._compute_requires_edge_weight(src, dst)
|
|
714
|
+
w2 = self._compute_requires_edge_weight(dst, src)
|
|
715
|
+
direction = (src, dst) if w1 <= w2 else (dst, src)
|
|
716
|
+
weight = min(w1, w2)
|
|
717
|
+
|
|
718
|
+
G.add_edge(src, dst, weight=weight, preferred_direction=direction)
|
|
719
|
+
|
|
720
|
+
return G
|
|
721
|
+
|
|
722
|
+
@cached_property
|
|
723
|
+
def _mst_by_view(self) -> dict[ViewReference, nx.Graph]:
|
|
724
|
+
"""Compute per-view MST graphs.
|
|
725
|
+
|
|
726
|
+
Each view gets its own MST over just its containers. This ensures:
|
|
727
|
+
- No routing through containers not in the view
|
|
728
|
+
- Each view gets exactly the edges it needs
|
|
729
|
+
- Voting handles orientation conflicts between views
|
|
730
|
+
|
|
731
|
+
Skips inherently unsolvable views (no immutable anchor + all modifiables are roots).
|
|
732
|
+
"""
|
|
733
|
+
if not self._requires_candidate_graph:
|
|
734
|
+
return {}
|
|
735
|
+
|
|
736
|
+
result: dict[ViewReference, nx.Graph] = {}
|
|
737
|
+
|
|
738
|
+
for view_ref in self.merged.views:
|
|
739
|
+
if view_ref in self._views_with_root_conflicts:
|
|
740
|
+
continue
|
|
741
|
+
|
|
742
|
+
containers = self.containers_by_view.get(view_ref, set())
|
|
743
|
+
if len(containers) < 2: # Need at least 2 containers to have a constraint
|
|
744
|
+
continue
|
|
745
|
+
if not containers.intersection(self.modifiable_containers):
|
|
746
|
+
continue
|
|
747
|
+
|
|
748
|
+
subgraph = self._requires_candidate_graph.subgraph(containers)
|
|
749
|
+
if not nx.is_connected(subgraph):
|
|
750
|
+
continue
|
|
751
|
+
|
|
752
|
+
result[view_ref] = nx.minimum_spanning_tree(subgraph, weight="weight")
|
|
753
|
+
|
|
754
|
+
return result
|
|
755
|
+
|
|
756
|
+
@cached_property
|
|
757
|
+
def _root_by_view(self) -> dict[ViewReference, ContainerReference]:
|
|
758
|
+
"""Map each view (with 2+ containers) to its most view-specific (root) container.
|
|
759
|
+
|
|
760
|
+
Only includes views with 2+ containers since single-container views
|
|
761
|
+
are trivially satisfied and don't need root direction.
|
|
762
|
+
|
|
763
|
+
Selection criteria (in priority order):
|
|
764
|
+
1. Fewest views: Containers appearing in fewer views are more "view-specific"
|
|
765
|
+
2. Has existing constraint: Prefer containers with existing outgoing constraints
|
|
766
|
+
3. Alphabetical: Deterministic tie-breaker
|
|
767
|
+
"""
|
|
768
|
+
result: dict[ViewReference, ContainerReference] = {}
|
|
769
|
+
|
|
770
|
+
for view, containers in self.containers_by_view.items():
|
|
771
|
+
if len(containers) < 2:
|
|
772
|
+
continue
|
|
773
|
+
|
|
774
|
+
modifiable = containers.intersection(self.modifiable_containers)
|
|
775
|
+
if not modifiable:
|
|
776
|
+
continue
|
|
777
|
+
|
|
778
|
+
# Selection priority: fewest views, has existing constraint, alphabetical
|
|
779
|
+
result[view] = min(
|
|
780
|
+
modifiable,
|
|
781
|
+
key=lambda c: (
|
|
782
|
+
len(self.views_by_container.get(c, set())),
|
|
783
|
+
0 if any((c, other) in self._existing_requires_edges for other in containers) else 1,
|
|
784
|
+
str(c),
|
|
785
|
+
),
|
|
786
|
+
)
|
|
787
|
+
|
|
788
|
+
return result
|
|
789
|
+
|
|
790
|
+
@cached_property
|
|
791
|
+
def _views_with_root_conflicts(self) -> set[ViewReference]:
|
|
792
|
+
"""Views where all modifiable containers are forced roots for other views.
|
|
793
|
+
|
|
794
|
+
A view has root conflicts if:
|
|
795
|
+
1. It has no immutable containers (no shared CDM anchor)
|
|
796
|
+
2. All its modifiable containers are already forced roots for other views
|
|
797
|
+
|
|
798
|
+
Such views would require edges between forced roots, causing conflicts.
|
|
799
|
+
"""
|
|
800
|
+
forced_roots = set(self._root_by_view.values())
|
|
801
|
+
unsolvable: set[ViewReference] = set()
|
|
802
|
+
|
|
803
|
+
for view, containers in self.containers_by_view.items():
|
|
804
|
+
modifiable = containers & self.modifiable_containers
|
|
805
|
+
immutable = containers - self.modifiable_containers
|
|
806
|
+
|
|
807
|
+
# Need at least 2 modifiable containers to have a conflict
|
|
808
|
+
if len(modifiable) < 2:
|
|
809
|
+
continue
|
|
810
|
+
|
|
811
|
+
# No immutable anchor AND all modifiables are roots elsewhere
|
|
812
|
+
if not immutable and modifiable <= forced_roots:
|
|
813
|
+
unsolvable.add(view)
|
|
814
|
+
|
|
815
|
+
return unsolvable
|
|
816
|
+
|
|
817
|
+
@cached_property
|
|
818
|
+
def oriented_mst_edges(self) -> set[tuple[ContainerReference, ContainerReference]]:
|
|
819
|
+
"""Orient per-view MST edges by voting across views.
|
|
820
|
+
|
|
821
|
+
Each view votes for edge orientations based on BFS from its root container.
|
|
822
|
+
Views with only 1 modifiable container use 'inf' vote weight to force
|
|
823
|
+
that container as root.
|
|
824
|
+
|
|
825
|
+
Tie-breaker: preferred_direction from weight function.
|
|
826
|
+
|
|
827
|
+
Returns set of directed (src, dst) tuples.
|
|
828
|
+
"""
|
|
829
|
+
edge_votes: dict[tuple[ContainerReference, ContainerReference], float] = defaultdict(float)
|
|
830
|
+
all_edges: set[tuple[ContainerReference, ContainerReference]] = set()
|
|
831
|
+
|
|
832
|
+
# Sort for deterministic iteration (dict order can vary with hash randomization)
|
|
833
|
+
for view in sorted(self._mst_by_view.keys(), key=str):
|
|
834
|
+
mst = self._mst_by_view[view]
|
|
835
|
+
root = self._root_by_view[view] # Always exists for views in _mst_by_view
|
|
836
|
+
containers = self.containers_by_view.get(view, set())
|
|
837
|
+
modifiable_count = len(containers & self.modifiable_containers)
|
|
838
|
+
# Views with only 1 modifiable container have no choice - that container MUST be root
|
|
839
|
+
vote_weight = float("inf") if modifiable_count == 1 else 1.0
|
|
840
|
+
|
|
841
|
+
# BFS from root orients edges away from root (parent → child)
|
|
842
|
+
for parent, child in nx.bfs_edges(mst, root): # type: ignore[func-returns-value]
|
|
843
|
+
if parent in self.modifiable_containers:
|
|
844
|
+
edge_votes[(parent, child)] += vote_weight
|
|
845
|
+
|
|
846
|
+
# Normalize edges to canonical form so votes for same undirected edge are counted together
|
|
847
|
+
for c1, c2 in mst.edges():
|
|
848
|
+
all_edges.add((c1, c2) if str(c1) < str(c2) else (c2, c1))
|
|
849
|
+
|
|
850
|
+
# Pick direction: most votes wins, preferred_direction breaks ties
|
|
851
|
+
oriented: set[tuple[ContainerReference, ContainerReference]] = set()
|
|
852
|
+
|
|
853
|
+
# Sort for deterministic iteration (hash randomization affects set order)
|
|
854
|
+
for c1, c2 in sorted(all_edges, key=lambda e: (str(e[0]), str(e[1]))):
|
|
855
|
+
c1_votes = edge_votes.get((c1, c2), 0)
|
|
856
|
+
c2_votes = edge_votes.get((c2, c1), 0)
|
|
857
|
+
|
|
858
|
+
if c1_votes > c2_votes:
|
|
859
|
+
oriented.add((c1, c2))
|
|
860
|
+
elif c2_votes > c1_votes:
|
|
861
|
+
oriented.add((c2, c1))
|
|
862
|
+
else:
|
|
863
|
+
# Tie-breaker: use preferred_direction from weight function
|
|
864
|
+
oriented.add(self._requires_candidate_graph[c1][c2].get("preferred_direction", (c1, c2)))
|
|
865
|
+
|
|
866
|
+
return oriented
|
|
867
|
+
|
|
868
|
+
@cached_property
|
|
869
|
+
def _transitively_reduced_edges(self) -> set[tuple[ContainerReference, ContainerReference]]:
|
|
870
|
+
"""Reduce MST edges to minimal necessary set (remove edges with alternative paths via immutable)."""
|
|
871
|
+
if not self.oriented_mst_edges:
|
|
872
|
+
return set()
|
|
873
|
+
|
|
874
|
+
# Optimal graph = MST + immutable + user-intentional (these provide existing paths)
|
|
875
|
+
optimal = nx.DiGraph()
|
|
876
|
+
optimal.add_edges_from(self.immutable_requires_constraint_graph.edges())
|
|
877
|
+
optimal.add_edges_from(self._user_intentional_constraints)
|
|
878
|
+
optimal.add_edges_from(self.oriented_mst_edges)
|
|
879
|
+
|
|
880
|
+
reduced = nx.transitive_reduction(optimal)
|
|
881
|
+
|
|
882
|
+
# Return MST edges that survive reduction
|
|
883
|
+
return {e for e in reduced.edges() if e in self.oriented_mst_edges}
|
|
884
|
+
|
|
885
|
+
def get_requires_changes_for_view(self, view: ViewReference) -> RequiresChangesForView:
|
|
886
|
+
"""Get requires constraint changes needed to optimize a view.
|
|
887
|
+
|
|
888
|
+
Returns a RequiresChangesForView with:
|
|
889
|
+
- to_add: New constraints needed where source is mapped in this view
|
|
890
|
+
- to_remove: Existing constraints that are redundant or wrongly oriented
|
|
891
|
+
- status: The optimization status for this view
|
|
892
|
+
"""
|
|
893
|
+
modifiable_containers_in_view = self.containers_by_view.get(view, set()).intersection(
|
|
894
|
+
self.modifiable_containers
|
|
895
|
+
)
|
|
896
|
+
if not modifiable_containers_in_view:
|
|
897
|
+
return RequiresChangesForView(set(), set(), RequiresChangeStatus.NO_MODIFIABLE_CONTAINERS)
|
|
898
|
+
|
|
899
|
+
# Early exit for inherently unsolvable views (no CDM anchor + all modifiables are roots)
|
|
900
|
+
if view in self._views_with_root_conflicts:
|
|
901
|
+
return RequiresChangesForView(
|
|
902
|
+
set[tuple[ContainerReference, ContainerReference]](), set(), RequiresChangeStatus.UNSOLVABLE
|
|
903
|
+
)
|
|
904
|
+
|
|
905
|
+
# Filter edges to those where source is in this view's modifiable containers
|
|
906
|
+
existing_from_view = {
|
|
907
|
+
edge for edge in self._existing_requires_edges if edge[0] in modifiable_containers_in_view
|
|
908
|
+
}
|
|
909
|
+
optimal_for_view = {
|
|
910
|
+
edge for edge in self._transitively_reduced_edges if edge[0] in modifiable_containers_in_view
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
to_add = optimal_for_view - existing_from_view
|
|
914
|
+
|
|
915
|
+
# To remove: existing edges with wrong direction or not in MST (and not needed externally)
|
|
916
|
+
# But NEVER remove user-intentional constraints (manually defined, no __auto postfix)
|
|
917
|
+
to_remove: set[tuple[ContainerReference, ContainerReference]] = set()
|
|
918
|
+
for src, dst in existing_from_view:
|
|
919
|
+
# Skip user-intentional constraints - they were set by the user on purpose
|
|
920
|
+
if (src, dst) in self._user_intentional_constraints:
|
|
921
|
+
continue
|
|
922
|
+
if (dst, src) in self.oriented_mst_edges:
|
|
923
|
+
to_remove.add((src, dst)) # Always remove if opposite direction from optimal solution
|
|
924
|
+
elif (src, dst) not in self.oriented_mst_edges and not (
|
|
925
|
+
self.find_views_mapping_to_containers([src, dst]) - set(self.merged.views)
|
|
926
|
+
):
|
|
927
|
+
to_remove.add((src, dst)) # Remove if not in optimal solution and not needed by external views
|
|
928
|
+
|
|
929
|
+
# Check solvability in optimized state
|
|
930
|
+
if not self.forms_directed_path(
|
|
931
|
+
self.containers_by_view.get(view, set()), self.optimized_requires_constraint_graph
|
|
932
|
+
):
|
|
933
|
+
return RequiresChangesForView(set(), set(), RequiresChangeStatus.UNSOLVABLE)
|
|
934
|
+
|
|
935
|
+
if not to_add and not to_remove:
|
|
936
|
+
return RequiresChangesForView(set(), set(), RequiresChangeStatus.OPTIMAL)
|
|
937
|
+
|
|
938
|
+
return RequiresChangesForView(to_add, to_remove, RequiresChangeStatus.CHANGES_AVAILABLE)
|
|
939
|
+
|
|
940
|
+
# ========================================================================
|
|
941
|
+
# REQUIRES CONSTRAINT MST WEIGHT CONSTANTS
|
|
942
|
+
# ========================================================================
|
|
943
|
+
# Weight = TIER + sub_weight.
|
|
944
|
+
#
|
|
945
|
+
# WHY THIS ENCODING:
|
|
946
|
+
# MST algorithm only support scalar weights, but we need a strict priority
|
|
947
|
+
# hierarchy where USER→USER ALWAYS beats USER→EXTERNAL. By using a large
|
|
948
|
+
# gap (1000) between tiers, sub-weights (max ~50) can never cause a lower
|
|
949
|
+
# tier to beat a higher tier.
|
|
950
|
+
#
|
|
951
|
+
# Tiers (explicit priority order):
|
|
952
|
+
# - Tier 1 (USER→USER): Both containers modifiable - always preferred
|
|
953
|
+
# - Tier 2 (USER→EXTERNAL): Target is CDF/CDM - only when needed
|
|
954
|
+
# - Tier ∞ (FORBIDDEN): Invalid edge, forms cycle or source is not modifiable
|
|
955
|
+
#
|
|
956
|
+
# Sub-weights refine ordering WITHIN a tier (shared views, direction, etc).
|
|
957
|
+
# - These have been empirically tuned through trial and error.
|
|
958
|
+
# ========================================================================
|
|
959
|
+
|
|
960
|
+
# Tier base weights (gap of 1000 ensures tier always wins)
|
|
961
|
+
_TIER_USER_TO_USER = 1000
|
|
962
|
+
_TIER_USER_TO_EXTERNAL = 2000
|
|
963
|
+
_TIER_FORBIDDEN = math.inf
|
|
964
|
+
|
|
965
|
+
# Sub-weight adjustments (applied within tier, max ~100)
|
|
966
|
+
_BONUS_SHARED_VIEWS_PER = 5 # Per shared view (max 5 views → 25)
|
|
967
|
+
_BONUS_SHARED_VIEWS_MAX = 25
|
|
968
|
+
_BONUS_COVERAGE_PER = 5 # Per descendant via immutable edges (max 3 → 15)
|
|
969
|
+
_BONUS_COVERAGE_MAX = 15
|
|
970
|
+
_PENALTY_VIEW_COUNT = 10 # When src is in more views than dst
|
|
971
|
+
|
|
972
|
+
# Tie-breaker for deterministic ordering
|
|
973
|
+
_TIE_BREAKER_DIVISOR = 1e9
|
|
974
|
+
|
|
975
|
+
def _compute_requires_edge_weight(self, src: ContainerReference, dst: ContainerReference) -> float:
|
|
976
|
+
"""Compute the weight/cost of adding edge src → dst.
|
|
977
|
+
|
|
978
|
+
Returns TIER + sub_weight where tier dominates (gap of 1000).
|
|
979
|
+
Sub-weights refine ordering within a tier based on shared views, direction, coverage.
|
|
980
|
+
"""
|
|
981
|
+
# Opposite direction of fixed constraints is forbidden (would conflict with existing path)
|
|
982
|
+
if src in self._fixed_descendants[dst]:
|
|
983
|
+
return self._TIER_FORBIDDEN
|
|
984
|
+
|
|
985
|
+
if src not in self.modifiable_containers:
|
|
986
|
+
return self._TIER_FORBIDDEN
|
|
987
|
+
|
|
988
|
+
src_views = self.views_by_container.get(src, set())
|
|
989
|
+
dst_views = self.views_by_container.get(dst, set())
|
|
990
|
+
|
|
991
|
+
# Sub-weight adjustments
|
|
992
|
+
shared_bonus = min(len(src_views & dst_views) * self._BONUS_SHARED_VIEWS_PER, self._BONUS_SHARED_VIEWS_MAX)
|
|
993
|
+
coverage_bonus = min(len(self._fixed_descendants[dst]) * self._BONUS_COVERAGE_PER, self._BONUS_COVERAGE_MAX)
|
|
994
|
+
view_penalty = self._PENALTY_VIEW_COUNT if len(src_views) > len(dst_views) else 0
|
|
995
|
+
|
|
996
|
+
# Deterministic tie-breaker (very small, only matters when all else is equal)
|
|
997
|
+
edge_str = f"{src.space}:{src.external_id}->{dst.space}:{dst.external_id}"
|
|
998
|
+
tie_breaker = sum(ord(c) for c in edge_str) / self._TIE_BREAKER_DIVISOR
|
|
999
|
+
|
|
1000
|
+
if dst in self.modifiable_containers:
|
|
1001
|
+
return self._TIER_USER_TO_USER - shared_bonus - coverage_bonus + view_penalty + tie_breaker
|
|
1002
|
+
|
|
1003
|
+
return self._TIER_USER_TO_EXTERNAL - shared_bonus - coverage_bonus + tie_breaker
|