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,81 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import uuid
|
|
3
|
+
from collections import defaultdict
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from cognite.neat._issues import ConsistencyError, IssueList, ModelSyntaxError, Recommendation
|
|
7
|
+
from cognite.neat._session._html._render import render
|
|
8
|
+
from cognite.neat._store import NeatStore
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Issues:
|
|
12
|
+
"""Class to handle issues in the NeatSession."""
|
|
13
|
+
|
|
14
|
+
def __init__(self, store: NeatStore) -> None:
|
|
15
|
+
self._store = store
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def _issues(self) -> IssueList:
|
|
19
|
+
"""Get all issues from the last change in the store."""
|
|
20
|
+
issues = IssueList()
|
|
21
|
+
if change := self._store.provenance.last_change:
|
|
22
|
+
issues += change.errors or IssueList()
|
|
23
|
+
issues += change.issues or IssueList()
|
|
24
|
+
return issues
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def _stats(self) -> dict[str, Any]:
|
|
28
|
+
"""Compute statistics about issues."""
|
|
29
|
+
by_type: defaultdict[str, int] = defaultdict(int)
|
|
30
|
+
by_code: defaultdict[str, int] = defaultdict(int)
|
|
31
|
+
|
|
32
|
+
stats: dict[str, Any] = {
|
|
33
|
+
"total": len(self._issues),
|
|
34
|
+
"by_type": by_type,
|
|
35
|
+
"by_code": by_code,
|
|
36
|
+
"severity_order": [ModelSyntaxError.__name__, ConsistencyError.__name__, Recommendation.__name__],
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
for issue in self._issues:
|
|
40
|
+
stats["by_type"][issue.issue_type()] += 1
|
|
41
|
+
|
|
42
|
+
if issue.code:
|
|
43
|
+
stats["by_code"][f"{issue.issue_type()}:{issue.code}"] += 1
|
|
44
|
+
|
|
45
|
+
return stats
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def _serialized_issues(self) -> list[dict[str, Any]]:
|
|
49
|
+
"""Convert issues to JSON-serializable format."""
|
|
50
|
+
serialized = []
|
|
51
|
+
for idx, issue in enumerate(self._issues):
|
|
52
|
+
serialized.append(
|
|
53
|
+
{
|
|
54
|
+
"id": idx,
|
|
55
|
+
"type": issue.issue_type(),
|
|
56
|
+
"code": issue.code or "",
|
|
57
|
+
"message": issue.message,
|
|
58
|
+
"fix": issue.fix or "",
|
|
59
|
+
}
|
|
60
|
+
)
|
|
61
|
+
return serialized
|
|
62
|
+
|
|
63
|
+
def _repr_html_(self) -> str:
|
|
64
|
+
"""Generate interactive HTML representation."""
|
|
65
|
+
if not self._issues:
|
|
66
|
+
return "<b>No issues found.</b>"
|
|
67
|
+
stats = self._stats
|
|
68
|
+
|
|
69
|
+
# Generate unique ID for this render to avoid conflicts in Jupyter
|
|
70
|
+
unique_id = uuid.uuid4().hex[:8]
|
|
71
|
+
|
|
72
|
+
template_vars = {
|
|
73
|
+
"JSON": json.dumps(self._serialized_issues),
|
|
74
|
+
"total": stats["total"],
|
|
75
|
+
"syntax_errors": stats["by_type"].get("ModelSyntaxError", 0),
|
|
76
|
+
"consistency_errors": stats["by_type"].get("ConsistencyError", 0),
|
|
77
|
+
"recommendations": stats["by_type"].get("Recommendation", 0),
|
|
78
|
+
"unique_id": unique_id,
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return render("issues", template_vars)
|
|
@@ -0,0 +1,294 @@
|
|
|
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 store.
|
|
72
|
+
|
|
73
|
+
Available methods:
|
|
74
|
+
|
|
75
|
+
- `neat.physical_data_model.read.yaml`
|
|
76
|
+
- `neat.physical_data_model.read.json`
|
|
77
|
+
- `neat.physical_data_model.read.excel`
|
|
78
|
+
- `neat.physical_data_model.read.cdf`
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
def __init__(self, store: NeatStore, client: NeatClient, config: NeatConfig) -> None:
|
|
82
|
+
self._store = store
|
|
83
|
+
self._client = client
|
|
84
|
+
self._config = config
|
|
85
|
+
|
|
86
|
+
def yaml(self, io: Any, format: Literal["neat", "toolkit"] = "neat") -> None:
|
|
87
|
+
"""Read physical data model from YAML file(s)
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
io (Any): The file or directory path or buffer to read from.
|
|
91
|
+
format (Literal["neat", "toolkit"]): The format of the input file(s).
|
|
92
|
+
- "neat": Neat's DMS table format.
|
|
93
|
+
- "toolkit": Cognite DMS API format which is the format used by Cognite Toolkit.
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
path = NeatReader.create(io).materialize_path()
|
|
97
|
+
|
|
98
|
+
reader: DMSImporter
|
|
99
|
+
if format == "neat":
|
|
100
|
+
reader = DMSTableImporter.from_yaml(path)
|
|
101
|
+
elif format == "toolkit":
|
|
102
|
+
reader = DMSAPIImporter.from_yaml(path)
|
|
103
|
+
else:
|
|
104
|
+
raise UserInputError(f"Unsupported format: {format}. Supported formats are 'neat' and 'toolkit'.")
|
|
105
|
+
|
|
106
|
+
on_success = DmsDataModelValidation(
|
|
107
|
+
modus_operandi=self._config.modeling.mode,
|
|
108
|
+
cdf_snapshot=self._store.cdf_snapshot,
|
|
109
|
+
limits=self._store.cdf_limits,
|
|
110
|
+
can_run_validator=self._config.validation.can_run_validator,
|
|
111
|
+
enable_alpha_validators=self._config.alpha.enable_experimental_validators,
|
|
112
|
+
)
|
|
113
|
+
return self._store.read_physical(reader, on_success)
|
|
114
|
+
|
|
115
|
+
def json(self, io: Any, format: Literal["neat", "toolkit"] = "neat") -> None:
|
|
116
|
+
"""Read physical data model from JSON file(s)
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
io (Any): The file or directory path or buffer to read from.
|
|
120
|
+
format (Literal["neat", "toolkit"]): The format of the input file(s).
|
|
121
|
+
- "neat": Neat's DMS table format.
|
|
122
|
+
- "toolkit": Cognite DMS API format which is the format used by Cognite Toolkit.
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
path = NeatReader.create(io).materialize_path()
|
|
126
|
+
|
|
127
|
+
reader: DMSImporter
|
|
128
|
+
if format == "neat":
|
|
129
|
+
reader = DMSTableImporter.from_json(path)
|
|
130
|
+
elif format == "toolkit":
|
|
131
|
+
reader = DMSAPIImporter.from_json(path)
|
|
132
|
+
else:
|
|
133
|
+
raise UserInputError(f"Unsupported format: {format}. Supported formats are 'neat' and 'toolkit'.")
|
|
134
|
+
|
|
135
|
+
on_success = DmsDataModelValidation(
|
|
136
|
+
modus_operandi=self._config.modeling.mode,
|
|
137
|
+
cdf_snapshot=self._store.cdf_snapshot,
|
|
138
|
+
limits=self._store.cdf_limits,
|
|
139
|
+
can_run_validator=self._config.validation.can_run_validator,
|
|
140
|
+
enable_alpha_validators=self._config.alpha.enable_experimental_validators,
|
|
141
|
+
)
|
|
142
|
+
return self._store.read_physical(reader, on_success)
|
|
143
|
+
|
|
144
|
+
def excel(self, io: Any) -> None:
|
|
145
|
+
"""Read physical data model from Excel file
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
io (Any): The file path or buffer to read from.
|
|
149
|
+
|
|
150
|
+
"""
|
|
151
|
+
|
|
152
|
+
path = NeatReader.create(io).materialize_path()
|
|
153
|
+
reader = DMSTableImporter.from_excel(path)
|
|
154
|
+
|
|
155
|
+
on_success = DmsDataModelValidation(
|
|
156
|
+
modus_operandi=self._config.modeling.mode,
|
|
157
|
+
cdf_snapshot=self._store.cdf_snapshot,
|
|
158
|
+
limits=self._store.cdf_limits,
|
|
159
|
+
can_run_validator=self._config.validation.can_run_validator,
|
|
160
|
+
enable_alpha_validators=self._config.alpha.enable_experimental_validators,
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
return self._store.read_physical(reader, on_success)
|
|
164
|
+
|
|
165
|
+
def cdf(self, space: str, external_id: str, version: str) -> None:
|
|
166
|
+
"""Read physical data model from CDF
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
space (str): The schema space of the data model.
|
|
170
|
+
external_id (str): The external id of the data model.
|
|
171
|
+
version (str): The version of the data model.
|
|
172
|
+
|
|
173
|
+
"""
|
|
174
|
+
reader = DMSAPIImporter.from_cdf(
|
|
175
|
+
DataModelReference(space=space, external_id=external_id, version=version), self._client
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
on_success = DmsDataModelValidation(
|
|
179
|
+
modus_operandi=self._config.modeling.mode,
|
|
180
|
+
cdf_snapshot=self._store.cdf_snapshot,
|
|
181
|
+
limits=self._store.cdf_limits,
|
|
182
|
+
can_run_validator=self._config.validation.can_run_validator,
|
|
183
|
+
enable_alpha_validators=self._config.alpha.enable_experimental_validators,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
return self._store.read_physical(reader, on_success)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
@session_wrapper
|
|
190
|
+
class WritePhysicalDataModel:
|
|
191
|
+
"""Write physical data model to various sources from NeatSession store.
|
|
192
|
+
|
|
193
|
+
Available methods:
|
|
194
|
+
|
|
195
|
+
- `neat.physical_data_model.write.yaml`
|
|
196
|
+
- `neat.physical_data_model.write.json`
|
|
197
|
+
- `neat.physical_data_model.write.excel`
|
|
198
|
+
- `neat.physical_data_model.write.cdf`
|
|
199
|
+
"""
|
|
200
|
+
|
|
201
|
+
def __init__(self, store: NeatStore, client: NeatClient, config: NeatConfig) -> None:
|
|
202
|
+
self._store = store
|
|
203
|
+
self._client = client
|
|
204
|
+
self._config = config
|
|
205
|
+
|
|
206
|
+
def yaml(self, io: Any, format: Literal["neat", "toolkit"] = "neat") -> None:
|
|
207
|
+
"""Write physical data model to YAML file
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
io (Any): The file path or buffer to write to.
|
|
211
|
+
format (Literal["neat", "toolkit"]): The format of the output file
|
|
212
|
+
- "neat": Neat's DMS table format.
|
|
213
|
+
- "toolkit": Cognite DMS API format which is the format used by Cognite Toolkit.
|
|
214
|
+
"""
|
|
215
|
+
|
|
216
|
+
file_path = NeatReader.create(io).materialize_path()
|
|
217
|
+
writer: DMSExporter
|
|
218
|
+
if format == "neat":
|
|
219
|
+
writer = DMSTableYamlExporter()
|
|
220
|
+
elif format == "toolkit":
|
|
221
|
+
writer = DMSAPIYAMLExporter()
|
|
222
|
+
else:
|
|
223
|
+
raise UserInputError(f"Unsupported format: {format}. Supported formats are 'neat' and 'toolkit'.")
|
|
224
|
+
|
|
225
|
+
return self._store.write_physical(writer, file_path=file_path)
|
|
226
|
+
|
|
227
|
+
def json(self, io: Any, format: Literal["neat", "toolkit"] = "neat") -> None:
|
|
228
|
+
"""Write physical data model to JSON file
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
io (Any): The file path or buffer to write to.
|
|
232
|
+
format (Literal["neat", "toolkit"]): The format of the output file
|
|
233
|
+
- "neat": Neat's DMS table format.
|
|
234
|
+
- "toolkit": Cognite DMS API format which is the format used by Cognite Toolkit.
|
|
235
|
+
"""
|
|
236
|
+
|
|
237
|
+
file_path = NeatReader.create(io).materialize_path()
|
|
238
|
+
writer: DMSExporter
|
|
239
|
+
if format == "neat":
|
|
240
|
+
writer = DMSTableJSONExporter()
|
|
241
|
+
elif format == "toolkit":
|
|
242
|
+
writer = DMSAPIJSONExporter()
|
|
243
|
+
else:
|
|
244
|
+
raise UserInputError(f"Unsupported format: {format}. Supported formats are 'neat' and 'toolkit'.")
|
|
245
|
+
|
|
246
|
+
return self._store.write_physical(writer, file_path=file_path)
|
|
247
|
+
|
|
248
|
+
def excel(self, io: Any, skip_other_spaces: bool = True) -> None:
|
|
249
|
+
"""Write physical data model to Excel file
|
|
250
|
+
|
|
251
|
+
Args:
|
|
252
|
+
io (Any): The file path or buffer to write to.
|
|
253
|
+
skip_other_spaces (bool): If true, only properties in the same space as the data model will be written.
|
|
254
|
+
|
|
255
|
+
"""
|
|
256
|
+
|
|
257
|
+
file_path = NeatReader.create(io).materialize_path()
|
|
258
|
+
options = WorkbookOptions(skip_properties_in_other_spaces=skip_other_spaces)
|
|
259
|
+
writer = DMSExcelExporter(options=options)
|
|
260
|
+
|
|
261
|
+
return self._store.write_physical(writer, file_path=file_path)
|
|
262
|
+
|
|
263
|
+
def cdf(self, dry_run: bool = True, rollback: bool = False, drop_data: bool = False) -> None:
|
|
264
|
+
"""Write physical data model with views, containers, and spaces that are in the same space as the data model
|
|
265
|
+
to CDF.
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
dry_run (bool): If true, the changes will not be applied to CDF. Instead, Neat will
|
|
269
|
+
report what changes would have been made.
|
|
270
|
+
rollback (bool): If true, all changes will be rolled back if any error occurs.
|
|
271
|
+
drop_data (bool): Only applicable if the session mode is 'rebuild'. If
|
|
272
|
+
|
|
273
|
+
!!! note "Impact of governance profile"
|
|
274
|
+
This method depends on the session governance profile for data modeling set when creating the NeatSession:
|
|
275
|
+
|
|
276
|
+
- In `additive` mode, only new or updates to data models/views/containers will be applied.
|
|
277
|
+
You cannot remove views from data models, properties from views or containers, or
|
|
278
|
+
indexes or constraints from containers.
|
|
279
|
+
|
|
280
|
+
- In `rebuild` mode, the data model in CDF will be made to exactly match the data model in Neat.
|
|
281
|
+
If there are any breaking changes, Neat will delete and recreate the relevant
|
|
282
|
+
data model/view/container. However, if drop_data is set to False, Neat will treat
|
|
283
|
+
containers as `additive` and will not delete any containers or remove properties,
|
|
284
|
+
indexes, or constraints. To fully rebuild the data model, including containers, set drop_data to True.
|
|
285
|
+
"""
|
|
286
|
+
writer = DMSAPIExporter()
|
|
287
|
+
options = DeploymentOptions(
|
|
288
|
+
dry_run=dry_run,
|
|
289
|
+
auto_rollback=rollback,
|
|
290
|
+
drop_data=drop_data,
|
|
291
|
+
modus_operandi=self._config.modeling.mode,
|
|
292
|
+
)
|
|
293
|
+
on_success = SchemaDeployer(self._client, options)
|
|
294
|
+
return self._store.write_physical(writer, on_success)
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import itertools
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
|
+
|
|
6
|
+
from cognite.neat._data_model.deployer.data_classes import (
|
|
7
|
+
AddedField,
|
|
8
|
+
AppliedChanges,
|
|
9
|
+
ChangedField,
|
|
10
|
+
ChangeResult,
|
|
11
|
+
DeploymentResult,
|
|
12
|
+
FieldChange,
|
|
13
|
+
FieldChanges,
|
|
14
|
+
RemovedField,
|
|
15
|
+
ResourceChange,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class SerializedFieldChange(BaseModel):
|
|
20
|
+
"""Serialized field change for JSON output."""
|
|
21
|
+
|
|
22
|
+
field_path: str
|
|
23
|
+
severity: str
|
|
24
|
+
description: str
|
|
25
|
+
|
|
26
|
+
@classmethod
|
|
27
|
+
def from_field_change(cls, field_change: FieldChange) -> list["SerializedFieldChange"]:
|
|
28
|
+
"""Serialize a field change, handling nested FieldChanges recursively.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
field_change: The field change to serialize.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
List of serialized field changes (may be multiple if nested).
|
|
35
|
+
"""
|
|
36
|
+
serialized_changes: list[SerializedFieldChange] = []
|
|
37
|
+
|
|
38
|
+
if isinstance(field_change, FieldChanges):
|
|
39
|
+
# Recursively handle nested changes
|
|
40
|
+
for change in field_change.changes:
|
|
41
|
+
serialized_changes.extend(cls.from_field_change(change))
|
|
42
|
+
else:
|
|
43
|
+
# Base case: single field change
|
|
44
|
+
serialized_changes.append(cls._from_single_field_change(field_change))
|
|
45
|
+
|
|
46
|
+
return serialized_changes
|
|
47
|
+
|
|
48
|
+
@classmethod
|
|
49
|
+
def _from_single_field_change(cls, field_change: FieldChange) -> "SerializedFieldChange":
|
|
50
|
+
"""Serialize a single non-nested field change.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
field_change: The single field change to serialize.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
Serialized field change.
|
|
57
|
+
"""
|
|
58
|
+
return cls(
|
|
59
|
+
field_path=field_change.field_path,
|
|
60
|
+
severity=field_change.severity.name,
|
|
61
|
+
description=field_change.description
|
|
62
|
+
if isinstance(field_change, AddedField | RemovedField | ChangedField)
|
|
63
|
+
else "Field changed",
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class SerializedResourceChange(BaseModel):
|
|
68
|
+
"""Serialized resource change for JSON output."""
|
|
69
|
+
|
|
70
|
+
id: int
|
|
71
|
+
endpoint: str
|
|
72
|
+
change_type: str
|
|
73
|
+
severity: str
|
|
74
|
+
resource_id: str
|
|
75
|
+
message: str | None = None
|
|
76
|
+
changes: list[SerializedFieldChange] = Field(default_factory=list)
|
|
77
|
+
|
|
78
|
+
@classmethod
|
|
79
|
+
def from_resource_change(
|
|
80
|
+
cls, resource: ResourceChange, endpoint: str, change_id: int
|
|
81
|
+
) -> "SerializedResourceChange":
|
|
82
|
+
"""Serialize a single resource change.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
resource: The resource change to serialize.
|
|
86
|
+
endpoint: The endpoint type.
|
|
87
|
+
change_id: Unique ID for this change.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
Serialized resource change.
|
|
91
|
+
"""
|
|
92
|
+
changes: list[SerializedFieldChange] = []
|
|
93
|
+
|
|
94
|
+
for change in resource.changes:
|
|
95
|
+
changes.extend(SerializedFieldChange.from_field_change(change))
|
|
96
|
+
|
|
97
|
+
return cls(
|
|
98
|
+
id=change_id,
|
|
99
|
+
endpoint=endpoint,
|
|
100
|
+
change_type=resource.change_type,
|
|
101
|
+
severity=resource.severity.name,
|
|
102
|
+
resource_id=str(resource.resource_id),
|
|
103
|
+
changes=changes,
|
|
104
|
+
message=resource.message,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
@classmethod
|
|
108
|
+
def from_change_result(cls, change_id: int, response: ChangeResult) -> "SerializedResourceChange":
|
|
109
|
+
"""Serialize from a change result (actual deployment).
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
change_id: Unique ID for this change.
|
|
113
|
+
response: The change result from deployment.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
Serialized resource change with deployment status.
|
|
117
|
+
"""
|
|
118
|
+
serialized_resource_change = cls.from_resource_change(
|
|
119
|
+
resource=response.change,
|
|
120
|
+
endpoint=response.endpoint,
|
|
121
|
+
change_id=change_id,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
serialized_resource_change.message = response.message
|
|
125
|
+
if not response.is_success:
|
|
126
|
+
serialized_resource_change.change_type = "failed"
|
|
127
|
+
|
|
128
|
+
return serialized_resource_change
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class SerializedChanges(BaseModel):
|
|
132
|
+
"""Container for all serialized changes."""
|
|
133
|
+
|
|
134
|
+
changes: list[SerializedResourceChange] = Field(default_factory=list)
|
|
135
|
+
|
|
136
|
+
@classmethod
|
|
137
|
+
def from_deployment_result(cls, result: DeploymentResult) -> "SerializedChanges":
|
|
138
|
+
"""Create SerializedChanges from a DeploymentResult.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
result: The deployment result to serialize changes from.
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
SerializedChanges instance with all changes.
|
|
145
|
+
"""
|
|
146
|
+
serialized = cls()
|
|
147
|
+
|
|
148
|
+
if not result.responses:
|
|
149
|
+
serialized._add_from_dry_run(result)
|
|
150
|
+
else:
|
|
151
|
+
serialized._add_from_applied_changes(result.responses)
|
|
152
|
+
|
|
153
|
+
return serialized
|
|
154
|
+
|
|
155
|
+
def _add_from_dry_run(self, result: DeploymentResult) -> None:
|
|
156
|
+
"""Add changes from dry run deployment.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
result: The deployment result in dry run mode.
|
|
160
|
+
"""
|
|
161
|
+
# Iterate over each endpoint plan
|
|
162
|
+
for endpoint_plan in result.plan:
|
|
163
|
+
# Then per resource in the endpoint
|
|
164
|
+
for resource in endpoint_plan.resources:
|
|
165
|
+
# Then serialize individual resource change
|
|
166
|
+
serialized_resource_change = SerializedResourceChange.from_resource_change(
|
|
167
|
+
resource=resource,
|
|
168
|
+
endpoint=endpoint_plan.endpoint,
|
|
169
|
+
change_id=len(self.changes),
|
|
170
|
+
)
|
|
171
|
+
self.changes.append(serialized_resource_change)
|
|
172
|
+
|
|
173
|
+
def _add_from_applied_changes(self, applied_changes: AppliedChanges) -> None:
|
|
174
|
+
"""Add changes from actual deployment.
|
|
175
|
+
Args:
|
|
176
|
+
result: The deployment result from actual deployment.
|
|
177
|
+
"""
|
|
178
|
+
for response in itertools.chain(
|
|
179
|
+
applied_changes.created,
|
|
180
|
+
applied_changes.merged_updated,
|
|
181
|
+
applied_changes.deletions,
|
|
182
|
+
applied_changes.unchanged,
|
|
183
|
+
applied_changes.skipped,
|
|
184
|
+
):
|
|
185
|
+
self.changes.append(SerializedResourceChange.from_change_result(len(self.changes), response))
|
|
186
|
+
|
|
187
|
+
def model_dump_json_flat(self, **kwargs: Any) -> str:
|
|
188
|
+
"""Dump changes as JSON array without the wrapper key.
|
|
189
|
+
Returns:
|
|
190
|
+
JSON string of the changes array.
|
|
191
|
+
"""
|
|
192
|
+
if not self.changes:
|
|
193
|
+
return "[]"
|
|
194
|
+
|
|
195
|
+
iterator = (change.model_dump_json(**kwargs) for change in self.changes)
|
|
196
|
+
return f"[{','.join(iterator)}]"
|