cognite-neat 0.123.2__py3-none-any.whl → 0.127.30__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 +2 -2
- cognite/neat/_client/__init__.py +4 -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 +125 -0
- cognite/neat/_client/data_classes.py +44 -0
- cognite/neat/_client/data_model_api.py +115 -0
- cognite/neat/_client/spaces_api.py +115 -0
- cognite/neat/_client/statistics_api.py +24 -0
- cognite/neat/_client/views_api.py +129 -0
- cognite/neat/_config.py +185 -0
- cognite/neat/_data_model/_analysis.py +196 -0
- cognite/neat/_data_model/_constants.py +67 -0
- cognite/neat/_data_model/_identifiers.py +61 -0
- cognite/neat/_data_model/_shared.py +41 -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 +529 -0
- cognite/neat/_data_model/deployer/deployer.py +401 -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 +421 -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 +295 -0
- cognite/neat/_data_model/importers/_table_importer/importer.py +192 -0
- cognite/neat/_data_model/importers/_table_importer/reader.py +1063 -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 +135 -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 +282 -0
- cognite/neat/_data_model/models/dms/_view_property.py +235 -0
- cognite/neat/_data_model/models/dms/_views.py +210 -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 +364 -0
- cognite/neat/_data_model/validation/dms/_base.py +307 -0
- cognite/neat/_data_model/validation/dms/_connections.py +638 -0
- cognite/neat/_data_model/validation/dms/_consistency.py +57 -0
- cognite/neat/_data_model/validation/dms/_containers.py +174 -0
- cognite/neat/_data_model/validation/dms/_limits.py +420 -0
- cognite/neat/_data_model/validation/dms/_orchestrator.py +222 -0
- cognite/neat/_data_model/validation/dms/_views.py +103 -0
- cognite/neat/_exceptions.py +56 -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 +303 -0
- cognite/neat/_session/_html/static/deployment.js +150 -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 +75 -0
- cognite/neat/_session/_html/templates/issues.html +45 -0
- cognite/neat/_session/_issues.py +81 -0
- cognite/neat/_session/_opt.py +35 -0
- cognite/neat/_session/_physical.py +261 -0
- cognite/neat/_session/_result.py +236 -0
- cognite/neat/_session/_session.py +88 -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 +82 -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 +81 -0
- cognite/neat/_store/_store.py +156 -0
- cognite/neat/_utils/__init__.py +0 -0
- cognite/neat/_utils/_reader.py +194 -0
- cognite/neat/_utils/auxiliary.py +39 -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/text.py +71 -0
- cognite/neat/_utils/useful_types.py +37 -0
- cognite/neat/_utils/validation.py +154 -0
- cognite/neat/_version.py +1 -1
- 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 +86 -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 +10 -3
- cognite/neat/v0/core/_data_model/__init__.py +0 -0
- cognite/neat/{core → v0/core}/_data_model/_constants.py +9 -6
- cognite/neat/{core → v0/core}/_data_model/_shared.py +5 -5
- cognite/neat/{core → v0/core}/_data_model/analysis/_base.py +12 -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 +13 -13
- 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 -133
- cognite/neat/{core → v0/core}/_data_model/exporters/_data_model2yaml.py +1 -1
- cognite/neat/{core → v0/core}/_data_model/importers/__init__.py +4 -6
- 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 +6 -6
- cognite/neat/{core → v0/core}/_data_model/importers/_dms2data_model.py +19 -16
- cognite/neat/v0/core/_data_model/importers/_graph2data_model.py +299 -0
- cognite/neat/v0/core/_data_model/importers/_rdf/__init__.py +4 -0
- cognite/neat/{core → v0/core}/_data_model/importers/_rdf/_base.py +13 -13
- cognite/neat/{core → v0/core}/_data_model/importers/_rdf/_inference2rdata_model.py +14 -14
- cognite/neat/v0/core/_data_model/importers/_rdf/_owl2data_model.py +144 -0
- cognite/neat/v0/core/_data_model/importers/_rdf/_shared.py +255 -0
- cognite/neat/{core → v0/core}/_data_model/importers/_spreadsheet2data_model.py +94 -13
- 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/v0/core/_data_model/models/_import_contexts.py +82 -0
- cognite/neat/{core → v0/core}/_data_model/models/_types.py +5 -5
- cognite/neat/{core → v0/core}/_data_model/models/conceptual/_unverified.py +18 -12
- cognite/neat/v0/core/_data_model/models/conceptual/_validation.py +308 -0
- cognite/neat/{core → v0/core}/_data_model/models/conceptual/_verified.py +13 -11
- 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 +28 -21
- cognite/neat/{core → v0/core}/_data_model/models/physical/_unverified.py +141 -38
- cognite/neat/{core → v0/core}/_data_model/models/physical/_validation.py +190 -24
- cognite/neat/{core → v0/core}/_data_model/models/physical/_verified.py +135 -15
- cognite/neat/{core → v0/core}/_data_model/transformers/__init__.py +2 -0
- cognite/neat/{core → v0/core}/_data_model/transformers/_base.py +4 -4
- cognite/neat/{core → v0/core}/_data_model/transformers/_converters.py +39 -32
- cognite/neat/{core → v0/core}/_data_model/transformers/_mapping.py +7 -7
- cognite/neat/v0/core/_data_model/transformers/_union_conceptual.py +208 -0
- 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 +1 -1
- 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 +11 -6
- cognite/neat/{core → v0/core}/_issues/_contextmanagers.py +8 -6
- cognite/neat/{core → v0/core}/_issues/_factory.py +11 -8
- cognite/neat/{core → v0/core}/_issues/errors/__init__.py +3 -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 +12 -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 +5 -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 +39 -4
- cognite/neat/{core → v0/core}/_issues/warnings/_properties.py +13 -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 +13 -12
- cognite/neat/{core → v0/core}/_store/_instance.py +45 -12
- 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 +1 -1
- cognite/neat/{core → v0/core}/_utils/auxiliary.py +7 -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 +38 -14
- cognite/neat/{core → v0/core}/_utils/reader/_base.py +1 -1
- cognite/neat/{core → v0/core}/_utils/spreadsheet.py +22 -4
- cognite/neat/v0/core/_utils/tarjan.py +44 -0
- cognite/neat/{core → v0/core}/_utils/text.py +1 -1
- cognite/neat/{core → v0/core}/_utils/upload.py +3 -3
- 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 -10
- 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 +33 -43
- 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 +22 -8
- 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}/engine/_load.py +1 -1
- cognite/neat/{session → v0/session}/exceptions.py +5 -5
- cognite/neat/v1.py +3 -0
- {cognite_neat-0.123.2.dist-info → cognite_neat-0.127.30.dist-info}/METADATA +9 -8
- cognite_neat-0.127.30.dist-info/RECORD +319 -0
- {cognite_neat-0.123.2.dist-info → cognite_neat-0.127.30.dist-info}/WHEEL +1 -1
- cognite/neat/core/_data_model/importers/_dtdl2data_model/__init__.py +0 -3
- cognite/neat/core/_data_model/importers/_dtdl2data_model/_unit_lookup.py +0 -224
- cognite/neat/core/_data_model/importers/_dtdl2data_model/dtdl_converter.py +0 -320
- cognite/neat/core/_data_model/importers/_dtdl2data_model/dtdl_importer.py +0 -155
- cognite/neat/core/_data_model/importers/_dtdl2data_model/spec.py +0 -363
- cognite/neat/core/_data_model/importers/_rdf/__init__.py +0 -5
- cognite/neat/core/_data_model/importers/_rdf/_imf2data_model.py +0 -98
- cognite/neat/core/_data_model/importers/_rdf/_owl2data_model.py +0 -87
- cognite/neat/core/_data_model/importers/_rdf/_shared.py +0 -168
- cognite/neat/core/_data_model/models/conceptual/_validation.py +0 -294
- 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-0.123.2.dist-info/RECORD +0 -197
- /cognite/neat/{core → _data_model}/__init__.py +0 -0
- /cognite/neat/{core/_client/_api → _data_model/deployer}/__init__.py +0 -0
- /cognite/neat/{core/_client/data_classes → _data_model/exporters/_table_exporter}/__init__.py +0 -0
- /cognite/neat/{core/_data_model → _data_model/importers/_table_importer}/__init__.py +0 -0
- /cognite/neat/{core/_instances → _data_model/models}/__init__.py +0 -0
- /cognite/neat/{core/_instances/extractors/_classic_cdf → _data_model/models/conceptual}/__init__.py +0 -0
- /cognite/neat/{core/_utils → _data_model/validation}/__init__.py +0 -0
- /cognite/neat/{plugins/data_model → _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/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}/_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/time_.py +0 -0
- /cognite/neat/{core → v0/core}/_utils/xml_.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
- /cognite/neat/{session → v0/session}/engine/__init__.py +0 -0
- /cognite/neat/{session → v0/session}/engine/_import.py +0 -0
- /cognite/neat/{session → v0/session}/engine/_interface.py +0 -0
- {cognite_neat-0.123.2.dist-info → cognite_neat-0.127.30.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
from typing import Any, Literal
|
|
2
|
+
|
|
3
|
+
from cognite.neat._client import NeatClient
|
|
4
|
+
from cognite.neat._config import NeatConfig
|
|
5
|
+
from cognite.neat._data_model.deployer.deployer import DeploymentOptions, SchemaDeployer
|
|
6
|
+
from cognite.neat._data_model.exporters import (
|
|
7
|
+
DMSAPIExporter,
|
|
8
|
+
DMSAPIJSONExporter,
|
|
9
|
+
DMSAPIYAMLExporter,
|
|
10
|
+
DMSExcelExporter,
|
|
11
|
+
DMSExporter,
|
|
12
|
+
DMSTableJSONExporter,
|
|
13
|
+
DMSTableYamlExporter,
|
|
14
|
+
)
|
|
15
|
+
from cognite.neat._data_model.exporters._table_exporter.workbook import WorkbookOptions
|
|
16
|
+
from cognite.neat._data_model.importers import DMSAPIImporter, DMSImporter, DMSTableImporter
|
|
17
|
+
from cognite.neat._data_model.models.dms import DataModelReference
|
|
18
|
+
from cognite.neat._data_model.validation.dms import DmsDataModelValidation
|
|
19
|
+
from cognite.neat._exceptions import UserInputError
|
|
20
|
+
from cognite.neat._state_machine import PhysicalState
|
|
21
|
+
from cognite.neat._store._store import NeatStore
|
|
22
|
+
from cognite.neat._utils._reader import NeatReader
|
|
23
|
+
|
|
24
|
+
from ._wrappers import session_wrapper
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class PhysicalDataModel:
|
|
28
|
+
"""Read from a data source into NeatSession graph store."""
|
|
29
|
+
|
|
30
|
+
def __init__(self, store: NeatStore, client: NeatClient, config: NeatConfig) -> None:
|
|
31
|
+
self._store = store
|
|
32
|
+
self._client = client
|
|
33
|
+
self._config = config
|
|
34
|
+
self.read = ReadPhysicalDataModel(self._store, self._client, self._config)
|
|
35
|
+
self.write = WritePhysicalDataModel(self._store, self._client, self._config)
|
|
36
|
+
|
|
37
|
+
def _repr_html_(self) -> str:
|
|
38
|
+
if not isinstance(self._store.state, PhysicalState):
|
|
39
|
+
return "No physical data model. Get started by reading physical data model <em>.physica_data_mode.read</em>"
|
|
40
|
+
|
|
41
|
+
dm = self._store.physical_data_model[-1]
|
|
42
|
+
|
|
43
|
+
html = ["<div>"]
|
|
44
|
+
html.append(
|
|
45
|
+
f"<h3>Data Model: {dm.data_model.space}:{dm.data_model.external_id}(version={dm.data_model.version})</h3>"
|
|
46
|
+
)
|
|
47
|
+
html.append("<table style='border-collapse: collapse;'>")
|
|
48
|
+
html.append("<tr><th style='text-align: left; padding: 4px; border: 1px solid #ddd;'>Component</th>")
|
|
49
|
+
html.append("<th style='text-align: left; padding: 4px; border: 1px solid #ddd;'>Count</th></tr>")
|
|
50
|
+
|
|
51
|
+
html.append("<tr><td style='padding: 4px; border: 1px solid #ddd;'>Views</td>")
|
|
52
|
+
html.append(f"<td style='padding: 4px; border: 1px solid #ddd;'>{len(dm.views)}</td></tr>")
|
|
53
|
+
|
|
54
|
+
html.append("<tr><td style='padding: 4px; border: 1px solid #ddd;'>Containers</td>")
|
|
55
|
+
html.append(f"<td style='padding: 4px; border: 1px solid #ddd;'>{len(dm.containers)}</td></tr>")
|
|
56
|
+
|
|
57
|
+
html.append("<tr><td style='padding: 4px; border: 1px solid #ddd;'>Spaces</td>")
|
|
58
|
+
html.append(f"<td style='padding: 4px; border: 1px solid #ddd;'>{len(dm.spaces)}</td></tr>")
|
|
59
|
+
|
|
60
|
+
html.append("<tr><td style='padding: 4px; border: 1px solid #ddd;'>Node Types</td>")
|
|
61
|
+
html.append(f"<td style='padding: 4px; border: 1px solid #ddd;'>{len(dm.node_types)}</td></tr>")
|
|
62
|
+
|
|
63
|
+
html.append("</table>")
|
|
64
|
+
html.append("</div>")
|
|
65
|
+
|
|
66
|
+
return "".join(html)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@session_wrapper
|
|
70
|
+
class ReadPhysicalDataModel:
|
|
71
|
+
"""Read physical data model from various sources into NeatSession graph store."""
|
|
72
|
+
|
|
73
|
+
def __init__(self, store: NeatStore, client: NeatClient, config: NeatConfig) -> None:
|
|
74
|
+
self._store = store
|
|
75
|
+
self._client = client
|
|
76
|
+
self._config = config
|
|
77
|
+
|
|
78
|
+
def yaml(self, io: Any, format: Literal["neat", "toolkit"] = "neat") -> None:
|
|
79
|
+
"""Read physical data model from YAML file(s)
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
io (Any): The file or directory path or buffer to read from.
|
|
83
|
+
format (Literal["neat", "toolkit"]): The format of the input file(s).
|
|
84
|
+
- "neat": Neat's DMS table format.
|
|
85
|
+
- "toolkit": Cognite DMS API format which is the format used by Cognite Toolkit.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
path = NeatReader.create(io).materialize_path()
|
|
89
|
+
|
|
90
|
+
reader: DMSImporter
|
|
91
|
+
if format == "neat":
|
|
92
|
+
reader = DMSTableImporter.from_yaml(path)
|
|
93
|
+
elif format == "toolkit":
|
|
94
|
+
reader = DMSAPIImporter.from_yaml(path)
|
|
95
|
+
else:
|
|
96
|
+
raise UserInputError(f"Unsupported format: {format}. Supported formats are 'neat' and 'toolkit'.")
|
|
97
|
+
on_success = DmsDataModelValidation(
|
|
98
|
+
self._client,
|
|
99
|
+
modus_operandi=self._config.modeling.mode,
|
|
100
|
+
can_run_validator=self._config.validation.can_run_validator,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
return self._store.read_physical(reader, on_success)
|
|
104
|
+
|
|
105
|
+
def json(self, io: Any, format: Literal["neat", "toolkit"] = "neat") -> None:
|
|
106
|
+
"""Read physical data model from JSON file(s)
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
io (Any): The file or directory path or buffer to read from.
|
|
110
|
+
format (Literal["neat", "toolkit"]): The format of the input file(s).
|
|
111
|
+
- "neat": Neat's DMS table format.
|
|
112
|
+
- "toolkit": Cognite DMS API format which is the format used by Cognite Toolkit.
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
path = NeatReader.create(io).materialize_path()
|
|
116
|
+
|
|
117
|
+
reader: DMSImporter
|
|
118
|
+
if format == "neat":
|
|
119
|
+
reader = DMSTableImporter.from_json(path)
|
|
120
|
+
elif format == "toolkit":
|
|
121
|
+
reader = DMSAPIImporter.from_json(path)
|
|
122
|
+
else:
|
|
123
|
+
raise UserInputError(f"Unsupported format: {format}. Supported formats are 'neat' and 'toolkit'.")
|
|
124
|
+
on_success = DmsDataModelValidation(
|
|
125
|
+
self._client,
|
|
126
|
+
modus_operandi=self._config.modeling.mode,
|
|
127
|
+
can_run_validator=self._config.validation.can_run_validator,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
return self._store.read_physical(reader, on_success)
|
|
131
|
+
|
|
132
|
+
def excel(self, io: Any) -> None:
|
|
133
|
+
"""Read physical data model from Excel file"""
|
|
134
|
+
|
|
135
|
+
path = NeatReader.create(io).materialize_path()
|
|
136
|
+
reader = DMSTableImporter.from_excel(path)
|
|
137
|
+
on_success = DmsDataModelValidation(
|
|
138
|
+
self._client,
|
|
139
|
+
modus_operandi=self._config.modeling.mode,
|
|
140
|
+
can_run_validator=self._config.validation.can_run_validator,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
return self._store.read_physical(reader, on_success)
|
|
144
|
+
|
|
145
|
+
def cdf(self, space: str, external_id: str, version: str) -> None:
|
|
146
|
+
"""Read physical data model from CDF
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
space (str): The schema space of the data model.
|
|
150
|
+
external_id (str): The external id of the data model.
|
|
151
|
+
version (str): The version of the data model.
|
|
152
|
+
|
|
153
|
+
"""
|
|
154
|
+
reader = DMSAPIImporter.from_cdf(
|
|
155
|
+
DataModelReference(space=space, external_id=external_id, version=version), self._client
|
|
156
|
+
)
|
|
157
|
+
on_success = DmsDataModelValidation(
|
|
158
|
+
self._client,
|
|
159
|
+
modus_operandi=self._config.modeling.mode,
|
|
160
|
+
can_run_validator=self._config.validation.can_run_validator,
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
return self._store.read_physical(reader, on_success)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
@session_wrapper
|
|
167
|
+
class WritePhysicalDataModel:
|
|
168
|
+
"""Write physical data model to various sources from NeatSession graph store."""
|
|
169
|
+
|
|
170
|
+
def __init__(self, store: NeatStore, client: NeatClient, config: NeatConfig) -> None:
|
|
171
|
+
self._store = store
|
|
172
|
+
self._client = client
|
|
173
|
+
self._config = config
|
|
174
|
+
|
|
175
|
+
def yaml(self, io: Any, format: Literal["neat", "toolkit"] = "neat") -> None:
|
|
176
|
+
"""Write physical data model to YAML file
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
io (Any): The file path or buffer to write to.
|
|
180
|
+
format (Literal["neat", "toolkit"]): The format of the output file
|
|
181
|
+
- "neat": Neat's DMS table format.
|
|
182
|
+
- "toolkit": Cognite DMS API format which is the format used by Cognite Toolkit.
|
|
183
|
+
"""
|
|
184
|
+
|
|
185
|
+
file_path = NeatReader.create(io).materialize_path()
|
|
186
|
+
writer: DMSExporter
|
|
187
|
+
if format == "neat":
|
|
188
|
+
writer = DMSTableYamlExporter()
|
|
189
|
+
elif format == "toolkit":
|
|
190
|
+
writer = DMSAPIYAMLExporter()
|
|
191
|
+
else:
|
|
192
|
+
raise UserInputError(f"Unsupported format: {format}. Supported formats are 'neat' and 'toolkit'.")
|
|
193
|
+
|
|
194
|
+
return self._store.write_physical(writer, file_path=file_path)
|
|
195
|
+
|
|
196
|
+
def json(self, io: Any, format: Literal["neat", "toolkit"] = "neat") -> None:
|
|
197
|
+
"""Write physical data model to JSON file
|
|
198
|
+
|
|
199
|
+
Args:
|
|
200
|
+
io (Any): The file path or buffer to write to.
|
|
201
|
+
format (Literal["neat", "toolkit"]): The format of the output file
|
|
202
|
+
- "neat": Neat's DMS table format.
|
|
203
|
+
- "toolkit": Cognite DMS API format which is the format used by Cognite Toolkit.
|
|
204
|
+
"""
|
|
205
|
+
|
|
206
|
+
file_path = NeatReader.create(io).materialize_path()
|
|
207
|
+
writer: DMSExporter
|
|
208
|
+
if format == "neat":
|
|
209
|
+
writer = DMSTableJSONExporter()
|
|
210
|
+
elif format == "toolkit":
|
|
211
|
+
writer = DMSAPIJSONExporter()
|
|
212
|
+
else:
|
|
213
|
+
raise UserInputError(f"Unsupported format: {format}. Supported formats are 'neat' and 'toolkit'.")
|
|
214
|
+
|
|
215
|
+
return self._store.write_physical(writer, file_path=file_path)
|
|
216
|
+
|
|
217
|
+
def excel(self, io: Any, skip_other_spaces: bool = True) -> None:
|
|
218
|
+
"""Write physical data model to Excel file
|
|
219
|
+
|
|
220
|
+
Args:
|
|
221
|
+
io (Any): The file path or buffer to write to.
|
|
222
|
+
skip_other_spaces (bool): If true, only properties in the same space as the data model will be written.
|
|
223
|
+
|
|
224
|
+
"""
|
|
225
|
+
|
|
226
|
+
file_path = NeatReader.create(io).materialize_path()
|
|
227
|
+
options = WorkbookOptions(skip_properties_in_other_spaces=skip_other_spaces)
|
|
228
|
+
writer = DMSExcelExporter(options=options)
|
|
229
|
+
|
|
230
|
+
return self._store.write_physical(writer, file_path=file_path)
|
|
231
|
+
|
|
232
|
+
def cdf(self, dry_run: bool = True, rollback: bool = True, drop_data: bool = False) -> None:
|
|
233
|
+
"""Write physical data model with views, containers, and spaces that are in the same space as the data model
|
|
234
|
+
to CDF.
|
|
235
|
+
|
|
236
|
+
This method depends on the session governance profile for data modeling set when creating the NeatSession.
|
|
237
|
+
- In 'additive' mode, only new or updates to data models/views/containers will be applied.
|
|
238
|
+
You cannot remove views from data models, properties from views or containers, or
|
|
239
|
+
indexes or constraints from containers.
|
|
240
|
+
- In 'rebuild' mode, the data model in CDF will be made to exactly match the data model in Neat.
|
|
241
|
+
If there are any breaking changes, Neat will delete and recreate the relevant
|
|
242
|
+
data model/view/container. However, if drop_data is set to False, Neat will treat
|
|
243
|
+
containers as 'additive' and will not delete any containers or remove properties,
|
|
244
|
+
indexes, or constraints. To fully rebuild the data model, including containers, set drop_data to True.
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
dry_run (bool): If true, the changes will not be applied to CDF. Instead, Neat will
|
|
248
|
+
report what changes would have been made.
|
|
249
|
+
rollback (bool): If true, all changes will be rolled back if any error occurs.
|
|
250
|
+
drop_data (bool): Only applicable if the session mode is 'rebuild'. If
|
|
251
|
+
|
|
252
|
+
"""
|
|
253
|
+
writer = DMSAPIExporter()
|
|
254
|
+
options = DeploymentOptions(
|
|
255
|
+
dry_run=dry_run,
|
|
256
|
+
auto_rollback=rollback,
|
|
257
|
+
drop_data=drop_data,
|
|
258
|
+
modus_operandi=self._config.modeling.mode,
|
|
259
|
+
)
|
|
260
|
+
on_success = SchemaDeployer(self._client, options)
|
|
261
|
+
return self._store.write_physical(writer, on_success)
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import uuid
|
|
3
|
+
from typing import Any, get_args
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
|
+
|
|
7
|
+
from cognite.neat._data_model.deployer.data_classes import (
|
|
8
|
+
AddedField,
|
|
9
|
+
ChangedField,
|
|
10
|
+
DataModelEndpoint,
|
|
11
|
+
DeploymentResult,
|
|
12
|
+
FieldChange,
|
|
13
|
+
FieldChanges,
|
|
14
|
+
RemovedField,
|
|
15
|
+
ResourceChange,
|
|
16
|
+
)
|
|
17
|
+
from cognite.neat._session._html._render import render
|
|
18
|
+
from cognite.neat._store import NeatStore
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class EndpointStatistics(BaseModel):
|
|
22
|
+
"""Statistics for a single endpoint."""
|
|
23
|
+
|
|
24
|
+
total: int = 0
|
|
25
|
+
create: int = 0
|
|
26
|
+
update: int = 0
|
|
27
|
+
delete: int = 0
|
|
28
|
+
skip: int = 0
|
|
29
|
+
unchanged: int = 0
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ChangeTypeStatistics(BaseModel):
|
|
33
|
+
"""Statistics grouped by change type."""
|
|
34
|
+
|
|
35
|
+
create: int = 0
|
|
36
|
+
update: int = 0
|
|
37
|
+
delete: int = 0
|
|
38
|
+
skip: int = 0
|
|
39
|
+
unchanged: int = 0
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class SeverityStatistics(BaseModel):
|
|
43
|
+
"""Statistics grouped by severity."""
|
|
44
|
+
|
|
45
|
+
SAFE: int = 0
|
|
46
|
+
WARNING: int = 0
|
|
47
|
+
BREAKING: int = 0
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class DeploymentStatistics(BaseModel):
|
|
51
|
+
"""Overall deployment statistics."""
|
|
52
|
+
|
|
53
|
+
status: str
|
|
54
|
+
is_dry_run: bool
|
|
55
|
+
total_changes: int = 0
|
|
56
|
+
by_endpoint: dict[str, EndpointStatistics] = Field(default_factory=dict)
|
|
57
|
+
by_change_type: ChangeTypeStatistics = Field(default_factory=ChangeTypeStatistics)
|
|
58
|
+
by_severity: SeverityStatistics = Field(default_factory=SeverityStatistics)
|
|
59
|
+
has_recovery: bool = False
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class SerializedFieldChange(BaseModel):
|
|
63
|
+
"""Serialized field change for JSON output."""
|
|
64
|
+
|
|
65
|
+
field_path: str
|
|
66
|
+
severity: str
|
|
67
|
+
description: str
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class SerializedResourceChange(BaseModel):
|
|
71
|
+
"""Serialized resource change for JSON output."""
|
|
72
|
+
|
|
73
|
+
id: int
|
|
74
|
+
endpoint: str
|
|
75
|
+
change_type: str
|
|
76
|
+
severity: str
|
|
77
|
+
resource_id: str
|
|
78
|
+
changes: list[SerializedFieldChange] = Field(default_factory=list)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class Result:
|
|
82
|
+
"""Class to handle deployment results in the NeatSession."""
|
|
83
|
+
|
|
84
|
+
def __init__(self, store: NeatStore) -> None:
|
|
85
|
+
self._store = store
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def _result(self) -> DeploymentResult | None:
|
|
89
|
+
"""Get deployment result from the last change in the store."""
|
|
90
|
+
if change := self._store.provenance.last_change:
|
|
91
|
+
if change.result:
|
|
92
|
+
return change.result
|
|
93
|
+
return None
|
|
94
|
+
|
|
95
|
+
def _initialize_stats(self, result: DeploymentResult) -> DeploymentStatistics:
|
|
96
|
+
"""Initialize the statistics structure."""
|
|
97
|
+
# Get all possible endpoints from the DataModelEndpoint type alias
|
|
98
|
+
endpoints = get_args(DataModelEndpoint)
|
|
99
|
+
|
|
100
|
+
return DeploymentStatistics(
|
|
101
|
+
status=result.status,
|
|
102
|
+
is_dry_run=result.is_dry_run,
|
|
103
|
+
total_changes=0,
|
|
104
|
+
by_endpoint={endpoint: EndpointStatistics() for endpoint in endpoints},
|
|
105
|
+
by_change_type=ChangeTypeStatistics(),
|
|
106
|
+
by_severity=SeverityStatistics(),
|
|
107
|
+
has_recovery=result.recovery is not None,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
def _update_statistics(self, stats: DeploymentStatistics, endpoint: str, change_type: str, severity: str) -> None:
|
|
111
|
+
"""Update all statistics counters for a single resource change."""
|
|
112
|
+
stats.total_changes += 1
|
|
113
|
+
|
|
114
|
+
# Update change type statistics
|
|
115
|
+
setattr(stats.by_change_type, change_type, getattr(stats.by_change_type, change_type) + 1)
|
|
116
|
+
|
|
117
|
+
# Update endpoint statistics
|
|
118
|
+
endpoint_stats = stats.by_endpoint[endpoint]
|
|
119
|
+
endpoint_stats.total += 1
|
|
120
|
+
setattr(endpoint_stats, change_type, getattr(endpoint_stats, change_type) + 1)
|
|
121
|
+
|
|
122
|
+
# Update severity statistics
|
|
123
|
+
setattr(stats.by_severity, severity, getattr(stats.by_severity, severity) + 1)
|
|
124
|
+
|
|
125
|
+
@property
|
|
126
|
+
def _stats(self) -> DeploymentStatistics | None:
|
|
127
|
+
"""Compute statistics about deployment result."""
|
|
128
|
+
if not self._result:
|
|
129
|
+
return None
|
|
130
|
+
|
|
131
|
+
stats = self._initialize_stats(self._result)
|
|
132
|
+
|
|
133
|
+
for plan in self._result.plan:
|
|
134
|
+
for resource in plan.resources:
|
|
135
|
+
self._update_statistics(
|
|
136
|
+
stats=stats,
|
|
137
|
+
endpoint=plan.endpoint,
|
|
138
|
+
change_type=resource.change_type,
|
|
139
|
+
severity=resource.severity.name,
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
return stats
|
|
143
|
+
|
|
144
|
+
def _serialize_single_field_change(self, field_change: FieldChange) -> SerializedFieldChange:
|
|
145
|
+
"""Serialize a single non-nested field change."""
|
|
146
|
+
return SerializedFieldChange(
|
|
147
|
+
field_path=field_change.field_path,
|
|
148
|
+
severity=field_change.severity.name,
|
|
149
|
+
description=field_change.description
|
|
150
|
+
if isinstance(field_change, AddedField | RemovedField | ChangedField)
|
|
151
|
+
else "Field changed",
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
def _serialize_field_change(self, field_change: FieldChange) -> list[SerializedFieldChange]:
|
|
155
|
+
"""Serialize a field change, handling nested FieldChanges recursively."""
|
|
156
|
+
serialized_changes: list[SerializedFieldChange] = []
|
|
157
|
+
|
|
158
|
+
if isinstance(field_change, FieldChanges):
|
|
159
|
+
# Recursively handle nested changes
|
|
160
|
+
for change in field_change.changes:
|
|
161
|
+
serialized_changes.extend(self._serialize_field_change(change))
|
|
162
|
+
else:
|
|
163
|
+
# Base case: single field change
|
|
164
|
+
serialized_changes.append(self._serialize_single_field_change(field_change))
|
|
165
|
+
|
|
166
|
+
return serialized_changes
|
|
167
|
+
|
|
168
|
+
def _serialize_resource_change(
|
|
169
|
+
self, resource: ResourceChange, endpoint: str, change_id: int
|
|
170
|
+
) -> SerializedResourceChange:
|
|
171
|
+
"""Serialize a single resource change."""
|
|
172
|
+
changes: list[SerializedFieldChange] = []
|
|
173
|
+
|
|
174
|
+
for change in resource.changes:
|
|
175
|
+
changes.extend(self._serialize_field_change(change))
|
|
176
|
+
|
|
177
|
+
return SerializedResourceChange(
|
|
178
|
+
id=change_id,
|
|
179
|
+
endpoint=endpoint,
|
|
180
|
+
change_type=resource.change_type,
|
|
181
|
+
severity=resource.severity.name,
|
|
182
|
+
resource_id=str(resource.resource_id),
|
|
183
|
+
changes=changes,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
@property
|
|
187
|
+
def _serialized_changes(self) -> list[SerializedResourceChange]:
|
|
188
|
+
"""Convert deployment changes to JSON-serializable format."""
|
|
189
|
+
if not self._result:
|
|
190
|
+
return []
|
|
191
|
+
|
|
192
|
+
all_changes: list[SerializedResourceChange] = []
|
|
193
|
+
|
|
194
|
+
for plan in self._result.plan:
|
|
195
|
+
for resource in plan.resources:
|
|
196
|
+
change_data = self._serialize_resource_change(
|
|
197
|
+
resource=resource,
|
|
198
|
+
endpoint=plan.endpoint,
|
|
199
|
+
change_id=len(all_changes),
|
|
200
|
+
)
|
|
201
|
+
all_changes.append(change_data)
|
|
202
|
+
|
|
203
|
+
return all_changes
|
|
204
|
+
|
|
205
|
+
def _build_template_vars(self, stats: DeploymentStatistics) -> dict[str, Any]:
|
|
206
|
+
"""Build template variables from statistics."""
|
|
207
|
+
# Generate unique ID for this render to avoid conflicts in Jupyter
|
|
208
|
+
unique_id = uuid.uuid4().hex[:8]
|
|
209
|
+
|
|
210
|
+
# Convert Pydantic models to dicts for JSON serialization
|
|
211
|
+
serialized_changes = [change.model_dump() for change in self._serialized_changes]
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
"CHANGES_JSON": json.dumps(serialized_changes),
|
|
215
|
+
"STATS_JSON": stats.model_dump_json(),
|
|
216
|
+
"status": stats.status,
|
|
217
|
+
"total_changes": stats.total_changes,
|
|
218
|
+
"created": stats.by_change_type.create,
|
|
219
|
+
"updated": stats.by_change_type.update,
|
|
220
|
+
"deleted": stats.by_change_type.delete,
|
|
221
|
+
"skipped": stats.by_change_type.skip,
|
|
222
|
+
"unchanged": stats.by_change_type.unchanged,
|
|
223
|
+
"unique_id": unique_id,
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
def _repr_html_(self) -> str:
|
|
227
|
+
"""Generate interactive HTML representation."""
|
|
228
|
+
if not self._result:
|
|
229
|
+
return "<p>No deployment result available</p>"
|
|
230
|
+
|
|
231
|
+
stats = self._stats
|
|
232
|
+
if not stats:
|
|
233
|
+
return "<p>Unable to compute deployment statistics</p>"
|
|
234
|
+
|
|
235
|
+
template_vars = self._build_template_vars(stats)
|
|
236
|
+
return render("deployment", template_vars)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import Literal
|
|
3
|
+
|
|
4
|
+
from cognite.client import ClientConfig, CogniteClient
|
|
5
|
+
|
|
6
|
+
from cognite.neat import _version
|
|
7
|
+
from cognite.neat._client import NeatClient
|
|
8
|
+
from cognite.neat._config import internal_profiles
|
|
9
|
+
from cognite.neat._state_machine import EmptyState, PhysicalState
|
|
10
|
+
from cognite.neat._store import NeatStore
|
|
11
|
+
from cognite.neat._utils.http_client import ParametersRequest, SuccessResponse
|
|
12
|
+
|
|
13
|
+
from ._issues import Issues
|
|
14
|
+
from ._opt import Opt
|
|
15
|
+
from ._physical import PhysicalDataModel
|
|
16
|
+
from ._result import Result
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class NeatSession:
|
|
20
|
+
"""A session is an interface for neat operations."""
|
|
21
|
+
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
client: CogniteClient | ClientConfig,
|
|
25
|
+
config: Literal["legacy-additive", "legacy-rebuild", "deep-additive", "deep-rebuild"] | None = None,
|
|
26
|
+
) -> None:
|
|
27
|
+
"""Initialize a Neat session.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
client (CogniteClient | ClientConfig): The Cognite client or client configuration to use for the session.
|
|
31
|
+
config (Literal["legacy-additive", "legacy-rebuild", "deep-additive", "deep-rebuild"] | None):
|
|
32
|
+
The configuration profile to use for the session.
|
|
33
|
+
If None, the default profile "legacy-additive" is used. Meaning that Neat will perform additive modeling
|
|
34
|
+
and apply only validations that were part of the legacy Neat version."""
|
|
35
|
+
|
|
36
|
+
# Load configuration
|
|
37
|
+
if config and config not in internal_profiles():
|
|
38
|
+
raise ValueError(f"Profile '{config}' not found among internal profiles.")
|
|
39
|
+
|
|
40
|
+
self._config = internal_profiles()[config or "legacy-additive"]
|
|
41
|
+
|
|
42
|
+
# Use configuration for physical data model
|
|
43
|
+
self._store = NeatStore()
|
|
44
|
+
self._client = NeatClient(client)
|
|
45
|
+
self.physical_data_model = PhysicalDataModel(self._store, self._client, self._config)
|
|
46
|
+
self.issues = Issues(self._store)
|
|
47
|
+
self.result = Result(self._store)
|
|
48
|
+
self.opt = Opt(self._store)
|
|
49
|
+
|
|
50
|
+
if self.opt._collector.can_collect:
|
|
51
|
+
self.opt._collector.collect("initSession", {"mode": self._config.modeling.mode})
|
|
52
|
+
|
|
53
|
+
self._welcome_message()
|
|
54
|
+
|
|
55
|
+
def _welcome_message(self) -> None:
|
|
56
|
+
cdf_project = self._client.config.project
|
|
57
|
+
message = f"Neat session started for CDF project: '{cdf_project}'"
|
|
58
|
+
responses = self._client.http_client.request(
|
|
59
|
+
ParametersRequest(endpoint_url=self._client.config.create_api_url(""), method="GET")
|
|
60
|
+
)
|
|
61
|
+
if len(responses) == 1 and isinstance(response := responses[0], SuccessResponse):
|
|
62
|
+
organization = ""
|
|
63
|
+
try:
|
|
64
|
+
organization = json.loads(response.body)["organization"]
|
|
65
|
+
except (KeyError, ValueError):
|
|
66
|
+
...
|
|
67
|
+
if organization:
|
|
68
|
+
message += f" (Organization: '{organization}')"
|
|
69
|
+
|
|
70
|
+
print(message)
|
|
71
|
+
print(self._config)
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def version(self) -> str:
|
|
75
|
+
"""Get the current version of neat."""
|
|
76
|
+
return _version.__version__
|
|
77
|
+
|
|
78
|
+
def _repr_html_(self) -> str:
|
|
79
|
+
if isinstance(self._store.state, EmptyState):
|
|
80
|
+
return (
|
|
81
|
+
"<strong>Empty session</strong>. Get started by reading for example physical data model"
|
|
82
|
+
" <em>.physical_data_model.read</em>"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
if isinstance(self._store.state, PhysicalState):
|
|
86
|
+
return self.physical_data_model._repr_html_()
|
|
87
|
+
|
|
88
|
+
raise RuntimeError("Unknown session state, contact support.")
|
|
File without changes
|