cognite-neat 0.123.26__py3-none-any.whl → 1.0.22__py3-none-any.whl
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/__init__.py +4 -3
- cognite/neat/_client/__init__.py +5 -0
- cognite/neat/_client/api.py +8 -0
- cognite/neat/_client/client.py +21 -0
- cognite/neat/_client/config.py +40 -0
- cognite/neat/_client/containers_api.py +138 -0
- cognite/neat/_client/data_classes.py +44 -0
- cognite/neat/_client/data_model_api.py +115 -0
- cognite/neat/_client/init/credentials.py +70 -0
- cognite/neat/_client/init/env_vars.py +131 -0
- cognite/neat/_client/init/main.py +51 -0
- cognite/neat/_client/spaces_api.py +115 -0
- cognite/neat/_client/statistics_api.py +24 -0
- cognite/neat/_client/views_api.py +144 -0
- cognite/neat/_config.py +266 -0
- cognite/neat/_data_model/_analysis.py +571 -0
- cognite/neat/_data_model/_constants.py +74 -0
- cognite/neat/_data_model/_identifiers.py +61 -0
- cognite/neat/_data_model/_shared.py +41 -0
- cognite/neat/_data_model/_snapshot.py +134 -0
- cognite/neat/_data_model/deployer/_differ.py +140 -0
- cognite/neat/_data_model/deployer/_differ_container.py +360 -0
- cognite/neat/_data_model/deployer/_differ_data_model.py +54 -0
- cognite/neat/_data_model/deployer/_differ_space.py +9 -0
- cognite/neat/_data_model/deployer/_differ_view.py +299 -0
- cognite/neat/_data_model/deployer/data_classes.py +644 -0
- cognite/neat/_data_model/deployer/deployer.py +431 -0
- cognite/neat/_data_model/exporters/__init__.py +15 -0
- cognite/neat/_data_model/exporters/_api_exporter.py +37 -0
- cognite/neat/_data_model/exporters/_base.py +24 -0
- cognite/neat/_data_model/exporters/_table_exporter/exporter.py +128 -0
- cognite/neat/_data_model/exporters/_table_exporter/workbook.py +409 -0
- cognite/neat/_data_model/exporters/_table_exporter/writer.py +480 -0
- cognite/neat/_data_model/importers/__init__.py +5 -0
- cognite/neat/_data_model/importers/_api_importer.py +166 -0
- cognite/neat/_data_model/importers/_base.py +16 -0
- cognite/neat/_data_model/importers/_table_importer/data_classes.py +344 -0
- cognite/neat/_data_model/importers/_table_importer/importer.py +192 -0
- cognite/neat/_data_model/importers/_table_importer/reader.py +1102 -0
- cognite/neat/_data_model/importers/_table_importer/source.py +94 -0
- cognite/neat/_data_model/models/conceptual/_base.py +18 -0
- cognite/neat/_data_model/models/conceptual/_concept.py +67 -0
- cognite/neat/_data_model/models/conceptual/_data_model.py +51 -0
- cognite/neat/_data_model/models/conceptual/_properties.py +104 -0
- cognite/neat/_data_model/models/conceptual/_property.py +105 -0
- cognite/neat/_data_model/models/dms/__init__.py +206 -0
- cognite/neat/_data_model/models/dms/_base.py +31 -0
- cognite/neat/_data_model/models/dms/_constants.py +48 -0
- cognite/neat/_data_model/models/dms/_constraints.py +42 -0
- cognite/neat/_data_model/models/dms/_container.py +159 -0
- cognite/neat/_data_model/models/dms/_data_model.py +95 -0
- cognite/neat/_data_model/models/dms/_data_types.py +195 -0
- cognite/neat/_data_model/models/dms/_http.py +28 -0
- cognite/neat/_data_model/models/dms/_indexes.py +30 -0
- cognite/neat/_data_model/models/dms/_limits.py +96 -0
- cognite/neat/_data_model/models/dms/_references.py +141 -0
- cognite/neat/_data_model/models/dms/_schema.py +18 -0
- cognite/neat/_data_model/models/dms/_space.py +48 -0
- cognite/neat/_data_model/models/dms/_types.py +17 -0
- cognite/neat/_data_model/models/dms/_view_filter.py +310 -0
- cognite/neat/_data_model/models/dms/_view_property.py +235 -0
- cognite/neat/_data_model/models/dms/_views.py +216 -0
- cognite/neat/_data_model/models/entities/__init__.py +50 -0
- cognite/neat/_data_model/models/entities/_base.py +101 -0
- cognite/neat/_data_model/models/entities/_constants.py +22 -0
- cognite/neat/_data_model/models/entities/_data_types.py +144 -0
- cognite/neat/_data_model/models/entities/_identifiers.py +61 -0
- cognite/neat/_data_model/models/entities/_parser.py +226 -0
- cognite/neat/_data_model/validation/dms/__init__.py +75 -0
- cognite/neat/_data_model/validation/dms/_ai_readiness.py +381 -0
- cognite/neat/_data_model/validation/dms/_base.py +25 -0
- cognite/neat/_data_model/validation/dms/_connections.py +681 -0
- cognite/neat/_data_model/validation/dms/_consistency.py +58 -0
- cognite/neat/_data_model/validation/dms/_containers.py +199 -0
- cognite/neat/_data_model/validation/dms/_limits.py +368 -0
- cognite/neat/_data_model/validation/dms/_orchestrator.py +70 -0
- cognite/neat/_data_model/validation/dms/_views.py +164 -0
- cognite/neat/_exceptions.py +68 -0
- cognite/neat/_issues.py +68 -0
- cognite/neat/_session/__init__.py +3 -0
- cognite/neat/_session/_html/_render.py +30 -0
- cognite/neat/_session/_html/static/__init__.py +8 -0
- cognite/neat/_session/_html/static/deployment.css +476 -0
- cognite/neat/_session/_html/static/deployment.js +181 -0
- cognite/neat/_session/_html/static/issues.css +211 -0
- cognite/neat/_session/_html/static/issues.js +168 -0
- cognite/neat/_session/_html/static/shared.css +186 -0
- cognite/neat/_session/_html/templates/__init__.py +4 -0
- cognite/neat/_session/_html/templates/deployment.html +80 -0
- cognite/neat/_session/_html/templates/issues.html +45 -0
- cognite/neat/_session/_issues.py +81 -0
- cognite/neat/_session/_physical.py +294 -0
- cognite/neat/_session/_result/__init__.py +3 -0
- cognite/neat/_session/_result/_deployment/__init__.py +0 -0
- cognite/neat/_session/_result/_deployment/_physical/__init__.py +0 -0
- cognite/neat/_session/_result/_deployment/_physical/_changes.py +196 -0
- cognite/neat/_session/_result/_deployment/_physical/_statistics.py +180 -0
- cognite/neat/_session/_result/_deployment/_physical/serializer.py +35 -0
- cognite/neat/_session/_result/_result.py +31 -0
- cognite/neat/_session/_session.py +81 -0
- cognite/neat/_session/_usage_analytics/__init__.py +0 -0
- cognite/neat/_session/_usage_analytics/_collector.py +131 -0
- cognite/neat/_session/_usage_analytics/_constants.py +23 -0
- cognite/neat/_session/_usage_analytics/_storage.py +240 -0
- cognite/neat/_session/_wrappers.py +101 -0
- cognite/neat/_state_machine/__init__.py +10 -0
- cognite/neat/_state_machine/_base.py +37 -0
- cognite/neat/_state_machine/_states.py +52 -0
- cognite/neat/_store/__init__.py +3 -0
- cognite/neat/_store/_provenance.py +88 -0
- cognite/neat/_store/_store.py +220 -0
- cognite/neat/_utils/__init__.py +0 -0
- cognite/neat/_utils/_reader.py +194 -0
- cognite/neat/_utils/auxiliary.py +49 -0
- cognite/neat/_utils/collection.py +11 -0
- cognite/neat/_utils/http_client/__init__.py +39 -0
- cognite/neat/_utils/http_client/_client.py +245 -0
- cognite/neat/_utils/http_client/_config.py +19 -0
- cognite/neat/_utils/http_client/_data_classes.py +294 -0
- cognite/neat/_utils/http_client/_tracker.py +31 -0
- cognite/neat/_utils/repo.py +19 -0
- cognite/neat/_utils/text.py +71 -0
- cognite/neat/_utils/useful_types.py +37 -0
- cognite/neat/_utils/validation.py +154 -0
- cognite/neat/_v0/__init__.py +0 -0
- cognite/neat/_v0/core/__init__.py +0 -0
- cognite/neat/_v0/core/_client/_api/__init__.py +0 -0
- cognite/neat/{core → _v0/core}/_client/_api/data_modeling_loaders.py +8 -7
- cognite/neat/{core → _v0/core}/_client/_api/neat_instances.py +5 -5
- cognite/neat/{core → _v0/core}/_client/_api/schema.py +5 -5
- cognite/neat/{core → _v0/core}/_client/_api/statistics.py +3 -3
- cognite/neat/{core → _v0/core}/_client/_api_client.py +1 -1
- cognite/neat/_v0/core/_client/data_classes/__init__.py +0 -0
- cognite/neat/{core → _v0/core}/_client/data_classes/schema.py +4 -4
- cognite/neat/{core → _v0/core}/_client/testing.py +1 -1
- cognite/neat/{core → _v0/core}/_constants.py +5 -3
- cognite/neat/_v0/core/_data_model/__init__.py +0 -0
- cognite/neat/{core → _v0/core}/_data_model/_constants.py +7 -0
- cognite/neat/{core → _v0/core}/_data_model/_shared.py +4 -4
- cognite/neat/{core → _v0/core}/_data_model/analysis/_base.py +8 -8
- cognite/neat/{core → _v0/core}/_data_model/exporters/__init__.py +1 -2
- cognite/neat/{core → _v0/core}/_data_model/exporters/_base.py +7 -7
- cognite/neat/{core → _v0/core}/_data_model/exporters/_data_model2dms.py +9 -9
- cognite/neat/{core → _v0/core}/_data_model/exporters/_data_model2excel.py +12 -12
- cognite/neat/{core → _v0/core}/_data_model/exporters/_data_model2instance_template.py +4 -4
- cognite/neat/{core/_data_model/exporters/_data_model2ontology.py → _v0/core/_data_model/exporters/_data_model2semantic_model.py} +126 -116
- cognite/neat/{core → _v0/core}/_data_model/exporters/_data_model2yaml.py +1 -1
- cognite/neat/{core → _v0/core}/_data_model/importers/_base.py +5 -5
- cognite/neat/{core → _v0/core}/_data_model/importers/_base_file_reader.py +2 -2
- cognite/neat/{core → _v0/core}/_data_model/importers/_dict2data_model.py +5 -5
- cognite/neat/{core → _v0/core}/_data_model/importers/_dms2data_model.py +18 -15
- cognite/neat/{core → _v0/core}/_data_model/importers/_graph2data_model.py +12 -12
- cognite/neat/{core → _v0/core}/_data_model/importers/_rdf/_base.py +12 -12
- cognite/neat/{core → _v0/core}/_data_model/importers/_rdf/_inference2rdata_model.py +14 -14
- cognite/neat/{core → _v0/core}/_data_model/importers/_rdf/_owl2data_model.py +41 -21
- cognite/neat/{core → _v0/core}/_data_model/importers/_rdf/_shared.py +9 -9
- cognite/neat/{core → _v0/core}/_data_model/importers/_spreadsheet2data_model.py +92 -12
- cognite/neat/{core → _v0/core}/_data_model/models/__init__.py +3 -3
- cognite/neat/{core → _v0/core}/_data_model/models/_base_verified.py +5 -5
- cognite/neat/{core → _v0/core}/_data_model/models/_import_contexts.py +1 -1
- cognite/neat/{core → _v0/core}/_data_model/models/_types.py +5 -5
- cognite/neat/{core → _v0/core}/_data_model/models/conceptual/_unverified.py +16 -10
- cognite/neat/{core → _v0/core}/_data_model/models/conceptual/_validation.py +12 -12
- cognite/neat/{core → _v0/core}/_data_model/models/conceptual/_verified.py +9 -9
- cognite/neat/{core → _v0/core}/_data_model/models/data_types.py +14 -4
- cognite/neat/{core → _v0/core}/_data_model/models/entities/__init__.py +6 -0
- cognite/neat/_v0/core/_data_model/models/entities/_loaders.py +155 -0
- cognite/neat/{core → _v0/core}/_data_model/models/entities/_multi_value.py +2 -2
- cognite/neat/_v0/core/_data_model/models/entities/_restrictions.py +230 -0
- cognite/neat/{core → _v0/core}/_data_model/models/entities/_single_value.py +121 -16
- cognite/neat/{core → _v0/core}/_data_model/models/entities/_types.py +10 -0
- cognite/neat/{core → _v0/core}/_data_model/models/mapping/_classic2core.py +5 -5
- cognite/neat/{core → _v0/core}/_data_model/models/physical/__init__.py +1 -1
- cognite/neat/{core → _v0/core}/_data_model/models/physical/_exporter.py +26 -19
- cognite/neat/{core → _v0/core}/_data_model/models/physical/_unverified.py +133 -37
- cognite/neat/{core → _v0/core}/_data_model/models/physical/_validation.py +24 -20
- cognite/neat/{core → _v0/core}/_data_model/models/physical/_verified.py +95 -24
- cognite/neat/{core → _v0/core}/_data_model/transformers/_base.py +4 -4
- cognite/neat/{core → _v0/core}/_data_model/transformers/_converters.py +35 -28
- cognite/neat/{core → _v0/core}/_data_model/transformers/_mapping.py +7 -7
- cognite/neat/{core → _v0/core}/_data_model/transformers/_union_conceptual.py +5 -5
- cognite/neat/{core → _v0/core}/_data_model/transformers/_verification.py +7 -7
- cognite/neat/_v0/core/_instances/__init__.py +0 -0
- cognite/neat/{core → _v0/core}/_instances/_tracking/base.py +1 -1
- cognite/neat/{core → _v0/core}/_instances/_tracking/log.py +1 -1
- cognite/neat/{core → _v0/core}/_instances/extractors/__init__.py +3 -2
- cognite/neat/{core → _v0/core}/_instances/extractors/_base.py +6 -6
- cognite/neat/_v0/core/_instances/extractors/_classic_cdf/__init__.py +0 -0
- cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_base.py +7 -7
- cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_classic.py +12 -12
- cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_relationships.py +3 -3
- cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_sequences.py +2 -2
- cognite/neat/{core → _v0/core}/_instances/extractors/_dict.py +6 -3
- cognite/neat/{core → _v0/core}/_instances/extractors/_dms.py +6 -6
- cognite/neat/{core → _v0/core}/_instances/extractors/_dms_graph.py +11 -11
- cognite/neat/{core → _v0/core}/_instances/extractors/_mock_graph_generator.py +10 -10
- cognite/neat/{core → _v0/core}/_instances/extractors/_raw.py +3 -3
- cognite/neat/{core → _v0/core}/_instances/extractors/_rdf_file.py +7 -7
- cognite/neat/{core → _v0/core}/_instances/loaders/_base.py +5 -5
- cognite/neat/{core → _v0/core}/_instances/loaders/_rdf2dms.py +17 -17
- cognite/neat/{core → _v0/core}/_instances/loaders/_rdf_to_instance_space.py +11 -11
- cognite/neat/{core → _v0/core}/_instances/queries/_select.py +29 -3
- cognite/neat/{core → _v0/core}/_instances/queries/_update.py +1 -1
- cognite/neat/{core → _v0/core}/_instances/transformers/_base.py +4 -4
- cognite/neat/{core → _v0/core}/_instances/transformers/_classic_cdf.py +6 -6
- cognite/neat/{core → _v0/core}/_instances/transformers/_prune_graph.py +4 -4
- cognite/neat/{core → _v0/core}/_instances/transformers/_rdfpath.py +1 -1
- cognite/neat/{core → _v0/core}/_instances/transformers/_value_type.py +4 -4
- cognite/neat/{core → _v0/core}/_issues/_base.py +5 -5
- cognite/neat/{core → _v0/core}/_issues/_contextmanagers.py +1 -1
- cognite/neat/{core → _v0/core}/_issues/_factory.py +3 -3
- cognite/neat/{core → _v0/core}/_issues/errors/__init__.py +1 -1
- cognite/neat/{core → _v0/core}/_issues/errors/_external.py +1 -1
- cognite/neat/{core → _v0/core}/_issues/errors/_general.py +1 -1
- cognite/neat/{core → _v0/core}/_issues/errors/_properties.py +1 -1
- cognite/neat/{core → _v0/core}/_issues/errors/_resources.py +2 -2
- cognite/neat/{core → _v0/core}/_issues/errors/_wrapper.py +7 -3
- cognite/neat/{core → _v0/core}/_issues/warnings/__init__.py +1 -1
- cognite/neat/{core → _v0/core}/_issues/warnings/_external.py +1 -1
- cognite/neat/{core → _v0/core}/_issues/warnings/_general.py +1 -1
- cognite/neat/{core → _v0/core}/_issues/warnings/_models.py +2 -2
- cognite/neat/{core → _v0/core}/_issues/warnings/_properties.py +2 -2
- cognite/neat/{core → _v0/core}/_issues/warnings/_resources.py +1 -1
- cognite/neat/{core → _v0/core}/_issues/warnings/user_modeling.py +1 -1
- cognite/neat/{core → _v0/core}/_store/_data_model.py +12 -12
- cognite/neat/{core → _v0/core}/_store/_instance.py +43 -10
- cognite/neat/{core → _v0/core}/_store/_provenance.py +3 -3
- cognite/neat/{core → _v0/core}/_store/exceptions.py +4 -4
- cognite/neat/_v0/core/_utils/__init__.py +0 -0
- cognite/neat/{core → _v0/core}/_utils/auth.py +22 -12
- cognite/neat/{core → _v0/core}/_utils/auxiliary.py +1 -1
- cognite/neat/{core → _v0/core}/_utils/collection_.py +2 -2
- cognite/neat/{core → _v0/core}/_utils/graph_transformations_report.py +1 -1
- cognite/neat/{core → _v0/core}/_utils/rdf_.py +1 -1
- cognite/neat/{core → _v0/core}/_utils/reader/_base.py +1 -1
- cognite/neat/{core → _v0/core}/_utils/spreadsheet.py +18 -4
- cognite/neat/{core → _v0/core}/_utils/text.py +1 -1
- cognite/neat/{core → _v0/core}/_utils/upload.py +3 -3
- cognite/neat/{session → _v0}/engine/_load.py +1 -1
- cognite/neat/_v0/plugins/__init__.py +4 -0
- cognite/neat/_v0/plugins/_base.py +9 -0
- cognite/neat/_v0/plugins/_data_model.py +48 -0
- cognite/neat/{plugins → _v0/plugins}/_issues.py +1 -1
- cognite/neat/{plugins → _v0/plugins}/_manager.py +7 -16
- cognite/neat/{session → _v0/session}/_base.py +13 -15
- cognite/neat/{session → _v0/session}/_collector.py +1 -1
- cognite/neat/_v0/session/_diff.py +51 -0
- cognite/neat/{session → _v0/session}/_drop.py +3 -3
- cognite/neat/{session → _v0/session}/_explore.py +2 -2
- cognite/neat/{session → _v0/session}/_fix.py +2 -2
- cognite/neat/{session → _v0/session}/_inspect.py +3 -3
- cognite/neat/{session → _v0/session}/_mapping.py +3 -3
- cognite/neat/{session → _v0/session}/_plugin.py +4 -5
- cognite/neat/{session → _v0/session}/_prepare.py +8 -8
- cognite/neat/{session → _v0/session}/_read.py +34 -21
- cognite/neat/{session → _v0/session}/_set.py +8 -8
- cognite/neat/{session → _v0/session}/_show.py +5 -5
- cognite/neat/{session → _v0/session}/_state.py +10 -10
- cognite/neat/{session → _v0/session}/_subset.py +4 -4
- cognite/neat/{session → _v0/session}/_template.py +11 -11
- cognite/neat/{session → _v0/session}/_to.py +12 -12
- cognite/neat/{session → _v0/session}/_wizard.py +1 -1
- cognite/neat/{session → _v0/session}/exceptions.py +5 -5
- cognite/neat/_version.py +1 -1
- cognite/neat/legacy.py +6 -0
- cognite_neat-1.0.22.dist-info/METADATA +123 -0
- cognite_neat-1.0.22.dist-info/RECORD +329 -0
- cognite_neat-1.0.22.dist-info/WHEEL +4 -0
- cognite/neat/core/_data_model/models/entities/_loaders.py +0 -75
- cognite/neat/plugins/__init__.py +0 -3
- cognite/neat/plugins/data_model/importers/__init__.py +0 -5
- cognite/neat/plugins/data_model/importers/_base.py +0 -28
- cognite/neat/session/_session/_data_model/__init__.py +0 -3
- cognite/neat/session/_session/_data_model/_read.py +0 -193
- cognite/neat/session/_session/_data_model/_routes.py +0 -45
- cognite/neat/session/_session/_data_model/_show.py +0 -147
- cognite/neat/session/_session/_data_model/_write.py +0 -335
- cognite_neat-0.123.26.dist-info/METADATA +0 -144
- cognite_neat-0.123.26.dist-info/RECORD +0 -201
- cognite_neat-0.123.26.dist-info/WHEEL +0 -4
- cognite_neat-0.123.26.dist-info/licenses/LICENSE +0 -201
- /cognite/neat/{core → _client/init}/__init__.py +0 -0
- /cognite/neat/{core/_client/_api → _data_model}/__init__.py +0 -0
- /cognite/neat/{core/_client/data_classes → _data_model/deployer}/__init__.py +0 -0
- /cognite/neat/{core/_data_model → _data_model/exporters/_table_exporter}/__init__.py +0 -0
- /cognite/neat/{core/_instances → _data_model/importers/_table_importer}/__init__.py +0 -0
- /cognite/neat/{core/_instances/extractors/_classic_cdf → _data_model/models}/__init__.py +0 -0
- /cognite/neat/{core/_utils → _data_model/models/conceptual}/__init__.py +0 -0
- /cognite/neat/{plugins/data_model → _data_model/validation}/__init__.py +0 -0
- /cognite/neat/{session/_session → _session/_html}/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_client/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_client/data_classes/data_modeling.py +0 -0
- /cognite/neat/{core → _v0/core}/_client/data_classes/neat_sequence.py +0 -0
- /cognite/neat/{core → _v0/core}/_client/data_classes/statistics.py +0 -0
- /cognite/neat/{core → _v0/core}/_config.py +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/analysis/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/catalog/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/catalog/classic_model.xlsx +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/catalog/conceptual-imf-data-model.xlsx +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/catalog/hello_world_pump.xlsx +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/importers/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/importers/_rdf/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/models/_base_unverified.py +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/models/conceptual/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/models/entities/_constants.py +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/models/entities/_wrapped.py +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/models/mapping/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/models/mapping/_classic2core.yaml +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/transformers/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/_shared.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/_tracking/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/examples/Knowledge-Graph-Nordic44-dirty.xml +0 -0
- /cognite/neat/{core → _v0/core}/_instances/examples/Knowledge-Graph-Nordic44.xml +0 -0
- /cognite/neat/{core → _v0/core}/_instances/examples/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/examples/skos-capturing-sheet-wind-topics.xlsx +0 -0
- /cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_assets.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_data_sets.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_events.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_files.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_labels.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_timeseries.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/loaders/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/queries/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/queries/_base.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/queries/_queries.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/transformers/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_issues/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_issues/formatters.py +0 -0
- /cognite/neat/{core → _v0/core}/_shared.py +0 -0
- /cognite/neat/{core → _v0/core}/_store/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_utils/io_.py +0 -0
- /cognite/neat/{core → _v0/core}/_utils/reader/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_utils/tarjan.py +0 -0
- /cognite/neat/{core → _v0/core}/_utils/time_.py +0 -0
- /cognite/neat/{core → _v0/core}/_utils/xml_.py +0 -0
- /cognite/neat/{session → _v0}/engine/__init__.py +0 -0
- /cognite/neat/{session → _v0}/engine/_import.py +0 -0
- /cognite/neat/{session → _v0}/engine/_interface.py +0 -0
- /cognite/neat/{session → _v0/session}/__init__.py +0 -0
- /cognite/neat/{session → _v0/session}/_experimental.py +0 -0
- /cognite/neat/{session → _v0/session}/_state/README.md +0 -0
|
@@ -0,0 +1,571 @@
|
|
|
1
|
+
from collections import defaultdict
|
|
2
|
+
from itertools import chain
|
|
3
|
+
from typing import Literal, TypeAlias, TypeVar
|
|
4
|
+
|
|
5
|
+
import networkx as nx
|
|
6
|
+
from pyparsing import cached_property
|
|
7
|
+
|
|
8
|
+
from cognite.neat._data_model._snapshot import SchemaSnapshot
|
|
9
|
+
from cognite.neat._data_model.models.dms._constraints import RequiresConstraintDefinition
|
|
10
|
+
from cognite.neat._data_model.models.dms._container import ContainerRequest
|
|
11
|
+
from cognite.neat._data_model.models.dms._data_types import DirectNodeRelation
|
|
12
|
+
from cognite.neat._data_model.models.dms._limits import SchemaLimits
|
|
13
|
+
from cognite.neat._data_model.models.dms._references import (
|
|
14
|
+
ContainerDirectReference,
|
|
15
|
+
ContainerReference,
|
|
16
|
+
ViewDirectReference,
|
|
17
|
+
ViewReference,
|
|
18
|
+
)
|
|
19
|
+
from cognite.neat._data_model.models.dms._view_property import (
|
|
20
|
+
EdgeProperty,
|
|
21
|
+
ReverseDirectRelationProperty,
|
|
22
|
+
ViewCorePropertyRequest,
|
|
23
|
+
ViewRequestProperty,
|
|
24
|
+
)
|
|
25
|
+
from cognite.neat._data_model.models.dms._views import ViewRequest
|
|
26
|
+
from cognite.neat._utils.useful_types import ModusOperandi, T_Reference
|
|
27
|
+
|
|
28
|
+
# Type aliases for better readability
|
|
29
|
+
ViewsByReference: TypeAlias = dict[ViewReference, ViewRequest]
|
|
30
|
+
ContainersByReference: TypeAlias = dict[ContainerReference, ContainerRequest]
|
|
31
|
+
AncestorsByReference: TypeAlias = dict[ViewReference, set[ViewReference]]
|
|
32
|
+
|
|
33
|
+
ReverseToDirectMapping: TypeAlias = dict[
|
|
34
|
+
tuple[ViewReference, str], tuple[ViewReference, ContainerDirectReference | ViewDirectReference]
|
|
35
|
+
]
|
|
36
|
+
ConnectionEndNodeTypes: TypeAlias = dict[tuple[ViewReference, str], ViewReference | None]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
ResourceSource = Literal["auto", "merged", "cdf", "both"]
|
|
40
|
+
|
|
41
|
+
_NodeT = TypeVar("_NodeT", ContainerReference, ViewReference)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class ValidationResources:
|
|
45
|
+
def __init__(
|
|
46
|
+
self, modus_operandi: ModusOperandi, local: SchemaSnapshot, cdf: SchemaSnapshot, limits: SchemaLimits
|
|
47
|
+
) -> None:
|
|
48
|
+
self._modus_operandi = modus_operandi
|
|
49
|
+
self.limits = limits
|
|
50
|
+
|
|
51
|
+
self.local = local
|
|
52
|
+
self.cdf = cdf
|
|
53
|
+
|
|
54
|
+
if self._modus_operandi == "additive":
|
|
55
|
+
self.merged = self.local.merge(self.cdf)
|
|
56
|
+
elif self._modus_operandi == "rebuild":
|
|
57
|
+
self.merged = local.model_copy(deep=True)
|
|
58
|
+
else:
|
|
59
|
+
raise RuntimeError(f"ValidationResources: Unknown modus_operandi: {self._modus_operandi}. This is a bug!")
|
|
60
|
+
|
|
61
|
+
# need this shortcut for easier access and also to avoid mypy to complains
|
|
62
|
+
self.merged_data_model = self.merged.data_model[next(iter(self.merged.data_model.keys()))]
|
|
63
|
+
|
|
64
|
+
# For caching of expanded views
|
|
65
|
+
self._expanded_views_cache: dict[ViewReference, ViewRequest] = {}
|
|
66
|
+
|
|
67
|
+
def select_view(
|
|
68
|
+
self, view_ref: ViewReference, property_: str | None = None, source: ResourceSource = "auto"
|
|
69
|
+
) -> ViewRequest | None:
|
|
70
|
+
"""Select view definition based on source strategy and optionally filter by property.
|
|
71
|
+
|
|
72
|
+
Selection prioritize merged view over CDF if both are available, as merged view represents the effective
|
|
73
|
+
definition which will be a result when the local schema is deployed to CDF.
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
view_ref: The view to select
|
|
78
|
+
property_: Optional property name to filter views that contain this property
|
|
79
|
+
source: The source strategy to use, options are: "auto", "local", "cdf", "both", where "auto" means
|
|
80
|
+
that the selection is driven by the modus_operandi of the validation resources.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
The selected ViewRequest or None if not found.
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
check_merged, check_cdf = self._resolve_resource_sources(view_ref, source)
|
|
87
|
+
|
|
88
|
+
merged_view = self.merged.views.get(view_ref) if check_merged else None
|
|
89
|
+
cdf_view = self.cdf.views.get(view_ref) if check_cdf else None
|
|
90
|
+
|
|
91
|
+
if property_ is None:
|
|
92
|
+
return merged_view or cdf_view
|
|
93
|
+
|
|
94
|
+
# Filtering based on the property presence
|
|
95
|
+
# Try views with the property first, then any available view where merged view is prioritized
|
|
96
|
+
candidates = chain(
|
|
97
|
+
(v for v in (merged_view, cdf_view) if v and v.properties and property_ in v.properties),
|
|
98
|
+
(v for v in (merged_view, cdf_view) if v),
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
return next(candidates, None)
|
|
102
|
+
|
|
103
|
+
def select_container(
|
|
104
|
+
self, container_ref: ContainerReference, property_: str | None = None, source: ResourceSource = "auto"
|
|
105
|
+
) -> ContainerRequest | None:
|
|
106
|
+
"""Select container definition based on source strategy and optionally filter by property.
|
|
107
|
+
|
|
108
|
+
Selection prioritize merged container over CDF if both are available, as merged container represents
|
|
109
|
+
the effective definition which will be a result when the local schema is deployed to CDF.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
container_ref: The container to select
|
|
113
|
+
property_: Optional property name to filter containers that contain this property
|
|
114
|
+
source: The source strategy to use, options are: "auto", "local", "cdf", "both", where "auto" means
|
|
115
|
+
that the selection is driven by the modus_operandi of the validation resources.
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
The selected ContainerRequest or None if not found.
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
check_merged, check_cdf = self._resolve_resource_sources(container_ref, source)
|
|
122
|
+
|
|
123
|
+
merged_container = self.merged.containers.get(container_ref) if check_merged else None
|
|
124
|
+
cdf_container = self.cdf.containers.get(container_ref) if check_cdf else None
|
|
125
|
+
|
|
126
|
+
if property_ is None:
|
|
127
|
+
return merged_container or cdf_container
|
|
128
|
+
|
|
129
|
+
# Try containers with the property first, then any available container
|
|
130
|
+
candidates = chain(
|
|
131
|
+
(c for c in (merged_container, cdf_container) if c and c.properties and property_ in c.properties),
|
|
132
|
+
(c for c in (merged_container, cdf_container) if c),
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
return next(candidates, None)
|
|
136
|
+
|
|
137
|
+
def _resolve_resource_sources(
|
|
138
|
+
self, resource_ref: ViewReference | ContainerReference, source: ResourceSource
|
|
139
|
+
) -> tuple[bool, bool]:
|
|
140
|
+
"""
|
|
141
|
+
Determine which resource sources (merged and/or CDF) to check based on the source parameter.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
resource_ref: The resource reference to check (ViewReference or ContainerReference)
|
|
145
|
+
source: The source strategy to use
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
Tuple of (check_merged, check_cdf) booleans indicating which sources to check
|
|
149
|
+
"""
|
|
150
|
+
if source == "auto":
|
|
151
|
+
# Auto mode: driven by data modeling modus (approach)
|
|
152
|
+
# If elements is in the schema space, we check merged, else we check CDF
|
|
153
|
+
|
|
154
|
+
in_schema_space = resource_ref.space == self.merged_data_model.space
|
|
155
|
+
|
|
156
|
+
if self._modus_operandi == "additive":
|
|
157
|
+
# In additive modus, schema space means local additions on top of CDF
|
|
158
|
+
# always check CDF, while do not check merged if resource is not in schema space
|
|
159
|
+
check_merged = in_schema_space
|
|
160
|
+
check_cdf = True
|
|
161
|
+
elif self._modus_operandi == "rebuild":
|
|
162
|
+
# In rebuild modus, schema space means the full desired state is in local schema (i.e., merged)
|
|
163
|
+
# you are not adding to CDF, but replacing it, so never check CDF for schema space resources
|
|
164
|
+
check_merged = in_schema_space
|
|
165
|
+
check_cdf = not in_schema_space
|
|
166
|
+
else:
|
|
167
|
+
raise RuntimeError(
|
|
168
|
+
f"_resolve_resource_sources: Unknown modus_operandi: {self._modus_operandi}. This is a bug!"
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
elif source == "merged":
|
|
172
|
+
check_merged = True
|
|
173
|
+
check_cdf = False
|
|
174
|
+
elif source == "cdf":
|
|
175
|
+
check_merged = False
|
|
176
|
+
check_cdf = True
|
|
177
|
+
elif source == "both":
|
|
178
|
+
check_merged = True
|
|
179
|
+
check_cdf = True
|
|
180
|
+
else:
|
|
181
|
+
raise RuntimeError(f"_resolve_resource_sources: Unknown source: {source}. This is a bug!")
|
|
182
|
+
|
|
183
|
+
return check_merged, check_cdf
|
|
184
|
+
|
|
185
|
+
@cached_property
|
|
186
|
+
def ancestors_by_view(self) -> dict[ViewReference, list[ViewReference]]:
|
|
187
|
+
"""
|
|
188
|
+
Create a mapping of each view to its list of ancestors.
|
|
189
|
+
|
|
190
|
+
Returns:
|
|
191
|
+
Dictionary mapping each ViewReference to its list of ancestor ViewReferences
|
|
192
|
+
"""
|
|
193
|
+
ancestors_mapping: dict[ViewReference, list[ViewReference]] = {}
|
|
194
|
+
|
|
195
|
+
if not self.merged_data_model.views:
|
|
196
|
+
return ancestors_mapping
|
|
197
|
+
|
|
198
|
+
for view in self.merged_data_model.views:
|
|
199
|
+
ancestors_mapping[view] = self.view_ancestors(view)
|
|
200
|
+
return ancestors_mapping
|
|
201
|
+
|
|
202
|
+
def view_ancestors(
|
|
203
|
+
self, offspring: ViewReference, ancestors: list[ViewReference] | None = None, source: ResourceSource = "auto"
|
|
204
|
+
) -> list[ViewReference]:
|
|
205
|
+
"""
|
|
206
|
+
Recursively find all ancestors of a given view by traversing the implements hierarchy.
|
|
207
|
+
Handles branching to explore all possible ancestor paths.
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
offspring: The view to find ancestors for
|
|
211
|
+
ancestors: Accumulated list of ancestors (used internally for recursion)
|
|
212
|
+
|
|
213
|
+
Returns:
|
|
214
|
+
List of all ancestor ViewReferences
|
|
215
|
+
"""
|
|
216
|
+
if ancestors is None:
|
|
217
|
+
ancestors = []
|
|
218
|
+
|
|
219
|
+
# Determine which view definition to use based on space and modus operandi
|
|
220
|
+
view_definition = self.select_view(view_ref=offspring, source=source)
|
|
221
|
+
|
|
222
|
+
# Base case: no view definition or no implements
|
|
223
|
+
if not view_definition or not view_definition.implements:
|
|
224
|
+
return ancestors
|
|
225
|
+
|
|
226
|
+
# Explore all parent branches
|
|
227
|
+
for parent in view_definition.implements:
|
|
228
|
+
if parent not in ancestors:
|
|
229
|
+
ancestors.append(parent)
|
|
230
|
+
# Recursively explore this branch
|
|
231
|
+
self.view_ancestors(parent, ancestors)
|
|
232
|
+
|
|
233
|
+
return ancestors
|
|
234
|
+
|
|
235
|
+
def is_ancestor(self, offspring: ViewReference, ancestor: ViewReference) -> bool:
|
|
236
|
+
return ancestor in self.view_ancestors(offspring)
|
|
237
|
+
|
|
238
|
+
def _expand_view(self, view_ref: ViewReference) -> ViewRequest | None:
|
|
239
|
+
"""Expand a view by including properties from its ancestors.
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
view_ref: The view to expand.
|
|
243
|
+
|
|
244
|
+
Returns:
|
|
245
|
+
ViewRequest with expanded properties, or None if view not found.
|
|
246
|
+
"""
|
|
247
|
+
view = self.select_view(view_ref)
|
|
248
|
+
|
|
249
|
+
if not view:
|
|
250
|
+
return None
|
|
251
|
+
|
|
252
|
+
# Create a deep copy to avoid mutating the original
|
|
253
|
+
expanded_view = view.model_copy(deep=True)
|
|
254
|
+
|
|
255
|
+
# Get all ancestor properties (oldest to newest)
|
|
256
|
+
ancestor_refs = self.view_ancestors(view_ref)
|
|
257
|
+
ancestor_properties: dict[str, ViewRequestProperty] = {}
|
|
258
|
+
|
|
259
|
+
# Collect properties from ancestors, overriding with newer ancestors properties
|
|
260
|
+
for ancestor_ref in reversed(ancestor_refs):
|
|
261
|
+
ancestor = self.select_view(ancestor_ref)
|
|
262
|
+
if ancestor and ancestor.properties:
|
|
263
|
+
ancestor_properties.update(ancestor.properties)
|
|
264
|
+
|
|
265
|
+
# Merge: ancestor properties first, then override with view's own properties
|
|
266
|
+
if ancestor_properties:
|
|
267
|
+
if not expanded_view.properties:
|
|
268
|
+
expanded_view.properties = {}
|
|
269
|
+
|
|
270
|
+
# Ancestor properties are base, view properties override
|
|
271
|
+
expanded_view.properties = {**ancestor_properties, **expanded_view.properties}
|
|
272
|
+
|
|
273
|
+
return expanded_view
|
|
274
|
+
|
|
275
|
+
def expand_view_properties(self, view_ref: ViewReference) -> ViewRequest | None:
|
|
276
|
+
"""Get a mapping of view references to their corresponding properties, both directly defined and inherited
|
|
277
|
+
from ancestor views through implements."""
|
|
278
|
+
|
|
279
|
+
if view_ref not in self._expanded_views_cache:
|
|
280
|
+
expanded_view = self._expand_view(view_ref)
|
|
281
|
+
if expanded_view:
|
|
282
|
+
self._expanded_views_cache[view_ref] = expanded_view
|
|
283
|
+
|
|
284
|
+
return self._expanded_views_cache.get(view_ref)
|
|
285
|
+
|
|
286
|
+
@cached_property
|
|
287
|
+
def referenced_containers(self) -> set[ContainerReference]:
|
|
288
|
+
"""Get a set of all container references used by the views in the local data model."""
|
|
289
|
+
|
|
290
|
+
referenced_containers: set[ContainerReference] = set()
|
|
291
|
+
|
|
292
|
+
if not self.merged_data_model.views:
|
|
293
|
+
return referenced_containers
|
|
294
|
+
|
|
295
|
+
for view_ref in self.merged_data_model.views:
|
|
296
|
+
view = self.select_view(view_ref)
|
|
297
|
+
# This should never happen, if it happens, it's a bug
|
|
298
|
+
if not view:
|
|
299
|
+
raise RuntimeError(f"referenced_containers: View {view_ref!s} not found. This is a bug!")
|
|
300
|
+
|
|
301
|
+
if not view.properties:
|
|
302
|
+
continue
|
|
303
|
+
for property_ in view.properties.values():
|
|
304
|
+
if isinstance(property_, ViewCorePropertyRequest):
|
|
305
|
+
referenced_containers.add(property_.container)
|
|
306
|
+
|
|
307
|
+
return referenced_containers
|
|
308
|
+
|
|
309
|
+
@cached_property
|
|
310
|
+
def reverse_to_direct_mapping(
|
|
311
|
+
self,
|
|
312
|
+
) -> dict[tuple[ViewReference, str], tuple[ViewReference, ContainerDirectReference | ViewDirectReference]]:
|
|
313
|
+
"""Get a mapping of reverse direct relations to their corresponding source view and 'through' property."""
|
|
314
|
+
|
|
315
|
+
bidirectional_connections: dict[
|
|
316
|
+
tuple[ViewReference, str], tuple[ViewReference, ContainerDirectReference | ViewDirectReference]
|
|
317
|
+
] = {}
|
|
318
|
+
|
|
319
|
+
if self.merged_data_model.views:
|
|
320
|
+
for view_ref in self.merged_data_model.views:
|
|
321
|
+
view = self.select_view(view_ref)
|
|
322
|
+
|
|
323
|
+
# This should never happen, if it happens, it's a bug
|
|
324
|
+
if not view:
|
|
325
|
+
raise RuntimeError(f"reverse_to_direct_mapping: View {view_ref!s} not found. This is a bug!")
|
|
326
|
+
|
|
327
|
+
if not view.properties:
|
|
328
|
+
continue
|
|
329
|
+
for prop_ref, property_ in view.properties.items():
|
|
330
|
+
# reverse direct relation
|
|
331
|
+
if isinstance(property_, ReverseDirectRelationProperty):
|
|
332
|
+
bidirectional_connections[(view_ref, prop_ref)] = (
|
|
333
|
+
property_.source,
|
|
334
|
+
property_.through,
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
return bidirectional_connections
|
|
338
|
+
|
|
339
|
+
@property
|
|
340
|
+
def connection_end_node_types(self) -> dict[tuple[ViewReference, str], ViewReference | None]:
|
|
341
|
+
"""Get a mapping of view references to their corresponding ViewRequest objects."""
|
|
342
|
+
|
|
343
|
+
connection_end_node_types: dict[tuple[ViewReference, str], ViewReference | None] = {}
|
|
344
|
+
|
|
345
|
+
if self.merged_data_model.views:
|
|
346
|
+
for view_ref in self.merged_data_model.views:
|
|
347
|
+
view = self.select_view(view_ref)
|
|
348
|
+
if not view:
|
|
349
|
+
raise RuntimeError(f"View {view_ref!s} not found. This is a bug!")
|
|
350
|
+
|
|
351
|
+
if not view.properties:
|
|
352
|
+
continue
|
|
353
|
+
|
|
354
|
+
for prop_ref, property_ in view.properties.items():
|
|
355
|
+
# direct relation
|
|
356
|
+
if isinstance(property_, ViewCorePropertyRequest):
|
|
357
|
+
# explicit set of end node type via 'source' which is View reference
|
|
358
|
+
if property_.source:
|
|
359
|
+
connection_end_node_types[(view_ref, prop_ref)] = property_.source
|
|
360
|
+
|
|
361
|
+
# implicit end node type via container property, without actual knowledge of end node type
|
|
362
|
+
elif (
|
|
363
|
+
(
|
|
364
|
+
container := self.select_container(
|
|
365
|
+
property_.container, property_.container_property_identifier
|
|
366
|
+
)
|
|
367
|
+
)
|
|
368
|
+
and (property_.container_property_identifier in container.properties)
|
|
369
|
+
and (
|
|
370
|
+
isinstance(
|
|
371
|
+
container.properties[property_.container_property_identifier].type,
|
|
372
|
+
DirectNodeRelation,
|
|
373
|
+
)
|
|
374
|
+
)
|
|
375
|
+
):
|
|
376
|
+
connection_end_node_types[(view_ref, prop_ref)] = None
|
|
377
|
+
|
|
378
|
+
# reverse direct relation
|
|
379
|
+
elif isinstance(property_, ReverseDirectRelationProperty) and property_.source:
|
|
380
|
+
connection_end_node_types[(view_ref, prop_ref)] = property_.source
|
|
381
|
+
|
|
382
|
+
# edge property
|
|
383
|
+
elif isinstance(property_, EdgeProperty) and property_.source:
|
|
384
|
+
connection_end_node_types[(view_ref, prop_ref)] = property_.source
|
|
385
|
+
|
|
386
|
+
return connection_end_node_types
|
|
387
|
+
|
|
388
|
+
@cached_property
|
|
389
|
+
def views_by_container(self) -> dict[ContainerReference, set[ViewReference]]:
|
|
390
|
+
"""Get a mapping from containers to the views that use them.
|
|
391
|
+
|
|
392
|
+
Includes views from both the merged schema and all CDF views to capture
|
|
393
|
+
container-view relationships across the entire CDF environment.
|
|
394
|
+
Uses expanded views to include inherited properties.
|
|
395
|
+
"""
|
|
396
|
+
|
|
397
|
+
# Include all unique views from merged and CDF
|
|
398
|
+
views_by_container: dict[ContainerReference, set[ViewReference]] = defaultdict(set)
|
|
399
|
+
|
|
400
|
+
# Include all unique views from merged and CDF
|
|
401
|
+
all_view_refs = set(self.merged.views.keys()) | set(self.cdf.views.keys())
|
|
402
|
+
|
|
403
|
+
for view_ref in all_view_refs:
|
|
404
|
+
# Use expanded view to include inherited properties
|
|
405
|
+
view = self.expand_view_properties(view_ref)
|
|
406
|
+
if not view:
|
|
407
|
+
continue
|
|
408
|
+
|
|
409
|
+
for container in view.used_containers:
|
|
410
|
+
views_by_container[container].add(view_ref)
|
|
411
|
+
|
|
412
|
+
return dict(views_by_container)
|
|
413
|
+
|
|
414
|
+
@cached_property
|
|
415
|
+
def containers_by_view(self) -> dict[ViewReference, set[ContainerReference]]:
|
|
416
|
+
"""Get a mapping from views to the containers they use.
|
|
417
|
+
|
|
418
|
+
Includes views from both the merged schema and all CDF views.
|
|
419
|
+
Uses expanded views to include inherited properties.
|
|
420
|
+
"""
|
|
421
|
+
containers_by_view: dict[ViewReference, set[ContainerReference]] = {}
|
|
422
|
+
|
|
423
|
+
# Include all unique views from merged and CDF
|
|
424
|
+
all_view_refs = set(self.merged.views.keys()) | set(self.cdf.views.keys())
|
|
425
|
+
|
|
426
|
+
for view_ref in all_view_refs:
|
|
427
|
+
# Use expanded view to include inherited properties
|
|
428
|
+
view = self.expand_view_properties(view_ref)
|
|
429
|
+
if view is not None:
|
|
430
|
+
containers_by_view[view_ref] = view.used_containers
|
|
431
|
+
|
|
432
|
+
return containers_by_view
|
|
433
|
+
|
|
434
|
+
def find_views_mapping_to_containers(self, containers: list[ContainerReference]) -> set[ViewReference]:
|
|
435
|
+
"""Find views that map to all specified containers.
|
|
436
|
+
|
|
437
|
+
That is, the intersection of views that use each of the specified containers.
|
|
438
|
+
|
|
439
|
+
Args:
|
|
440
|
+
containers: List of containers to check
|
|
441
|
+
|
|
442
|
+
Returns:
|
|
443
|
+
Set of views that contain all the specified containers
|
|
444
|
+
|
|
445
|
+
Example:
|
|
446
|
+
Given views V1, V2, V3 and containers C1, C2:
|
|
447
|
+
- V1 uses containers {C1, C2}
|
|
448
|
+
- V2 uses containers {C1}
|
|
449
|
+
- V3 uses containers {C2}
|
|
450
|
+
|
|
451
|
+
find_views_mapping_to_containers([C1, C2]) returns {V1}
|
|
452
|
+
find_views_mapping_to_containers([C1]) returns {V1, V2}
|
|
453
|
+
find_views_mapping_to_containers([C2]) returns {V1, V3}
|
|
454
|
+
"""
|
|
455
|
+
if not containers:
|
|
456
|
+
return set()
|
|
457
|
+
|
|
458
|
+
view_sets = [self.views_by_container.get(c, set()) for c in containers]
|
|
459
|
+
return set.intersection(*view_sets)
|
|
460
|
+
|
|
461
|
+
@cached_property
|
|
462
|
+
def implements_graph(self) -> nx.DiGraph:
|
|
463
|
+
"""Build a weighted directed graph of view implements.
|
|
464
|
+
|
|
465
|
+
Nodes are ViewReferences, edges represent implements.
|
|
466
|
+
An edge A → B means view A implements view B. Order of views in implements is used to set weight of an edge.
|
|
467
|
+
|
|
468
|
+
Includes views from both merged schema and CDF
|
|
469
|
+
"""
|
|
470
|
+
graph: nx.DiGraph = nx.DiGraph()
|
|
471
|
+
|
|
472
|
+
for view_ref in self.cdf.views:
|
|
473
|
+
graph.add_node(view_ref)
|
|
474
|
+
for view_ref in self.merged.views:
|
|
475
|
+
graph.add_node(view_ref)
|
|
476
|
+
|
|
477
|
+
# Add edges for implements
|
|
478
|
+
for view_ref in graph.nodes():
|
|
479
|
+
view = self.select_view(view_ref)
|
|
480
|
+
if not view or not view.implements:
|
|
481
|
+
continue
|
|
482
|
+
|
|
483
|
+
# Adding weight to preserve order of implements
|
|
484
|
+
for i, implement in enumerate(view.implements):
|
|
485
|
+
graph.add_edge(view_ref, implement, weight=i + 1)
|
|
486
|
+
|
|
487
|
+
return graph
|
|
488
|
+
|
|
489
|
+
@cached_property
|
|
490
|
+
def implements_cycles(self) -> list[list[ViewReference]]:
|
|
491
|
+
"""Find all cycles in the implements graph.
|
|
492
|
+
Returns:
|
|
493
|
+
List of lists, where each list contains the ordered Views involved in forming the implements cycle.
|
|
494
|
+
"""
|
|
495
|
+
|
|
496
|
+
return self.graph_cycles(self.implements_graph)
|
|
497
|
+
|
|
498
|
+
@cached_property
|
|
499
|
+
def requires_constraint_graph(self) -> nx.DiGraph:
|
|
500
|
+
"""Build a directed graph of container requires constraints.
|
|
501
|
+
|
|
502
|
+
Nodes are ContainerReferences, edges represent requires constraints.
|
|
503
|
+
An edge A → B means container A requires container B.
|
|
504
|
+
|
|
505
|
+
Includes containers from both merged schema and CDF
|
|
506
|
+
"""
|
|
507
|
+
graph: nx.DiGraph = nx.DiGraph()
|
|
508
|
+
|
|
509
|
+
for container_ref in self.cdf.containers:
|
|
510
|
+
graph.add_node(container_ref)
|
|
511
|
+
for container_ref in self.merged.containers:
|
|
512
|
+
graph.add_node(container_ref)
|
|
513
|
+
|
|
514
|
+
# Add edges for requires constraints from all known containers
|
|
515
|
+
for container_ref in graph.nodes():
|
|
516
|
+
container = self.select_container(container_ref)
|
|
517
|
+
if not container or not container.constraints:
|
|
518
|
+
continue
|
|
519
|
+
for constraint in container.constraints.values():
|
|
520
|
+
if not isinstance(constraint, RequiresConstraintDefinition):
|
|
521
|
+
continue
|
|
522
|
+
graph.add_edge(container_ref, constraint.require)
|
|
523
|
+
|
|
524
|
+
return graph
|
|
525
|
+
|
|
526
|
+
@staticmethod
|
|
527
|
+
def forms_directed_path(nodes: set[_NodeT], graph: nx.DiGraph) -> bool:
|
|
528
|
+
"""Check if nodes form an uninterrupted directed path in the graph.
|
|
529
|
+
|
|
530
|
+
Returns True if there exists a node that can reach all other nodes via
|
|
531
|
+
directed edges in the graph.
|
|
532
|
+
|
|
533
|
+
Args:
|
|
534
|
+
nodes: Set of nodes to check
|
|
535
|
+
graph: Directed graph containing the nodes
|
|
536
|
+
|
|
537
|
+
Returns:
|
|
538
|
+
True if nodes form a directed path (one node reaches all others)
|
|
539
|
+
|
|
540
|
+
Example:
|
|
541
|
+
Given nodes N1, N2, N3 with edges:
|
|
542
|
+
- N1 -> N2
|
|
543
|
+
- N2 -> N3
|
|
544
|
+
|
|
545
|
+
forms_directed_path({N1, N2, N3}) returns True (N1 reaches all others)
|
|
546
|
+
forms_directed_path({N2, N3}) returns True (N2 reaches N3)
|
|
547
|
+
forms_directed_path({N1, N3}) returns False (N1 can't reach N3 without N2)
|
|
548
|
+
"""
|
|
549
|
+
if len(nodes) <= 1:
|
|
550
|
+
return True
|
|
551
|
+
|
|
552
|
+
for candidate in nodes:
|
|
553
|
+
others = nodes - {candidate}
|
|
554
|
+
if others.issubset(nx.descendants(graph, candidate)):
|
|
555
|
+
return True
|
|
556
|
+
|
|
557
|
+
return False
|
|
558
|
+
|
|
559
|
+
@cached_property
|
|
560
|
+
def requires_constraint_cycles(self) -> list[list[ContainerReference]]:
|
|
561
|
+
"""Find all cycles in the requires constraint graph.
|
|
562
|
+
Returns:
|
|
563
|
+
List of lists, where each list contains the ordered containers involved in forming the requires cycle.
|
|
564
|
+
"""
|
|
565
|
+
|
|
566
|
+
return self.graph_cycles(self.requires_constraint_graph)
|
|
567
|
+
|
|
568
|
+
@staticmethod
|
|
569
|
+
def graph_cycles(graph: nx.DiGraph) -> list[list[T_Reference]]:
|
|
570
|
+
"""Returns cycles in the graph otherwise empty list"""
|
|
571
|
+
return [candidate for candidate in nx.simple_cycles(graph) if len(candidate) > 1]
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
from ._identifiers import NameSpace
|
|
2
|
+
|
|
3
|
+
XML_SCHEMA_NAMESPACE = NameSpace("http://www.w3.org/2001/XMLSchema#")
|
|
4
|
+
|
|
5
|
+
CDF_CDM_SPACE = "cdf_cdm"
|
|
6
|
+
CDF_CDM_VERSION = "v1"
|
|
7
|
+
|
|
8
|
+
COGNITE_CONCEPTS_MAIN = (
|
|
9
|
+
"CogniteAsset",
|
|
10
|
+
"CogniteEquipment",
|
|
11
|
+
"CogniteActivity",
|
|
12
|
+
"CogniteTimeSeries",
|
|
13
|
+
"CogniteFile",
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
COGNITE_CONCEPTS_INTERFACES = (
|
|
17
|
+
"CogniteDescribable",
|
|
18
|
+
"CogniteSourceable",
|
|
19
|
+
"CogniteSchedulable",
|
|
20
|
+
"CogniteVisualizable",
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
COGNITE_CONCEPTS_CONFIGURATIONS = (
|
|
24
|
+
"CogniteSourceSystem",
|
|
25
|
+
"CogniteUnit",
|
|
26
|
+
"CogniteAssetClass",
|
|
27
|
+
"CogniteAssetType",
|
|
28
|
+
"CogniteEquipmentType",
|
|
29
|
+
"CogniteFileCategory",
|
|
30
|
+
)
|
|
31
|
+
COGNITE_CONCEPTS_ANNOTATIONS = (
|
|
32
|
+
"CogniteAnnotation",
|
|
33
|
+
"CogniteDiagramAnnotation",
|
|
34
|
+
)
|
|
35
|
+
COGNITE_CONCEPTS_3D = (
|
|
36
|
+
"CogniteCubeMap",
|
|
37
|
+
"CogniteCADRevision",
|
|
38
|
+
"CognitePointCloudVolume",
|
|
39
|
+
"Cognite360ImageAnnotation",
|
|
40
|
+
"Cognite3DObject",
|
|
41
|
+
"Cognite3DRevision",
|
|
42
|
+
"Cognite360Image",
|
|
43
|
+
"Cognite360ImageCollection",
|
|
44
|
+
"Cognite360ImageStation",
|
|
45
|
+
"CognitePointCloudModel",
|
|
46
|
+
"Cognite3DTransformation",
|
|
47
|
+
"Cognite360ImageModel",
|
|
48
|
+
"Cognite3DModel",
|
|
49
|
+
"CogniteCADModel",
|
|
50
|
+
"CognitePointCloudRevision",
|
|
51
|
+
"CogniteCADNode",
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
COGNITE_CONCEPTS: tuple[str, ...] = (
|
|
55
|
+
*COGNITE_CONCEPTS_MAIN,
|
|
56
|
+
*COGNITE_CONCEPTS_INTERFACES,
|
|
57
|
+
*COGNITE_CONCEPTS_CONFIGURATIONS,
|
|
58
|
+
*COGNITE_CONCEPTS_ANNOTATIONS,
|
|
59
|
+
*COGNITE_CONCEPTS_3D,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
COGNITE_SPACES = (
|
|
63
|
+
CDF_CDM_SPACE,
|
|
64
|
+
"cdf_360_image_schema",
|
|
65
|
+
"cdf_3d_schema",
|
|
66
|
+
"cdf_apm",
|
|
67
|
+
"cdf_apps_shared",
|
|
68
|
+
"cdf_cdm_3d",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# Defaults from https://docs.cognite.com/cdf/dm/dm_reference/dm_limits_and_restrictions#list-size-limits
|
|
72
|
+
|
|
73
|
+
DEFAULT_MAX_LIST_SIZE = 1000
|
|
74
|
+
DEFAULT_MAX_LIST_SIZE_DIRECT_RELATIONS = 100
|