cognite-neat 0.88.2__tar.gz → 0.88.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of cognite-neat might be problematic. Click here for more details.
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/PKG-INFO +1 -1
- cognite_neat-0.88.3/cognite/neat/_version.py +1 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/loaders/_base.py +3 -3
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/loaders/_rdf2asset.py +24 -25
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/loaders/_rdf2dms.py +20 -15
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/issues/__init__.py +1 -3
- cognite_neat-0.88.3/cognite/neat/issues/_base.py +415 -0
- cognite_neat-0.88.3/cognite/neat/issues/errors/__init__.py +72 -0
- cognite_neat-0.88.3/cognite/neat/issues/errors/_external.py +67 -0
- cognite_neat-0.88.3/cognite/neat/issues/errors/_general.py +28 -0
- cognite_neat-0.88.3/cognite/neat/issues/errors/_properties.py +62 -0
- cognite_neat-0.88.3/cognite/neat/issues/errors/_resources.py +111 -0
- cognite_neat-0.88.3/cognite/neat/issues/errors/_workflow.py +36 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/issues/formatters.py +1 -1
- cognite_neat-0.88.3/cognite/neat/issues/warnings/__init__.py +66 -0
- cognite_neat-0.88.3/cognite/neat/issues/warnings/_external.py +40 -0
- cognite_neat-0.88.3/cognite/neat/issues/warnings/_general.py +29 -0
- cognite_neat-0.88.3/cognite/neat/issues/warnings/_models.py +92 -0
- cognite_neat-0.88.3/cognite/neat/issues/warnings/_properties.py +44 -0
- cognite_neat-0.88.3/cognite/neat/issues/warnings/_resources.py +55 -0
- cognite_neat-0.88.3/cognite/neat/issues/warnings/user_modeling.py +113 -0
- cognite_neat-0.88.3/cognite/neat/rules/_shared.py +18 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/exporters/_base.py +6 -6
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/exporters/_rules2dms.py +18 -11
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/exporters/_rules2excel.py +4 -4
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/exporters/_rules2ontology.py +74 -51
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/exporters/_rules2yaml.py +3 -3
- cognite_neat-0.88.3/cognite/neat/rules/exporters/_validation.py +14 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_base.py +8 -12
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_dms2rules.py +21 -24
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_dtdl2rules/dtdl_converter.py +22 -17
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_dtdl2rules/dtdl_importer.py +26 -19
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_dtdl2rules/spec.py +7 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_imf2rules/_imf2classes.py +1 -1
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_imf2rules/_imf2rules.py +9 -7
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_inference2rules.py +8 -8
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_owl2rules/_owl2classes.py +1 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_owl2rules/_owl2properties.py +1 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_owl2rules/_owl2rules.py +4 -4
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_shared.py +3 -3
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_spreadsheet2rules.py +35 -22
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_yaml2rules.py +23 -22
- cognite_neat-0.88.3/cognite/neat/rules/models/_constants.py +2 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/_rdfpath.py +4 -4
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/_types/_field.py +5 -10
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/asset/_rules.py +1 -3
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/asset/_validation.py +13 -9
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/dms/_converter.py +2 -4
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/dms/_exporter.py +30 -8
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/dms/_rules.py +23 -7
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/dms/_schema.py +87 -78
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/dms/_validation.py +104 -65
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/information/_converter.py +2 -2
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/information/_rules.py +7 -8
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/information/_validation.py +47 -24
- cognite_neat-0.88.3/cognite/neat/rules/transformers/_base.py +15 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/auxiliary.py +2 -35
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/text.py +17 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/base.py +4 -4
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/cdf_store.py +3 -3
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/data_contracts.py +1 -1
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/lib/current/graph_extractor.py +3 -3
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/lib/current/graph_loader.py +2 -2
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/lib/current/graph_store.py +1 -1
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/lib/current/rules_exporter.py +10 -10
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/lib/current/rules_importer.py +6 -6
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/lib/current/rules_validator.py +5 -6
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/lib/io/io_steps.py +5 -5
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps_registry.py +4 -5
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/pyproject.toml +1 -1
- cognite_neat-0.88.2/cognite/neat/_version.py +0 -1
- cognite_neat-0.88.2/cognite/neat/exceptions.py +0 -145
- cognite_neat-0.88.2/cognite/neat/graph/__init__.py +0 -3
- cognite_neat-0.88.2/cognite/neat/graph/exceptions.py +0 -90
- cognite_neat-0.88.2/cognite/neat/issues/_base.py +0 -226
- cognite_neat-0.88.2/cognite/neat/issues/errors/external.py +0 -21
- cognite_neat-0.88.2/cognite/neat/issues/errors/properties.py +0 -75
- cognite_neat-0.88.2/cognite/neat/issues/errors/resources.py +0 -123
- cognite_neat-0.88.2/cognite/neat/issues/neat_warnings/__init__.py +0 -2
- cognite_neat-0.88.2/cognite/neat/issues/neat_warnings/identifier.py +0 -27
- cognite_neat-0.88.2/cognite/neat/issues/neat_warnings/models.py +0 -22
- cognite_neat-0.88.2/cognite/neat/issues/neat_warnings/properties.py +0 -77
- cognite_neat-0.88.2/cognite/neat/issues/neat_warnings/resources.py +0 -125
- cognite_neat-0.88.2/cognite/neat/rules/_shared.py +0 -10
- cognite_neat-0.88.2/cognite/neat/rules/exporters/_validation.py +0 -99
- cognite_neat-0.88.2/cognite/neat/rules/issues/__init__.py +0 -22
- cognite_neat-0.88.2/cognite/neat/rules/issues/base.py +0 -63
- cognite_neat-0.88.2/cognite/neat/rules/issues/dms.py +0 -549
- cognite_neat-0.88.2/cognite/neat/rules/issues/fileread.py +0 -197
- cognite_neat-0.88.2/cognite/neat/rules/issues/ontology.py +0 -298
- cognite_neat-0.88.2/cognite/neat/rules/issues/spreadsheet.py +0 -563
- cognite_neat-0.88.2/cognite/neat/rules/issues/spreadsheet_file.py +0 -151
- cognite_neat-0.88.2/cognite/neat/rules/issues/tables.py +0 -72
- cognite_neat-0.88.2/cognite/neat/rules/models/_constants.py +0 -1
- cognite_neat-0.88.2/cognite/neat/workflows/_exceptions.py +0 -41
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/LICENSE +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/README.md +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/_shared.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/asgi/metrics.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/configuration.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/context_manager/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/context_manager/manager.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/data_classes/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/data_classes/rest.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/explorer.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/routers/configuration.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/routers/crud.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/routers/metrics.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/routers/workflows.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/utils/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/utils/data_mapping.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/utils/logging.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/utils/query_templates.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/main.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/monitoring/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/monitoring/metrics.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/index.html +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/.gitignore +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/README.md +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/asset-manifest.json +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/favicon.ico +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/img/architect-icon.svg +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/img/developer-icon.svg +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/img/sme-icon.svg +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/index.html +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/logo192.png +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/manifest.json +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/robots.txt +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/static/css/main.72e3d92e.css +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/static/css/main.72e3d92e.css.map +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/static/js/main.5a52cf09.js +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/static/js/main.5a52cf09.js.LICENSE.txt +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/static/js/main.5a52cf09.js.map +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/static/media/logo.8093b84df9ed36a174c629d6fe0b730d.svg +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/config.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/constants.py +0 -0
- {cognite_neat-0.88.2/cognite/neat/graph/extractors/_classic_cdf → cognite_neat-0.88.3/cognite/neat/graph}/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/_shared.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/_tracking/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/_tracking/base.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/_tracking/log.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/examples/Knowledge-Graph-Nordic44-dirty.xml +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/examples/Knowledge-Graph-Nordic44.xml +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/examples/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/examples/skos-capturing-sheet-wind-topics.xlsx +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_base.py +0 -0
- {cognite_neat-0.88.2/cognite/neat/issues/errors → cognite_neat-0.88.3/cognite/neat/graph/extractors/_classic_cdf}/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_classic_cdf/_assets.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_classic_cdf/_base.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_classic_cdf/_events.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_classic_cdf/_files.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_classic_cdf/_labels.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_classic_cdf/_relationships.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_classic_cdf/_sequences.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_classic_cdf/_timeseries.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_dexpi.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_mock_graph_generator.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_rdf_file.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/loaders/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/models.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/queries/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/queries/_base.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/queries/_construct.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/queries/_shared.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/transformers/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/transformers/_base.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/transformers/_classic_cdf.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/transformers/_rdfpath.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/py.typed +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/analysis/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/analysis/_asset.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/analysis/_base.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/analysis/_information.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/examples/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/examples/wind-energy.owl +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/exporters/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_dtdl2rules/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_dtdl2rules/_unit_lookup.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_imf2rules/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_imf2rules/_imf2metadata.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_imf2rules/_imf2properties.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_owl2rules/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_owl2rules/_owl2metadata.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/_base.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/_types/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/asset/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/asset/_converter.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/asset/_rules_input.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/asset/_serializer.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/data_types.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/dms/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/dms/_rules_input.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/dms/_serializer.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/domain.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/entities.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/information/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/information/_rules_input.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/information/_serializer.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/wrapped_entities.py +0 -0
- {cognite_neat-0.88.2/cognite/neat/utils → cognite_neat-0.88.3/cognite/neat/rules/transformers}/__init__.py +0 -0
- {cognite_neat-0.88.2/cognite/neat/graph/stores → cognite_neat-0.88.3/cognite/neat/store}/__init__.py +0 -0
- {cognite_neat-0.88.2/cognite/neat/graph/stores → cognite_neat-0.88.3/cognite/neat/store}/_base.py +0 -0
- {cognite_neat-0.88.2/cognite/neat/graph/stores → cognite_neat-0.88.3/cognite/neat/store}/_provenance.py +0 -0
- {cognite_neat-0.88.2/cognite/neat/utils/cdf → cognite_neat-0.88.3/cognite/neat/utils}/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/auth.py +0 -0
- {cognite_neat-0.88.2/cognite/neat/workflows/steps → cognite_neat-0.88.3/cognite/neat/utils/cdf}/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/cdf/data_classes.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/cdf/loaders/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/cdf/loaders/_base.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/cdf/loaders/_data_modeling.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/cdf/loaders/_ingestion.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/collection_.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/rdf_.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/regex_patterns.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/spreadsheet.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/time_.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/upload.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/xml_.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/examples/Export_DMS/workflow.yaml +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/examples/Import_DMS/workflow.yaml +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/examples/Validate_Rules/workflow.yaml +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/examples/Validate_Solution_Model/workflow.yaml +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/examples/Visualize_Data_Model_Using_Mock_Graph/workflow.yaml +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/examples/Visualize_Semantic_Data_Model/workflow.yaml +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/manager.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/model.py +0 -0
- {cognite_neat-0.88.2/cognite/neat/workflows/steps/lib → cognite_neat-0.88.3/cognite/neat/workflows/steps}/__init__.py +0 -0
- /cognite_neat-0.88.2/cognite/neat/issues/errors/schema.py → /cognite_neat-0.88.3/cognite/neat/workflows/steps/lib/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/lib/current/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/lib/io/__init__.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/step_model.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/tasks.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/triggers.py +0 -0
- {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/utils.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.88.3"
|
|
@@ -6,9 +6,9 @@ from typing import ClassVar, Generic, TypeVar
|
|
|
6
6
|
from cognite.client import CogniteClient
|
|
7
7
|
from cognite.client.data_classes.capabilities import Capability
|
|
8
8
|
|
|
9
|
-
from cognite.neat.graph import NeatGraphStore
|
|
10
9
|
from cognite.neat.issues import IssueList, NeatIssue, NeatIssueList
|
|
11
|
-
from cognite.neat.issues.errors
|
|
10
|
+
from cognite.neat.issues.errors import AuthorizationError
|
|
11
|
+
from cognite.neat.store import NeatGraphStore
|
|
12
12
|
from cognite.neat.utils.auxiliary import class_html_doc
|
|
13
13
|
from cognite.neat.utils.upload import UploadResult, UploadResultList
|
|
14
14
|
|
|
@@ -61,7 +61,7 @@ class CDFLoader(BaseLoader[T_Output]):
|
|
|
61
61
|
if missing_capabilities:
|
|
62
62
|
upload_result = UploadResult[Hashable](name=type(self).__name__)
|
|
63
63
|
upload_result.issues.append(
|
|
64
|
-
|
|
64
|
+
AuthorizationError(action="Upload to CDF", reason=str(missing_capabilities))
|
|
65
65
|
)
|
|
66
66
|
yield upload_result
|
|
67
67
|
return
|
|
@@ -19,12 +19,12 @@ from cognite.client.exceptions import CogniteAPIError, CogniteDuplicatedError
|
|
|
19
19
|
|
|
20
20
|
from cognite.neat.graph._tracking.base import Tracker
|
|
21
21
|
from cognite.neat.graph._tracking.log import LogTracker
|
|
22
|
-
from cognite.neat.
|
|
23
|
-
from cognite.neat.issues import
|
|
24
|
-
from cognite.neat.issues.errors.resources import InvalidResourceError
|
|
22
|
+
from cognite.neat.issues import IssueList, NeatError, NeatIssue, NeatIssueList
|
|
23
|
+
from cognite.neat.issues.errors import ResourceCreationError, ResourceNotFoundError
|
|
25
24
|
from cognite.neat.rules.analysis._asset import AssetAnalysis
|
|
26
25
|
from cognite.neat.rules.models import AssetRules
|
|
27
26
|
from cognite.neat.rules.models.entities import ClassEntity, EntityTypes
|
|
27
|
+
from cognite.neat.store import NeatGraphStore
|
|
28
28
|
from cognite.neat.utils.auxiliary import create_sha256_hash
|
|
29
29
|
from cognite.neat.utils.upload import UploadResult
|
|
30
30
|
|
|
@@ -122,6 +122,7 @@ class AssetLoader(CDFLoader[AssetWrite]):
|
|
|
122
122
|
tracker: Tracker,
|
|
123
123
|
stop_on_exception: bool,
|
|
124
124
|
) -> Iterable[Any]:
|
|
125
|
+
error: NeatError
|
|
125
126
|
for class_ in ordered_classes:
|
|
126
127
|
tracker.start(repr(class_.id))
|
|
127
128
|
|
|
@@ -143,20 +144,18 @@ class AssetLoader(CDFLoader[AssetWrite]):
|
|
|
143
144
|
|
|
144
145
|
# check on parent
|
|
145
146
|
if "parentExternalId" in fields and fields["parentExternalId"] not in self.processed_assets:
|
|
146
|
-
error =
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
else ''}"""
|
|
155
|
-
),
|
|
147
|
+
error = ResourceNotFoundError(
|
|
148
|
+
fields["parentExternalId"],
|
|
149
|
+
EntityTypes.asset,
|
|
150
|
+
identifier,
|
|
151
|
+
EntityTypes.asset,
|
|
152
|
+
f"Moving the asset {identifier} under orphanage {self.orphanage.external_id}"
|
|
153
|
+
if self.orphanage
|
|
154
|
+
else "",
|
|
156
155
|
)
|
|
157
156
|
tracker.issue(error)
|
|
158
157
|
if stop_on_exception:
|
|
159
|
-
raise error
|
|
158
|
+
raise error
|
|
160
159
|
yield error
|
|
161
160
|
|
|
162
161
|
# if orphanage is set asset will use orphanage as parent
|
|
@@ -171,10 +170,10 @@ class AssetLoader(CDFLoader[AssetWrite]):
|
|
|
171
170
|
yield AssetWrite.load(fields)
|
|
172
171
|
self.processed_assets.add(identifier)
|
|
173
172
|
except KeyError as e:
|
|
174
|
-
error =
|
|
173
|
+
error = ResourceCreationError(identifier, EntityTypes.asset, error=str(e))
|
|
175
174
|
tracker.issue(error)
|
|
176
175
|
if stop_on_exception:
|
|
177
|
-
raise error
|
|
176
|
+
raise error from e
|
|
178
177
|
yield error
|
|
179
178
|
|
|
180
179
|
yield _END_OF_CLASS
|
|
@@ -201,17 +200,17 @@ class AssetLoader(CDFLoader[AssetWrite]):
|
|
|
201
200
|
|
|
202
201
|
# check if source asset exists
|
|
203
202
|
if source_external_id not in self.processed_assets:
|
|
204
|
-
error =
|
|
203
|
+
error = ResourceCreationError(
|
|
205
204
|
resource_type=EntityTypes.relationship,
|
|
206
205
|
identifier=source_external_id,
|
|
207
|
-
|
|
206
|
+
error=(
|
|
208
207
|
f"Asset {source_external_id} does not exist! "
|
|
209
208
|
"Aborting creation of relationships which use this asset as the source."
|
|
210
209
|
),
|
|
211
210
|
)
|
|
212
211
|
tracker.issue(error)
|
|
213
212
|
if stop_on_exception:
|
|
214
|
-
raise error
|
|
213
|
+
raise error
|
|
215
214
|
yield error
|
|
216
215
|
continue
|
|
217
216
|
|
|
@@ -221,10 +220,10 @@ class AssetLoader(CDFLoader[AssetWrite]):
|
|
|
221
220
|
target_external_id = f"{self.external_id_prefix or ''}{target_external_id}"
|
|
222
221
|
# check if source asset exists
|
|
223
222
|
if target_external_id not in self.processed_assets:
|
|
224
|
-
error =
|
|
223
|
+
error = ResourceCreationError(
|
|
225
224
|
resource_type=EntityTypes.relationship,
|
|
226
225
|
identifier=target_external_id,
|
|
227
|
-
|
|
226
|
+
error=(
|
|
228
227
|
f"Asset {target_external_id} does not exist! "
|
|
229
228
|
f"Cannot create relationship between {source_external_id}"
|
|
230
229
|
f" and {target_external_id}. "
|
|
@@ -232,7 +231,7 @@ class AssetLoader(CDFLoader[AssetWrite]):
|
|
|
232
231
|
)
|
|
233
232
|
tracker.issue(error)
|
|
234
233
|
if stop_on_exception:
|
|
235
|
-
raise error
|
|
234
|
+
raise error
|
|
236
235
|
yield error
|
|
237
236
|
continue
|
|
238
237
|
|
|
@@ -248,14 +247,14 @@ class AssetLoader(CDFLoader[AssetWrite]):
|
|
|
248
247
|
labels=[label] if self.use_labels else None,
|
|
249
248
|
)
|
|
250
249
|
except KeyError as e:
|
|
251
|
-
error =
|
|
250
|
+
error = ResourceCreationError(
|
|
252
251
|
resource_type=EntityTypes.relationship,
|
|
253
252
|
identifier=external_id,
|
|
254
|
-
|
|
253
|
+
error=str(e),
|
|
255
254
|
)
|
|
256
255
|
tracker.issue(error)
|
|
257
256
|
if stop_on_exception:
|
|
258
|
-
raise error
|
|
257
|
+
raise error from e
|
|
259
258
|
yield error
|
|
260
259
|
|
|
261
260
|
yield _END_OF_CLASS
|
|
@@ -14,14 +14,18 @@ from cognite.client.data_classes.data_modeling.views import SingleEdgeConnection
|
|
|
14
14
|
from cognite.client.exceptions import CogniteAPIError
|
|
15
15
|
from pydantic import BaseModel, ValidationInfo, create_model, field_validator
|
|
16
16
|
|
|
17
|
-
import cognite.neat.issues.errors.resources
|
|
18
17
|
from cognite.neat.graph._tracking import LogTracker, Tracker
|
|
19
|
-
from cognite.neat.graph.stores import NeatGraphStore
|
|
20
18
|
from cognite.neat.issues import IssueList, NeatIssue, NeatIssueList
|
|
21
|
-
from cognite.neat.issues.errors
|
|
22
|
-
|
|
19
|
+
from cognite.neat.issues.errors import (
|
|
20
|
+
ResourceConvertionError,
|
|
21
|
+
ResourceCreationError,
|
|
22
|
+
ResourceDuplicatedError,
|
|
23
|
+
ResourceRetrievalError,
|
|
24
|
+
)
|
|
25
|
+
from cognite.neat.issues.warnings import PropertyTypeNotSupportedWarning
|
|
23
26
|
from cognite.neat.rules.models import DMSRules
|
|
24
27
|
from cognite.neat.rules.models.data_types import _DATA_TYPE_BY_DMS_TYPE, Json
|
|
28
|
+
from cognite.neat.store import NeatGraphStore
|
|
25
29
|
from cognite.neat.utils.auxiliary import create_sha256_hash
|
|
26
30
|
from cognite.neat.utils.upload import UploadResult
|
|
27
31
|
|
|
@@ -69,9 +73,7 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
69
73
|
try:
|
|
70
74
|
data_model = client.data_modeling.data_models.retrieve(data_model_id, inline_views=True).latest_version()
|
|
71
75
|
except Exception as e:
|
|
72
|
-
issues.append(
|
|
73
|
-
ResourceNotFoundError(identifier=repr(data_model_id), resource_type="Data Model", reason=str(e))
|
|
74
|
-
)
|
|
76
|
+
issues.append(ResourceRetrievalError(data_model_id, "data model", str(e)))
|
|
75
77
|
|
|
76
78
|
return cls(graph_store, data_model, instance_space, {}, issues)
|
|
77
79
|
|
|
@@ -83,8 +85,9 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
83
85
|
data_model = rules.as_schema().as_read_model()
|
|
84
86
|
except Exception as e:
|
|
85
87
|
issues.append(
|
|
86
|
-
|
|
88
|
+
ResourceConvertionError(
|
|
87
89
|
identifier=rules.metadata.as_identifier(),
|
|
90
|
+
resource_type="DMS Rules",
|
|
88
91
|
target_format="read DMS model",
|
|
89
92
|
reason=str(e),
|
|
90
93
|
)
|
|
@@ -114,10 +117,10 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
114
117
|
try:
|
|
115
118
|
yield self._create_node(identifier, properties, pydantic_cls, view_id)
|
|
116
119
|
except ValueError as e:
|
|
117
|
-
error =
|
|
120
|
+
error = ResourceCreationError(identifier, "node", error=str(e))
|
|
118
121
|
tracker.issue(error)
|
|
119
122
|
if stop_on_exception:
|
|
120
|
-
raise error
|
|
123
|
+
raise error from e
|
|
121
124
|
yield error
|
|
122
125
|
yield from self._create_edges(identifier, properties, edge_by_properties, tracker)
|
|
123
126
|
tracker.finish(repr(view_id))
|
|
@@ -162,9 +165,11 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
162
165
|
data_type = _DATA_TYPE_BY_DMS_TYPE.get(prop.type._type)
|
|
163
166
|
if not data_type:
|
|
164
167
|
issues.append(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
+
PropertyTypeNotSupportedWarning(
|
|
169
|
+
view.as_id(),
|
|
170
|
+
"view",
|
|
171
|
+
prop_name,
|
|
172
|
+
prop.type._type,
|
|
168
173
|
)
|
|
169
174
|
)
|
|
170
175
|
continue
|
|
@@ -251,10 +256,10 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
251
256
|
continue
|
|
252
257
|
edge = edge_by_properties[prop]
|
|
253
258
|
if isinstance(edge, SingleEdgeConnection) and len(values) > 1:
|
|
254
|
-
error =
|
|
259
|
+
error = ResourceDuplicatedError(
|
|
255
260
|
resource_type="edge",
|
|
256
261
|
identifier=identifier,
|
|
257
|
-
|
|
262
|
+
location=f"Multiple values for single edge {edge}. Expected only one.",
|
|
258
263
|
)
|
|
259
264
|
tracker.issue(error)
|
|
260
265
|
yield error
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
"""This is module contains all the Neat Exceptions (Errors) and Warnings as well
|
|
2
|
-
as
|
|
3
|
-
|
|
4
|
-
"""
|
|
2
|
+
as some helper classes to handle them like NeatIssueList"""
|
|
5
3
|
|
|
6
4
|
from ._base import DefaultWarning, IssueList, MultiValueError, NeatError, NeatIssue, NeatIssueList, NeatWarning
|
|
7
5
|
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import warnings
|
|
3
|
+
from abc import ABC
|
|
4
|
+
from collections import UserList
|
|
5
|
+
from collections.abc import Collection, Hashable, Iterable, Sequence
|
|
6
|
+
from dataclasses import dataclass, fields
|
|
7
|
+
from functools import total_ordering
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from types import UnionType
|
|
10
|
+
from typing import Any, ClassVar, Literal, TypeAlias, TypeVar, get_args, get_origin
|
|
11
|
+
from warnings import WarningMessage
|
|
12
|
+
|
|
13
|
+
import pandas as pd
|
|
14
|
+
from cognite.client.data_classes.data_modeling import ContainerId, ViewId
|
|
15
|
+
from pydantic_core import ErrorDetails
|
|
16
|
+
|
|
17
|
+
from cognite.neat.utils.spreadsheet import SpreadsheetRead
|
|
18
|
+
from cognite.neat.utils.text import humanize_collection, to_camel, to_snake
|
|
19
|
+
|
|
20
|
+
if sys.version_info < (3, 11):
|
|
21
|
+
from exceptiongroup import ExceptionGroup
|
|
22
|
+
from typing_extensions import Self
|
|
23
|
+
else:
|
|
24
|
+
from typing import Self
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
__all__ = [
|
|
28
|
+
"NeatIssue",
|
|
29
|
+
"NeatError",
|
|
30
|
+
"NeatWarning",
|
|
31
|
+
"DefaultWarning",
|
|
32
|
+
"NeatIssueList",
|
|
33
|
+
"MultiValueError",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
T_Identifier = TypeVar("T_Identifier", bound=Hashable)
|
|
37
|
+
|
|
38
|
+
T_ReferenceIdentifier = TypeVar("T_ReferenceIdentifier", bound=Hashable)
|
|
39
|
+
|
|
40
|
+
ResourceType: TypeAlias = (
|
|
41
|
+
Literal[
|
|
42
|
+
"view",
|
|
43
|
+
"container",
|
|
44
|
+
"view property",
|
|
45
|
+
"container property",
|
|
46
|
+
"space",
|
|
47
|
+
"class",
|
|
48
|
+
"asset",
|
|
49
|
+
"relationship",
|
|
50
|
+
"data model",
|
|
51
|
+
"edge",
|
|
52
|
+
"node",
|
|
53
|
+
"unknown",
|
|
54
|
+
]
|
|
55
|
+
# String to handle all unknown types in different importers.
|
|
56
|
+
| str
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@total_ordering
|
|
61
|
+
@dataclass(frozen=True)
|
|
62
|
+
class NeatIssue:
|
|
63
|
+
"""This is the base class for all exceptions and warnings (issues) used in Neat."""
|
|
64
|
+
|
|
65
|
+
extra: ClassVar[str | None] = None
|
|
66
|
+
fix: ClassVar[str | None] = None
|
|
67
|
+
|
|
68
|
+
def as_message(self) -> str:
|
|
69
|
+
"""Return a human-readable message for the issue."""
|
|
70
|
+
template = self.__doc__
|
|
71
|
+
if not template:
|
|
72
|
+
return "Missing"
|
|
73
|
+
variables, has_all_optional = self._get_variables()
|
|
74
|
+
|
|
75
|
+
msg = template.format(**variables)
|
|
76
|
+
if self.extra and has_all_optional:
|
|
77
|
+
msg += "\n" + self.extra.format(**variables)
|
|
78
|
+
if self.fix:
|
|
79
|
+
msg += f"\nFix: {self.fix.format(**variables)}"
|
|
80
|
+
name = type(self).__name__
|
|
81
|
+
return f"{name}: {msg}"
|
|
82
|
+
|
|
83
|
+
def _get_variables(self) -> tuple[dict[str, str], bool]:
|
|
84
|
+
variables: dict[str, str] = {}
|
|
85
|
+
has_all_optional = True
|
|
86
|
+
for name, var_ in vars(self).items():
|
|
87
|
+
if var_ is None:
|
|
88
|
+
has_all_optional = False
|
|
89
|
+
elif isinstance(var_, str):
|
|
90
|
+
variables[name] = var_
|
|
91
|
+
elif isinstance(var_, Path):
|
|
92
|
+
variables[name] = var_.as_posix()
|
|
93
|
+
elif isinstance(var_, Collection):
|
|
94
|
+
variables[name] = humanize_collection(var_)
|
|
95
|
+
else:
|
|
96
|
+
variables[name] = repr(var_)
|
|
97
|
+
return variables, has_all_optional
|
|
98
|
+
|
|
99
|
+
def dump(self) -> dict[str, Any]:
|
|
100
|
+
"""Return a dictionary representation of the issue."""
|
|
101
|
+
variables = vars(self)
|
|
102
|
+
output = {to_camel(key): self._dump_value(value) for key, value in variables.items() if value is not None}
|
|
103
|
+
output["NeatIssue"] = type(self).__name__
|
|
104
|
+
return output
|
|
105
|
+
|
|
106
|
+
@classmethod
|
|
107
|
+
def _dump_value(cls, value: Any) -> list | int | bool | float | str | dict:
|
|
108
|
+
if isinstance(value, str | int | bool | float):
|
|
109
|
+
return value
|
|
110
|
+
elif isinstance(value, frozenset):
|
|
111
|
+
return [cls._dump_value(item) for item in value]
|
|
112
|
+
elif isinstance(value, Path):
|
|
113
|
+
return value.as_posix()
|
|
114
|
+
elif isinstance(value, tuple):
|
|
115
|
+
return [cls._dump_value(item) for item in value]
|
|
116
|
+
elif isinstance(value, ViewId | ContainerId):
|
|
117
|
+
return value.dump(camel_case=True, include_type=True)
|
|
118
|
+
raise ValueError(f"Unsupported type: {type(value)}")
|
|
119
|
+
|
|
120
|
+
@classmethod
|
|
121
|
+
def load(cls, data: dict[str, Any]) -> "NeatIssue":
|
|
122
|
+
"""Create an instance of the issue from a dictionary."""
|
|
123
|
+
from cognite.neat.issues.errors import _NEAT_ERRORS_BY_NAME, NeatValueError
|
|
124
|
+
from cognite.neat.issues.warnings import _NEAT_WARNINGS_BY_NAME
|
|
125
|
+
|
|
126
|
+
if "NeatIssue" not in data:
|
|
127
|
+
raise NeatValueError("The data does not contain a NeatIssue key.")
|
|
128
|
+
issue_type = data.pop("NeatIssue")
|
|
129
|
+
args = {to_snake(key): value for key, value in data.items()}
|
|
130
|
+
if issue_type in _NEAT_ERRORS_BY_NAME:
|
|
131
|
+
return cls._load_values(_NEAT_ERRORS_BY_NAME[issue_type], args)
|
|
132
|
+
elif issue_type in _NEAT_WARNINGS_BY_NAME:
|
|
133
|
+
return cls._load_values(_NEAT_WARNINGS_BY_NAME[issue_type], args)
|
|
134
|
+
else:
|
|
135
|
+
raise NeatValueError(f"Unknown issue type: {issue_type}")
|
|
136
|
+
|
|
137
|
+
@classmethod
|
|
138
|
+
def _load_values(cls, neat_issue_cls: "type[NeatIssue]", data: dict[str, Any]) -> "NeatIssue":
|
|
139
|
+
args: dict[str, Any] = {}
|
|
140
|
+
for f in fields(neat_issue_cls):
|
|
141
|
+
if f.name not in data:
|
|
142
|
+
continue
|
|
143
|
+
value = data[f.name]
|
|
144
|
+
args[f.name] = cls._load_value(f.type, value)
|
|
145
|
+
return neat_issue_cls(**args)
|
|
146
|
+
|
|
147
|
+
@classmethod
|
|
148
|
+
def _load_value(cls, type_: type, value: Any) -> Any:
|
|
149
|
+
if isinstance(type_, UnionType) or get_origin(type_) is UnionType:
|
|
150
|
+
args = get_args(type_)
|
|
151
|
+
return cls._load_value(args[0], value)
|
|
152
|
+
elif type_ is frozenset or get_origin(type_) is frozenset:
|
|
153
|
+
subtype = get_args(type_)[0]
|
|
154
|
+
return frozenset(cls._load_value(subtype, item) for item in value)
|
|
155
|
+
elif type_ is Path:
|
|
156
|
+
return Path(value)
|
|
157
|
+
elif type_ is tuple or get_origin(type_) is tuple:
|
|
158
|
+
subtype = get_args(type_)[0]
|
|
159
|
+
return tuple(cls._load_value(subtype, item) for item in value)
|
|
160
|
+
elif type_ is ViewId:
|
|
161
|
+
return ViewId.load(value)
|
|
162
|
+
elif type_ is ContainerId:
|
|
163
|
+
return ContainerId.load(value)
|
|
164
|
+
return value
|
|
165
|
+
|
|
166
|
+
def __lt__(self, other: "NeatIssue") -> bool:
|
|
167
|
+
if not isinstance(other, NeatIssue):
|
|
168
|
+
return NotImplemented
|
|
169
|
+
return (type(self).__name__, self.as_message()) < (type(other).__name__, other.as_message())
|
|
170
|
+
|
|
171
|
+
def __eq__(self, other: object) -> bool:
|
|
172
|
+
if not isinstance(other, NeatIssue):
|
|
173
|
+
return NotImplemented
|
|
174
|
+
return (type(self).__name__, self.as_message()) == (type(other).__name__, other.as_message())
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
@dataclass(frozen=True)
|
|
178
|
+
class NeatError(NeatIssue, Exception):
|
|
179
|
+
"""This is the base class for all exceptions (errors) used in Neat."""
|
|
180
|
+
|
|
181
|
+
@classmethod
|
|
182
|
+
def from_pydantic_errors(cls, errors: list[ErrorDetails], **kwargs) -> "list[NeatError]":
|
|
183
|
+
"""Convert a list of pydantic errors to a list of Error instances.
|
|
184
|
+
|
|
185
|
+
This is intended to be overridden in subclasses to handle specific error types.
|
|
186
|
+
"""
|
|
187
|
+
all_errors: list[NeatError] = []
|
|
188
|
+
read_info_by_sheet = kwargs.get("read_info_by_sheet")
|
|
189
|
+
|
|
190
|
+
for error in errors:
|
|
191
|
+
ctx = error.get("ctx")
|
|
192
|
+
if isinstance(ctx, dict) and isinstance(multi_error := ctx.get("error"), MultiValueError):
|
|
193
|
+
if read_info_by_sheet:
|
|
194
|
+
for caught_error in multi_error.errors:
|
|
195
|
+
cls._adjust_row_numbers(caught_error, read_info_by_sheet) # type: ignore[arg-type]
|
|
196
|
+
all_errors.extend(multi_error.errors) # type: ignore[arg-type]
|
|
197
|
+
elif isinstance(ctx, dict) and isinstance(single_error := ctx.get("error"), NeatError):
|
|
198
|
+
if read_info_by_sheet:
|
|
199
|
+
cls._adjust_row_numbers(single_error, read_info_by_sheet)
|
|
200
|
+
all_errors.append(single_error)
|
|
201
|
+
elif len(error["loc"]) >= 4 and read_info_by_sheet:
|
|
202
|
+
all_errors.append(RowError.from_pydantic_error(error, read_info_by_sheet))
|
|
203
|
+
else:
|
|
204
|
+
all_errors.append(DefaultPydanticError.from_pydantic_error(error))
|
|
205
|
+
return all_errors
|
|
206
|
+
|
|
207
|
+
@staticmethod
|
|
208
|
+
def _adjust_row_numbers(caught_error: "NeatError", read_info_by_sheet: dict[str, SpreadsheetRead]) -> None:
|
|
209
|
+
from cognite.neat.issues.errors._properties import PropertyDefinitionDuplicatedError
|
|
210
|
+
from cognite.neat.issues.errors._resources import ResourceNotDefinedError
|
|
211
|
+
|
|
212
|
+
reader = read_info_by_sheet.get("Properties", SpreadsheetRead())
|
|
213
|
+
|
|
214
|
+
if isinstance(caught_error, PropertyDefinitionDuplicatedError) and caught_error.location_name == "rows":
|
|
215
|
+
adjusted_row_number = (
|
|
216
|
+
tuple(
|
|
217
|
+
reader.adjusted_row_number(row_no) if isinstance(row_no, int) else row_no
|
|
218
|
+
for row_no in caught_error.locations or []
|
|
219
|
+
)
|
|
220
|
+
or None
|
|
221
|
+
)
|
|
222
|
+
# The error is frozen, so we have to use __setattr__ to change the row number
|
|
223
|
+
object.__setattr__(caught_error, "locations", adjusted_row_number)
|
|
224
|
+
elif isinstance(caught_error, RowError):
|
|
225
|
+
# Adjusting the row number to the actual row number in the spreadsheet
|
|
226
|
+
new_row = reader.adjusted_row_number(caught_error.row)
|
|
227
|
+
# The error is frozen, so we have to use __setattr__ to change the row number
|
|
228
|
+
object.__setattr__(caught_error, "row", new_row)
|
|
229
|
+
elif isinstance(caught_error, ResourceNotDefinedError):
|
|
230
|
+
if isinstance(caught_error.row_number, int) and caught_error.sheet_name == "Properties":
|
|
231
|
+
new_row = reader.adjusted_row_number(caught_error.row_number)
|
|
232
|
+
object.__setattr__(caught_error, "row_number", new_row)
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
@dataclass(frozen=True)
|
|
236
|
+
class DefaultPydanticError(NeatError, ValueError):
|
|
237
|
+
"""{type}: {msg} [loc={loc}]"""
|
|
238
|
+
|
|
239
|
+
type: str
|
|
240
|
+
loc: tuple[int | str, ...]
|
|
241
|
+
msg: str
|
|
242
|
+
|
|
243
|
+
@classmethod
|
|
244
|
+
def from_pydantic_error(cls, error: ErrorDetails) -> "DefaultPydanticError":
|
|
245
|
+
return cls(
|
|
246
|
+
type=error["type"],
|
|
247
|
+
loc=error["loc"],
|
|
248
|
+
msg=error["msg"],
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
def as_message(self) -> str:
|
|
252
|
+
if self.loc and len(self.loc) == 1:
|
|
253
|
+
return f"{self.loc[0]} sheet: {self.msg}"
|
|
254
|
+
elif self.loc and len(self.loc) == 2:
|
|
255
|
+
return f"{self.loc[0]} sheet field/column <{self.loc[1]}>: {self.msg}"
|
|
256
|
+
else:
|
|
257
|
+
return self.msg
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
@dataclass(frozen=True)
|
|
261
|
+
class RowError(NeatError, ValueError):
|
|
262
|
+
"""In {sheet_name}, row={row}, column={column}: {msg}. [type={type}, input_value={input}]"""
|
|
263
|
+
|
|
264
|
+
extra = "For further information visit {url}"
|
|
265
|
+
|
|
266
|
+
sheet_name: str
|
|
267
|
+
column: str
|
|
268
|
+
row: int
|
|
269
|
+
type: str
|
|
270
|
+
msg: str
|
|
271
|
+
input: Any
|
|
272
|
+
url: str | None = None
|
|
273
|
+
|
|
274
|
+
@classmethod
|
|
275
|
+
def from_pydantic_error(
|
|
276
|
+
cls,
|
|
277
|
+
error: ErrorDetails,
|
|
278
|
+
read_info_by_sheet: dict[str, SpreadsheetRead] | None = None,
|
|
279
|
+
) -> Self:
|
|
280
|
+
sheet_name, _, row, column, *__ = error["loc"]
|
|
281
|
+
reader = (read_info_by_sheet or {}).get(str(sheet_name), SpreadsheetRead())
|
|
282
|
+
return cls(
|
|
283
|
+
sheet_name=str(sheet_name),
|
|
284
|
+
column=str(column),
|
|
285
|
+
row=reader.adjusted_row_number(int(row)),
|
|
286
|
+
type=error["type"],
|
|
287
|
+
msg=error["msg"],
|
|
288
|
+
input=error.get("input"),
|
|
289
|
+
url=str(url) if (url := error.get("url")) else None,
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
def as_message(self) -> str:
|
|
293
|
+
input_str = str(self.input) if self.input is not None else ""
|
|
294
|
+
input_str = input_str[:50] + "..." if len(input_str) > 50 else input_str
|
|
295
|
+
output = (
|
|
296
|
+
f"In {self.sheet_name}, row={self.row}, column={self.column}: {self.msg}. "
|
|
297
|
+
f"[type={self.type}, input_value={input_str}]"
|
|
298
|
+
)
|
|
299
|
+
if self.url:
|
|
300
|
+
output += f" For further information visit {self.url}"
|
|
301
|
+
return output
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
@dataclass(frozen=True)
|
|
305
|
+
class NeatWarning(NeatIssue, UserWarning):
|
|
306
|
+
"""This is the base class for all warnings used in Neat."""
|
|
307
|
+
|
|
308
|
+
@classmethod
|
|
309
|
+
def from_warning(cls, warning: WarningMessage) -> "NeatWarning":
|
|
310
|
+
"""Create a NeatWarning from a WarningMessage."""
|
|
311
|
+
return DefaultWarning.from_warning_message(warning)
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
@dataclass(frozen=True)
|
|
315
|
+
class DefaultWarning(NeatWarning):
|
|
316
|
+
"""{category}: {warning}"""
|
|
317
|
+
|
|
318
|
+
extra = "Source: {source}"
|
|
319
|
+
|
|
320
|
+
warning: str
|
|
321
|
+
category: str
|
|
322
|
+
source: str | None = None
|
|
323
|
+
|
|
324
|
+
@classmethod
|
|
325
|
+
def from_warning_message(cls, warning: WarningMessage) -> NeatWarning:
|
|
326
|
+
if isinstance(warning.message, NeatWarning):
|
|
327
|
+
return warning.message
|
|
328
|
+
|
|
329
|
+
return cls(
|
|
330
|
+
warning=str(warning.message),
|
|
331
|
+
category=warning.category.__name__,
|
|
332
|
+
source=warning.source,
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
def as_message(self) -> str:
|
|
336
|
+
return str(self.warning)
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
T_NeatIssue = TypeVar("T_NeatIssue", bound=NeatIssue)
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
class NeatIssueList(UserList[T_NeatIssue], ABC):
|
|
343
|
+
"""This is a generic list of NeatIssues."""
|
|
344
|
+
|
|
345
|
+
def __init__(self, issues: Sequence[T_NeatIssue] | None = None, title: str | None = None):
|
|
346
|
+
super().__init__(issues or [])
|
|
347
|
+
self.title = title
|
|
348
|
+
|
|
349
|
+
@property
|
|
350
|
+
def errors(self) -> Self:
|
|
351
|
+
"""Return all the errors in this list."""
|
|
352
|
+
return type(self)([issue for issue in self if isinstance(issue, NeatError)]) # type: ignore[misc]
|
|
353
|
+
|
|
354
|
+
@property
|
|
355
|
+
def has_errors(self) -> bool:
|
|
356
|
+
"""Return True if this list contains any errors."""
|
|
357
|
+
return any(isinstance(issue, NeatError) for issue in self)
|
|
358
|
+
|
|
359
|
+
@property
|
|
360
|
+
def warnings(self) -> Self:
|
|
361
|
+
"""Return all the warnings in this list."""
|
|
362
|
+
return type(self)([issue for issue in self if isinstance(issue, NeatWarning)]) # type: ignore[misc]
|
|
363
|
+
|
|
364
|
+
def as_errors(self) -> ExceptionGroup:
|
|
365
|
+
"""Return an ExceptionGroup with all the errors in this list."""
|
|
366
|
+
return ExceptionGroup(
|
|
367
|
+
"Operation failed",
|
|
368
|
+
[issue for issue in self if isinstance(issue, NeatError)],
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
def trigger_warnings(self) -> None:
|
|
372
|
+
"""Trigger all warnings in this list."""
|
|
373
|
+
for warning in [issue for issue in self if isinstance(issue, NeatWarning)]:
|
|
374
|
+
warnings.warn(warning, stacklevel=2)
|
|
375
|
+
|
|
376
|
+
def to_pandas(self) -> pd.DataFrame:
|
|
377
|
+
"""Return a pandas DataFrame representation of this list."""
|
|
378
|
+
return pd.DataFrame([issue.dump() for issue in self])
|
|
379
|
+
|
|
380
|
+
def _repr_html_(self) -> str | None:
|
|
381
|
+
return self.to_pandas()._repr_html_() # type: ignore[operator]
|
|
382
|
+
|
|
383
|
+
def as_exception(self) -> "MultiValueError":
|
|
384
|
+
"""Return a MultiValueError with all the errors in this list."""
|
|
385
|
+
return MultiValueError(self.errors)
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
class MultiValueError(ValueError):
|
|
389
|
+
"""This is a container for multiple errors.
|
|
390
|
+
|
|
391
|
+
It is used in the pydantic field_validator/model_validator to collect multiple errors, which
|
|
392
|
+
can then be caught in a try-except block and returned as an IssueList.
|
|
393
|
+
|
|
394
|
+
"""
|
|
395
|
+
|
|
396
|
+
def __init__(self, errors: Sequence[NeatIssue]):
|
|
397
|
+
self.errors = list(errors)
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
class IssueList(NeatIssueList[NeatIssue]):
|
|
401
|
+
"""This is a list of NeatIssues."""
|
|
402
|
+
|
|
403
|
+
...
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
T_Cls = TypeVar("T_Cls")
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
def _get_subclasses(cls_: type[T_Cls], include_base: bool = False) -> Iterable[type[T_Cls]]:
|
|
410
|
+
"""Get all subclasses of a class."""
|
|
411
|
+
if include_base:
|
|
412
|
+
yield cls_
|
|
413
|
+
for s in cls_.__subclasses__():
|
|
414
|
+
yield s
|
|
415
|
+
yield from _get_subclasses(s, False)
|