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,58 @@
|
|
|
1
|
+
"""Validators checking for consistency issues in data model."""
|
|
2
|
+
|
|
3
|
+
from cognite.neat._data_model._constants import COGNITE_SPACES
|
|
4
|
+
from cognite.neat._data_model.validation.dms._base import DataModelValidator
|
|
5
|
+
from cognite.neat._issues import Recommendation
|
|
6
|
+
|
|
7
|
+
BASE_CODE = "NEAT-DMS-CONSISTENCY"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ViewSpaceVersionInconsistentWithDataModel(DataModelValidator):
|
|
11
|
+
"""Validates that views have consistent space and version with the data model.
|
|
12
|
+
|
|
13
|
+
## What it does
|
|
14
|
+
Validates that all views in the data model have the same space and version as the data model.
|
|
15
|
+
|
|
16
|
+
## Why is this bad?
|
|
17
|
+
If views have different space or version than the data model, it may lead to more demanding development and
|
|
18
|
+
maintenance efforts. The industry best practice is to keep views in the same space and version as the data model.
|
|
19
|
+
|
|
20
|
+
## Example
|
|
21
|
+
If the data model is defined in space "my_space" version "v1", but a view is defined in the same spave but with
|
|
22
|
+
version "v2", this requires additional attention during deployment and maintenance of the data model.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
code = f"{BASE_CODE}-001"
|
|
26
|
+
issue_type = Recommendation
|
|
27
|
+
|
|
28
|
+
def run(self) -> list[Recommendation]:
|
|
29
|
+
recommendations: list[Recommendation] = []
|
|
30
|
+
|
|
31
|
+
if not self.validation_resources.merged_data_model.views:
|
|
32
|
+
return recommendations
|
|
33
|
+
|
|
34
|
+
space = self.validation_resources.merged_data_model.space
|
|
35
|
+
version = self.validation_resources.merged_data_model.version
|
|
36
|
+
|
|
37
|
+
for view_ref in self.validation_resources.merged_data_model.views:
|
|
38
|
+
issue_description = ""
|
|
39
|
+
|
|
40
|
+
if view_ref.space not in COGNITE_SPACES:
|
|
41
|
+
# notify about inconsistent space
|
|
42
|
+
if view_ref.space != space:
|
|
43
|
+
issue_description = f"space (view: {view_ref.space}, data model: {space})"
|
|
44
|
+
|
|
45
|
+
# or version if spaces are same
|
|
46
|
+
elif view_ref.version != version:
|
|
47
|
+
issue_description = f"version (view: {view_ref.version}, data model: {version})"
|
|
48
|
+
|
|
49
|
+
if issue_description:
|
|
50
|
+
recommendations.append(
|
|
51
|
+
Recommendation(
|
|
52
|
+
message=(f"View {view_ref!s} has inconsistent {issue_description} with the data model."),
|
|
53
|
+
fix="Update view version and/or space to match data model",
|
|
54
|
+
code=self.code,
|
|
55
|
+
)
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
return recommendations
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"""Validators for checking containers in the data model."""
|
|
2
|
+
|
|
3
|
+
from pyparsing import cast
|
|
4
|
+
|
|
5
|
+
from cognite.neat._data_model.models.dms._constraints import Constraint, RequiresConstraintDefinition
|
|
6
|
+
from cognite.neat._data_model.models.dms._view_property import ViewCorePropertyRequest
|
|
7
|
+
from cognite.neat._data_model.validation.dms._base import DataModelValidator
|
|
8
|
+
from cognite.neat._issues import ConsistencyError
|
|
9
|
+
|
|
10
|
+
BASE_CODE = "NEAT-DMS-CONTAINER"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ExternalContainerDoesNotExist(DataModelValidator):
|
|
14
|
+
"""
|
|
15
|
+
Validates that any container referenced by a view property, when the
|
|
16
|
+
referenced container does not belong to the data model's space, exists in CDF.
|
|
17
|
+
|
|
18
|
+
## What it does
|
|
19
|
+
For each view property that maps to a container in a different space than the data model,
|
|
20
|
+
this validator checks that the referenced external container exists in CDF.
|
|
21
|
+
|
|
22
|
+
## Why is this bad?
|
|
23
|
+
If a view property references a container that does not exist in CDF,
|
|
24
|
+
the data model cannot be deployed. The affected view property will not function, and the
|
|
25
|
+
deployment of the entire data model will fail.
|
|
26
|
+
|
|
27
|
+
## Example
|
|
28
|
+
View `my_space:WindTurbine` has a property `location` that maps to container
|
|
29
|
+
`other_space:WindTurbineContainer`, where `other_space` differs from `my_space`. If that
|
|
30
|
+
container does not exist in CDF, the model cannot be deployed.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
code = f"{BASE_CODE}-001"
|
|
34
|
+
issue_type = ConsistencyError
|
|
35
|
+
|
|
36
|
+
def run(self) -> list[ConsistencyError]:
|
|
37
|
+
errors: list[ConsistencyError] = []
|
|
38
|
+
|
|
39
|
+
if not self.validation_resources.merged_data_model.views:
|
|
40
|
+
return errors
|
|
41
|
+
|
|
42
|
+
for view_ref in self.validation_resources.merged_data_model.views:
|
|
43
|
+
view = self.validation_resources.select_view(view_ref)
|
|
44
|
+
|
|
45
|
+
if not view:
|
|
46
|
+
raise RuntimeError(
|
|
47
|
+
f"{type(self).__name__}: View {view_ref!s} not found in local resources. This is a bug in NEAT."
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
if view.properties is None:
|
|
51
|
+
continue
|
|
52
|
+
|
|
53
|
+
for property_ref, property_ in view.properties.items():
|
|
54
|
+
if not isinstance(property_, ViewCorePropertyRequest):
|
|
55
|
+
continue
|
|
56
|
+
|
|
57
|
+
if property_.container.space == self.validation_resources.merged_data_model.space:
|
|
58
|
+
continue
|
|
59
|
+
|
|
60
|
+
# Check existence of container in CDF
|
|
61
|
+
if property_.container not in self.validation_resources.cdf.containers:
|
|
62
|
+
errors.append(
|
|
63
|
+
ConsistencyError(
|
|
64
|
+
message=(
|
|
65
|
+
f"View {view_ref!s} property {property_ref!s} maps to "
|
|
66
|
+
f"external container {property_.container!s} which does not exist in CDF."
|
|
67
|
+
),
|
|
68
|
+
fix="Define necessary container in CDF",
|
|
69
|
+
code=self.code,
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
return errors
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class ExternalContainerPropertyDoesNotExist(DataModelValidator):
|
|
77
|
+
"""
|
|
78
|
+
Validates that any container property referenced by a view property, when the
|
|
79
|
+
referenced container does not belong to the data model's space, exists in CDF.
|
|
80
|
+
|
|
81
|
+
## What it does
|
|
82
|
+
For each view property that maps to a container in a different space than the data model,
|
|
83
|
+
this validator checks that the referenced container property exists in that external container in CDF.
|
|
84
|
+
This validator only runs if the external container exists in CDF.
|
|
85
|
+
|
|
86
|
+
## Why is this bad?
|
|
87
|
+
If a view property references a container property that does not exist in CDF,
|
|
88
|
+
the data model cannot be deployed. The affected view property will not function, and the
|
|
89
|
+
deployment of the entire data model will fail.
|
|
90
|
+
|
|
91
|
+
## Example
|
|
92
|
+
View `my_space:WindTurbine` has a property `location` that maps to container property
|
|
93
|
+
`gpsCoordinates` in `other_space:WindTurbineContainer`. If `gpsCoordinates` does not exist
|
|
94
|
+
in that container in CDF, deployment will fail.
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
code = f"{BASE_CODE}-002"
|
|
98
|
+
issue_type = ConsistencyError
|
|
99
|
+
|
|
100
|
+
def run(self) -> list[ConsistencyError]:
|
|
101
|
+
errors: list[ConsistencyError] = []
|
|
102
|
+
|
|
103
|
+
if self.validation_resources.merged_data_model.views:
|
|
104
|
+
for view_ref in self.validation_resources.merged_data_model.views:
|
|
105
|
+
view = self.validation_resources.select_view(view_ref)
|
|
106
|
+
|
|
107
|
+
if not view:
|
|
108
|
+
raise RuntimeError(
|
|
109
|
+
f"{type(self).__name__}: View {view_ref!s} not found in local resources. This is a bug in NEAT."
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
if view.properties is None:
|
|
113
|
+
continue
|
|
114
|
+
|
|
115
|
+
for property_ref, property_ in view.properties.items():
|
|
116
|
+
if not isinstance(property_, ViewCorePropertyRequest):
|
|
117
|
+
continue
|
|
118
|
+
|
|
119
|
+
if property_.container.space == self.validation_resources.merged_data_model.space:
|
|
120
|
+
continue
|
|
121
|
+
|
|
122
|
+
# Only check property if container exists in CDF
|
|
123
|
+
# this check is done in ExternalContainerDoesNotExist
|
|
124
|
+
if property_.container not in self.validation_resources.cdf.containers:
|
|
125
|
+
continue
|
|
126
|
+
|
|
127
|
+
# Check existence of container property in CDF
|
|
128
|
+
if (
|
|
129
|
+
property_.container_property_identifier
|
|
130
|
+
not in self.validation_resources.cdf.containers[property_.container].properties
|
|
131
|
+
):
|
|
132
|
+
errors.append(
|
|
133
|
+
ConsistencyError(
|
|
134
|
+
message=(
|
|
135
|
+
f"View {view_ref!s} property {property_ref!s} maps to "
|
|
136
|
+
f"external container {property_.container!s} which does not have "
|
|
137
|
+
f"property '{property_.container_property_identifier}' in CDF."
|
|
138
|
+
),
|
|
139
|
+
fix="Define necessary container property in CDF",
|
|
140
|
+
code=self.code,
|
|
141
|
+
)
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
return errors
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class RequiredContainerDoesNotExist(DataModelValidator):
|
|
148
|
+
"""
|
|
149
|
+
Validates that any container required by another container exists in the data model.
|
|
150
|
+
|
|
151
|
+
## What it does
|
|
152
|
+
For each container in the data model, this validator checks that any container it
|
|
153
|
+
requires (via requires constraints) exists either in the data model or in CDF.
|
|
154
|
+
|
|
155
|
+
## Why is this bad?
|
|
156
|
+
If a container requires another container that does not exist in the data model or in CDF,
|
|
157
|
+
the data model cannot be deployed. The affected container will not function, and
|
|
158
|
+
the deployment of the entire data model will fail.
|
|
159
|
+
|
|
160
|
+
## Example
|
|
161
|
+
Container `windy_space:WindTurbineContainer` has a constraint requiring `windy_space:LocationContainer`.
|
|
162
|
+
If `windy_space:LocationContainer` does not exist in the data model or in CDF, deployment will fail.
|
|
163
|
+
"""
|
|
164
|
+
|
|
165
|
+
code = f"{BASE_CODE}-003"
|
|
166
|
+
issue_type = ConsistencyError
|
|
167
|
+
|
|
168
|
+
def run(self) -> list[ConsistencyError]:
|
|
169
|
+
errors: list[ConsistencyError] = []
|
|
170
|
+
|
|
171
|
+
for container_ref in self.validation_resources.merged.containers:
|
|
172
|
+
container = self.validation_resources.select_container(container_ref)
|
|
173
|
+
|
|
174
|
+
if not container:
|
|
175
|
+
raise RuntimeError(
|
|
176
|
+
f"{type(self).__name__}: Container {container_ref!s} "
|
|
177
|
+
"not found in local resources. This is a bug in NEAT."
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
if not container.constraints:
|
|
181
|
+
continue
|
|
182
|
+
|
|
183
|
+
for constraint_ref, constraint in cast(dict[str, Constraint], container.constraints).items():
|
|
184
|
+
if not isinstance(constraint, RequiresConstraintDefinition):
|
|
185
|
+
continue
|
|
186
|
+
|
|
187
|
+
if not self.validation_resources.select_container(constraint.require):
|
|
188
|
+
errors.append(
|
|
189
|
+
ConsistencyError(
|
|
190
|
+
message=(
|
|
191
|
+
f"Container '{container_ref!s}' constraint '{constraint_ref}' requires container "
|
|
192
|
+
f"'{constraint.require!s}' which does not exist."
|
|
193
|
+
),
|
|
194
|
+
fix="Define necessary container in the data model",
|
|
195
|
+
code=self.code,
|
|
196
|
+
)
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
return errors
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
"""Validators for checking if defined data model is within CDF DMS schema limits."""
|
|
2
|
+
|
|
3
|
+
from typing import Literal
|
|
4
|
+
|
|
5
|
+
from cognite.neat._data_model.models.dms._container import ContainerRequest
|
|
6
|
+
from cognite.neat._data_model.models.dms._data_types import EnumProperty, ListablePropertyTypeDefinition
|
|
7
|
+
from cognite.neat._data_model.models.dms._indexes import BtreeIndex, InvertedIndex
|
|
8
|
+
from cognite.neat._data_model.models.dms._view_property import (
|
|
9
|
+
ViewCorePropertyRequest,
|
|
10
|
+
)
|
|
11
|
+
from cognite.neat._data_model.validation.dms._base import (
|
|
12
|
+
DataModelValidator,
|
|
13
|
+
)
|
|
14
|
+
from cognite.neat._issues import ConsistencyError
|
|
15
|
+
|
|
16
|
+
BASE_CODE = "NEAT-DMS-LIMITS"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class DataModelViewCountIsOutOfLimits(DataModelValidator):
|
|
20
|
+
"""Validates that the data model does not exceed the maximum number of views.
|
|
21
|
+
|
|
22
|
+
## What it does
|
|
23
|
+
This validator checks that the total number of views referenced by the data model
|
|
24
|
+
does not exceed the limit defined in the CDF project.
|
|
25
|
+
|
|
26
|
+
## Why is this bad?
|
|
27
|
+
CDF enforces limits on the number of views per data model to ensure optimal performance
|
|
28
|
+
and resource utilization.
|
|
29
|
+
|
|
30
|
+
## Example
|
|
31
|
+
If the CDF project has a limit of 100 views per data model, and the data model
|
|
32
|
+
references 120 views, this validator will raise a ConsistencyError issue.
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
code = f"{BASE_CODE}-DATA-MODEL-001"
|
|
37
|
+
issue_type = ConsistencyError
|
|
38
|
+
|
|
39
|
+
def run(self) -> list[ConsistencyError]:
|
|
40
|
+
errors: list[ConsistencyError] = []
|
|
41
|
+
|
|
42
|
+
if self.validation_resources.merged_data_model.views is None:
|
|
43
|
+
errors.append(
|
|
44
|
+
ConsistencyError(
|
|
45
|
+
message="The data model does not have any views. This means it is not a data model.",
|
|
46
|
+
code=self.code,
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
elif (
|
|
51
|
+
len(self.validation_resources.merged_data_model.views) > self.validation_resources.limits.data_models.views
|
|
52
|
+
):
|
|
53
|
+
errors.append(
|
|
54
|
+
ConsistencyError(
|
|
55
|
+
message=(
|
|
56
|
+
f"The data model references {len(self.validation_resources.merged_data_model.views)} views, "
|
|
57
|
+
"which exceeds the limit of "
|
|
58
|
+
f"{self.validation_resources.limits.data_models.views} views per data model."
|
|
59
|
+
),
|
|
60
|
+
code=self.code,
|
|
61
|
+
)
|
|
62
|
+
)
|
|
63
|
+
return errors
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
### View level limits
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class ViewPropertyCountIsOutOfLimits(DataModelValidator):
|
|
70
|
+
"""Validates that a view does not exceed the maximum number of properties.
|
|
71
|
+
|
|
72
|
+
## What it does
|
|
73
|
+
Checks that the view has no more properties than the CDF limit allows.
|
|
74
|
+
|
|
75
|
+
## Why is this bad?
|
|
76
|
+
CDF enforces limits on the number of properties per view to ensure optimal performance.
|
|
77
|
+
|
|
78
|
+
## Example
|
|
79
|
+
If a view has 150 properties and the CDF limit is 100 properties per view,
|
|
80
|
+
this validator will raise a ConsistencyError issue.
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
code = f"{BASE_CODE}-VIEW-001"
|
|
84
|
+
issue_type = ConsistencyError
|
|
85
|
+
|
|
86
|
+
def run(self) -> list[ConsistencyError]:
|
|
87
|
+
errors: list[ConsistencyError] = []
|
|
88
|
+
|
|
89
|
+
for view_ref in self.validation_resources.merged_data_model.views or []:
|
|
90
|
+
if not (view := self.validation_resources.expand_view_properties(view_ref)):
|
|
91
|
+
raise RuntimeError(f"{type(self).__name__}: View {view_ref!s} not found. This is a bug in NEAT.")
|
|
92
|
+
|
|
93
|
+
if view.properties and len(view.properties) > self.validation_resources.limits.views.properties:
|
|
94
|
+
errors.append(
|
|
95
|
+
ConsistencyError(
|
|
96
|
+
message=(
|
|
97
|
+
f"View {view_ref!s} has {len(view.properties)} properties,"
|
|
98
|
+
" which exceeds the limit of "
|
|
99
|
+
f"{self.validation_resources.limits.views.properties} properties per view."
|
|
100
|
+
),
|
|
101
|
+
code=self.code,
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
elif not view.properties:
|
|
106
|
+
errors.append(
|
|
107
|
+
ConsistencyError(
|
|
108
|
+
message=(
|
|
109
|
+
f"View {view_ref!s} does "
|
|
110
|
+
"not have any properties defined, either directly or through implements."
|
|
111
|
+
),
|
|
112
|
+
fix="Define at least one property for view",
|
|
113
|
+
code=self.code,
|
|
114
|
+
)
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
return errors
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class ViewContainerCountIsOutOfLimits(DataModelValidator):
|
|
121
|
+
"""Validates that a view does not reference too many containers.
|
|
122
|
+
|
|
123
|
+
## What it does
|
|
124
|
+
Checks that the view references no more containers than the CDF limit allows.
|
|
125
|
+
|
|
126
|
+
## Why is this bad?
|
|
127
|
+
CDF enforces limits on the number of containers per view to prevent overly complex view definitions, leading
|
|
128
|
+
to too many joins and performance degradation.
|
|
129
|
+
|
|
130
|
+
## Example
|
|
131
|
+
If a view references 20 containers and the CDF limit is 10 containers per view,
|
|
132
|
+
this validator will raise a ConsistencyError issue.
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
code = f"{BASE_CODE}-VIEW-002"
|
|
136
|
+
issue_type = ConsistencyError
|
|
137
|
+
|
|
138
|
+
def run(self) -> list[ConsistencyError]:
|
|
139
|
+
errors: list[ConsistencyError] = []
|
|
140
|
+
|
|
141
|
+
# Single loop over all views
|
|
142
|
+
for view_ref in self.validation_resources.merged_data_model.views or []:
|
|
143
|
+
if not (view := self.validation_resources.expand_view_properties(view_ref)):
|
|
144
|
+
raise RuntimeError(f"{type(self).__name__}: View {view_ref!s} not found. This is a bug in NEAT.")
|
|
145
|
+
|
|
146
|
+
if view.properties:
|
|
147
|
+
count = len(
|
|
148
|
+
{
|
|
149
|
+
prop.container
|
|
150
|
+
for prop in view.properties.values()
|
|
151
|
+
if (isinstance(prop, ViewCorePropertyRequest) and prop.container)
|
|
152
|
+
}
|
|
153
|
+
)
|
|
154
|
+
if count > self.validation_resources.limits.views.containers:
|
|
155
|
+
errors.append(
|
|
156
|
+
ConsistencyError(
|
|
157
|
+
message=(
|
|
158
|
+
f"View {view_ref!s} references "
|
|
159
|
+
f"{count} containers, which exceeds the limit of "
|
|
160
|
+
f"{self.validation_resources.limits.views.containers} containers per view."
|
|
161
|
+
),
|
|
162
|
+
code=self.code,
|
|
163
|
+
)
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
return errors
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class ViewImplementsCountIsOutOfLimits(DataModelValidator):
|
|
170
|
+
"""Validates that a view does not implement too many other views.
|
|
171
|
+
|
|
172
|
+
## What it does
|
|
173
|
+
Checks that the view implements no more views than the CDF limit allows.
|
|
174
|
+
|
|
175
|
+
## Why is this bad?
|
|
176
|
+
CDF enforces limits on the number of implemented views to prevent overly deep inheritance hierarchies.
|
|
177
|
+
|
|
178
|
+
## Example
|
|
179
|
+
If a view implements 15 other views and the CDF limit is 10 implemented views per view,
|
|
180
|
+
this validator will raise a ConsistencyError issue.
|
|
181
|
+
"""
|
|
182
|
+
|
|
183
|
+
code = f"{BASE_CODE}-VIEW-003"
|
|
184
|
+
issue_type = ConsistencyError
|
|
185
|
+
|
|
186
|
+
def run(self) -> list[ConsistencyError]:
|
|
187
|
+
errors: list[ConsistencyError] = []
|
|
188
|
+
|
|
189
|
+
# Single loop over all views
|
|
190
|
+
for view_ref in self.validation_resources.merged_data_model.views or []:
|
|
191
|
+
ancestors = self.validation_resources.view_ancestors(view_ref)
|
|
192
|
+
if ancestors and len(ancestors) > self.validation_resources.limits.views.implements:
|
|
193
|
+
errors.append(
|
|
194
|
+
ConsistencyError(
|
|
195
|
+
message=(
|
|
196
|
+
f"View {view_ref!s} implements {len(ancestors)} views,"
|
|
197
|
+
" which exceeds the limit of"
|
|
198
|
+
f" {self.validation_resources.limits.views.implements} implemented views per view."
|
|
199
|
+
),
|
|
200
|
+
code=self.code,
|
|
201
|
+
)
|
|
202
|
+
)
|
|
203
|
+
return errors
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
### Container level limits
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
class ContainerPropertyCountIsOutOfLimits(DataModelValidator):
|
|
210
|
+
"""Validates that a container does not exceed the maximum number of properties.
|
|
211
|
+
|
|
212
|
+
## What it does
|
|
213
|
+
Checks that the container has no more properties than the CDF limit allows.
|
|
214
|
+
|
|
215
|
+
## Why is this bad?
|
|
216
|
+
CDF enforces limits on the number of properties per container to ensure optimal performance
|
|
217
|
+
and prevent PostGres tables that have too many columns.
|
|
218
|
+
|
|
219
|
+
## Example
|
|
220
|
+
If a container has 150 properties and the CDF limit is 100 properties per container,
|
|
221
|
+
this validator will raise a ConsistencyError issue.
|
|
222
|
+
"""
|
|
223
|
+
|
|
224
|
+
code = f"{BASE_CODE}-CONTAINER-001"
|
|
225
|
+
issue_type = ConsistencyError
|
|
226
|
+
|
|
227
|
+
def run(self) -> list[ConsistencyError]:
|
|
228
|
+
errors: list[ConsistencyError] = []
|
|
229
|
+
# Single loop over all containers
|
|
230
|
+
for container_ref in self.validation_resources.merged.containers:
|
|
231
|
+
container = self.validation_resources.select_container(container_ref)
|
|
232
|
+
|
|
233
|
+
if not container:
|
|
234
|
+
raise RuntimeError(
|
|
235
|
+
f"{type(self).__name__}: Container {container_ref!s} "
|
|
236
|
+
"not found in local resources. This is a bug in NEAT."
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
if (
|
|
240
|
+
container.properties
|
|
241
|
+
and len(container.properties) > self.validation_resources.limits.containers.properties()
|
|
242
|
+
):
|
|
243
|
+
errors.append(
|
|
244
|
+
ConsistencyError(
|
|
245
|
+
message=(
|
|
246
|
+
f"Container {container_ref!s} has {len(container.properties)} properties, "
|
|
247
|
+
"which exceeds the limit of "
|
|
248
|
+
f"{self.validation_resources.limits.containers.properties()} properties per container."
|
|
249
|
+
),
|
|
250
|
+
fix="Define at least one property for container",
|
|
251
|
+
code=self.code,
|
|
252
|
+
)
|
|
253
|
+
)
|
|
254
|
+
elif not container.properties:
|
|
255
|
+
errors.append(
|
|
256
|
+
ConsistencyError(
|
|
257
|
+
message=(f"Container {container_ref!s} does not have any properties defined."),
|
|
258
|
+
fix="Define at least one property for container",
|
|
259
|
+
code=self.code,
|
|
260
|
+
)
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
return errors
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
class ContainerPropertyListSizeIsOutOfLimits(DataModelValidator):
|
|
267
|
+
"""Validates that container property list sizes do not exceed CDF limits.
|
|
268
|
+
|
|
269
|
+
## What it does
|
|
270
|
+
Checks that list-type properties (max_list_size) do not exceed the appropriate limit based on:
|
|
271
|
+
- Data type (Int32, Int64, DirectRelation, etc.)
|
|
272
|
+
- Presence of btree index
|
|
273
|
+
- Default vs maximum limits
|
|
274
|
+
|
|
275
|
+
## Why is this bad?
|
|
276
|
+
CDF enforces different list size limits for different data types and indexing configurations
|
|
277
|
+
to ensure optimal performance and prevent resource exhaustion.
|
|
278
|
+
|
|
279
|
+
## Example
|
|
280
|
+
If a DirectRelation property has max_list_size=2000 with a btree index, but the limit
|
|
281
|
+
is 1000 for indexed DirectRelations, this validator will raise a ConsistencyError issue.
|
|
282
|
+
|
|
283
|
+
## Note
|
|
284
|
+
Enum properties are skipped as they have a separate 32-value limit checked during read time of data model to neat
|
|
285
|
+
as a SyntaxError check.
|
|
286
|
+
"""
|
|
287
|
+
|
|
288
|
+
code = f"{BASE_CODE}-CONTAINER-002"
|
|
289
|
+
issue_type = ConsistencyError
|
|
290
|
+
|
|
291
|
+
def run(self) -> list[ConsistencyError]:
|
|
292
|
+
errors: list[ConsistencyError] = []
|
|
293
|
+
|
|
294
|
+
# Single loop over all containers
|
|
295
|
+
for container_ref in self.validation_resources.merged.containers:
|
|
296
|
+
container = self.validation_resources.select_container(container_ref)
|
|
297
|
+
|
|
298
|
+
if not container:
|
|
299
|
+
raise RuntimeError(
|
|
300
|
+
f"{type(self).__name__}: Container {container_ref!s} "
|
|
301
|
+
"not found in local resources. This is a bug in NEAT."
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
properties_by_index_type = self.container_property_by_index_type(container)
|
|
305
|
+
|
|
306
|
+
for property_id, property_ in container.properties.items():
|
|
307
|
+
type_ = property_.type
|
|
308
|
+
|
|
309
|
+
# Skip enum properties (have separate 32-value limit)
|
|
310
|
+
if isinstance(type_, EnumProperty):
|
|
311
|
+
continue
|
|
312
|
+
|
|
313
|
+
# Only check listable properties with max_list_size set
|
|
314
|
+
if not isinstance(type_, ListablePropertyTypeDefinition) or type_.max_list_size is None:
|
|
315
|
+
continue
|
|
316
|
+
|
|
317
|
+
has_btree_index = property_id in properties_by_index_type[BtreeIndex.model_fields["index_type"].default]
|
|
318
|
+
limit = self.validation_resources.limits.containers.properties.listable(type_, has_btree_index)
|
|
319
|
+
|
|
320
|
+
if type_.max_list_size > limit:
|
|
321
|
+
errors.append(
|
|
322
|
+
ConsistencyError(
|
|
323
|
+
message=(
|
|
324
|
+
f"Container {container_ref!s} has property {property_id} with list size "
|
|
325
|
+
f"{type_.max_list_size}, which exceeds the limit of {limit} "
|
|
326
|
+
f"for data type {type_.__class__.__name__}."
|
|
327
|
+
),
|
|
328
|
+
code=self.code,
|
|
329
|
+
)
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
return errors
|
|
333
|
+
|
|
334
|
+
@staticmethod
|
|
335
|
+
def container_property_by_index_type(container: ContainerRequest) -> dict[Literal["btree", "inverted"], list]:
|
|
336
|
+
"""Map container properties to their index types for limit validation.
|
|
337
|
+
|
|
338
|
+
Categorizes container properties by their index configuration:
|
|
339
|
+
- "btree": Properties with btree indexes (have stricter list size limits)
|
|
340
|
+
- "inverted": Properties with inverted indexes
|
|
341
|
+
|
|
342
|
+
This mapping is used to determine the appropriate list size limit for
|
|
343
|
+
each property based on whether it has a btree index.
|
|
344
|
+
|
|
345
|
+
Args:
|
|
346
|
+
container: The container to analyze.
|
|
347
|
+
|
|
348
|
+
Returns:
|
|
349
|
+
Dictionary with index type strings as keys and lists of property identifiers
|
|
350
|
+
as values. Returns empty lists for both index types if container has no indexes.
|
|
351
|
+
"""
|
|
352
|
+
|
|
353
|
+
container_property_by_index_type: dict[Literal["btree", "inverted"], list] = {
|
|
354
|
+
BtreeIndex.model_fields["index_type"].default: [],
|
|
355
|
+
InvertedIndex.model_fields["index_type"].default: [],
|
|
356
|
+
}
|
|
357
|
+
if not container.indexes:
|
|
358
|
+
return container_property_by_index_type
|
|
359
|
+
|
|
360
|
+
for index in container.indexes.values():
|
|
361
|
+
if isinstance(index, BtreeIndex):
|
|
362
|
+
container_property_by_index_type[BtreeIndex.model_fields["index_type"].default].extend(index.properties)
|
|
363
|
+
elif isinstance(index, InvertedIndex):
|
|
364
|
+
container_property_by_index_type[InvertedIndex.model_fields["index_type"].default].extend(
|
|
365
|
+
index.properties
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
return container_property_by_index_type
|