cognite-neat 0.87.6__py3-none-any.whl → 0.88.1__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.
Potentially problematic release.
This version of cognite-neat might be problematic. Click here for more details.
- cognite/neat/_version.py +1 -1
- cognite/neat/app/api/data_classes/rest.py +0 -19
- cognite/neat/app/api/explorer.py +6 -4
- cognite/neat/app/api/routers/configuration.py +1 -1
- cognite/neat/app/api/routers/crud.py +11 -21
- cognite/neat/app/api/routers/workflows.py +24 -94
- cognite/neat/app/ui/neat-app/build/asset-manifest.json +7 -7
- cognite/neat/app/ui/neat-app/build/index.html +1 -1
- cognite/neat/app/ui/neat-app/build/static/css/{main.38a62222.css → main.72e3d92e.css} +2 -2
- cognite/neat/app/ui/neat-app/build/static/css/main.72e3d92e.css.map +1 -0
- cognite/neat/app/ui/neat-app/build/static/js/main.5a52cf09.js +3 -0
- cognite/neat/app/ui/neat-app/build/static/js/{main.ec7f72e2.js.LICENSE.txt → main.5a52cf09.js.LICENSE.txt} +0 -9
- cognite/neat/app/ui/neat-app/build/static/js/main.5a52cf09.js.map +1 -0
- cognite/neat/config.py +44 -27
- cognite/neat/exceptions.py +6 -0
- cognite/neat/graph/extractors/_classic_cdf/_assets.py +21 -73
- cognite/neat/graph/extractors/_classic_cdf/_base.py +102 -0
- cognite/neat/graph/extractors/_classic_cdf/_events.py +46 -42
- cognite/neat/graph/extractors/_classic_cdf/_files.py +41 -45
- cognite/neat/graph/extractors/_classic_cdf/_labels.py +75 -52
- cognite/neat/graph/extractors/_classic_cdf/_relationships.py +49 -27
- cognite/neat/graph/extractors/_classic_cdf/_sequences.py +47 -50
- cognite/neat/graph/extractors/_classic_cdf/_timeseries.py +47 -49
- cognite/neat/graph/queries/_base.py +22 -29
- cognite/neat/graph/queries/_shared.py +1 -1
- cognite/neat/graph/stores/_base.py +24 -11
- cognite/neat/graph/transformers/_rdfpath.py +3 -2
- cognite/neat/issues.py +8 -0
- cognite/neat/rules/exporters/_rules2ontology.py +28 -20
- cognite/neat/rules/exporters/_validation.py +15 -21
- cognite/neat/rules/importers/_inference2rules.py +31 -35
- cognite/neat/rules/importers/_owl2rules/_owl2metadata.py +3 -7
- cognite/neat/rules/importers/_spreadsheet2rules.py +30 -27
- cognite/neat/rules/issues/dms.py +20 -0
- cognite/neat/rules/issues/importing.py +15 -0
- cognite/neat/rules/issues/ontology.py +298 -0
- cognite/neat/rules/issues/spreadsheet.py +48 -0
- cognite/neat/rules/issues/tables.py +72 -0
- cognite/neat/rules/models/_rdfpath.py +4 -4
- cognite/neat/rules/models/_types/_field.py +9 -19
- cognite/neat/rules/models/information/_rules.py +5 -4
- cognite/neat/utils/rdf_.py +17 -9
- cognite/neat/utils/regex_patterns.py +52 -0
- cognite/neat/workflows/steps/data_contracts.py +17 -43
- cognite/neat/workflows/steps/lib/current/graph_extractor.py +28 -24
- cognite/neat/workflows/steps/lib/current/graph_loader.py +4 -21
- cognite/neat/workflows/steps/lib/current/graph_store.py +18 -134
- cognite/neat/workflows/steps_registry.py +5 -7
- {cognite_neat-0.87.6.dist-info → cognite_neat-0.88.1.dist-info}/METADATA +2 -6
- cognite_neat-0.88.1.dist-info/RECORD +209 -0
- cognite/neat/app/api/routers/core.py +0 -91
- cognite/neat/app/api/routers/data_exploration.py +0 -336
- cognite/neat/app/api/routers/rules.py +0 -203
- cognite/neat/app/ui/neat-app/build/static/css/main.38a62222.css.map +0 -1
- cognite/neat/app/ui/neat-app/build/static/js/main.ec7f72e2.js +0 -3
- cognite/neat/app/ui/neat-app/build/static/js/main.ec7f72e2.js.map +0 -1
- cognite/neat/graph/stores/_oxrdflib.py +0 -247
- cognite/neat/legacy/__init__.py +0 -0
- cognite/neat/legacy/graph/__init__.py +0 -3
- cognite/neat/legacy/graph/examples/Knowledge-Graph-Nordic44-dirty.xml +0 -20182
- cognite/neat/legacy/graph/examples/Knowledge-Graph-Nordic44.xml +0 -20163
- cognite/neat/legacy/graph/examples/__init__.py +0 -10
- cognite/neat/legacy/graph/examples/skos-capturing-sheet-wind-topics.xlsx +0 -0
- cognite/neat/legacy/graph/exceptions.py +0 -90
- cognite/neat/legacy/graph/extractors/__init__.py +0 -6
- cognite/neat/legacy/graph/extractors/_base.py +0 -14
- cognite/neat/legacy/graph/extractors/_dexpi.py +0 -44
- cognite/neat/legacy/graph/extractors/_graph_capturing_sheet.py +0 -403
- cognite/neat/legacy/graph/extractors/_mock_graph_generator.py +0 -361
- cognite/neat/legacy/graph/loaders/__init__.py +0 -23
- cognite/neat/legacy/graph/loaders/_asset_loader.py +0 -511
- cognite/neat/legacy/graph/loaders/_base.py +0 -67
- cognite/neat/legacy/graph/loaders/_exceptions.py +0 -85
- cognite/neat/legacy/graph/loaders/core/__init__.py +0 -0
- cognite/neat/legacy/graph/loaders/core/labels.py +0 -58
- cognite/neat/legacy/graph/loaders/core/models.py +0 -136
- cognite/neat/legacy/graph/loaders/core/rdf_to_assets.py +0 -1046
- cognite/neat/legacy/graph/loaders/core/rdf_to_relationships.py +0 -559
- cognite/neat/legacy/graph/loaders/rdf_to_dms.py +0 -309
- cognite/neat/legacy/graph/loaders/validator.py +0 -87
- cognite/neat/legacy/graph/models.py +0 -6
- cognite/neat/legacy/graph/stores/__init__.py +0 -13
- cognite/neat/legacy/graph/stores/_base.py +0 -400
- cognite/neat/legacy/graph/stores/_graphdb_store.py +0 -52
- cognite/neat/legacy/graph/stores/_memory_store.py +0 -43
- cognite/neat/legacy/graph/stores/_oxigraph_store.py +0 -151
- cognite/neat/legacy/graph/stores/_oxrdflib.py +0 -247
- cognite/neat/legacy/graph/stores/_rdf_to_graph.py +0 -42
- cognite/neat/legacy/graph/transformations/__init__.py +0 -0
- cognite/neat/legacy/graph/transformations/entity_matcher.py +0 -101
- cognite/neat/legacy/graph/transformations/query_generator/__init__.py +0 -3
- cognite/neat/legacy/graph/transformations/query_generator/sparql.py +0 -575
- cognite/neat/legacy/graph/transformations/transformer.py +0 -322
- cognite/neat/legacy/rules/__init__.py +0 -0
- cognite/neat/legacy/rules/analysis.py +0 -231
- cognite/neat/legacy/rules/examples/Rules-Nordic44-to-graphql.xlsx +0 -0
- cognite/neat/legacy/rules/examples/Rules-Nordic44.xlsx +0 -0
- cognite/neat/legacy/rules/examples/__init__.py +0 -18
- cognite/neat/legacy/rules/examples/power-grid-containers.yaml +0 -124
- cognite/neat/legacy/rules/examples/power-grid-example.xlsx +0 -0
- cognite/neat/legacy/rules/examples/power-grid-model.yaml +0 -224
- cognite/neat/legacy/rules/examples/rules-template.xlsx +0 -0
- cognite/neat/legacy/rules/examples/sheet2cdf-transformation-rules.xlsx +0 -0
- cognite/neat/legacy/rules/examples/skos-rules.xlsx +0 -0
- cognite/neat/legacy/rules/examples/source-to-solution-mapping-rules.xlsx +0 -0
- cognite/neat/legacy/rules/examples/wind-energy.owl +0 -1511
- cognite/neat/legacy/rules/exceptions.py +0 -2972
- cognite/neat/legacy/rules/exporters/__init__.py +0 -20
- cognite/neat/legacy/rules/exporters/_base.py +0 -45
- cognite/neat/legacy/rules/exporters/_core/__init__.py +0 -5
- cognite/neat/legacy/rules/exporters/_core/rules2labels.py +0 -24
- cognite/neat/legacy/rules/exporters/_rules2dms.py +0 -885
- cognite/neat/legacy/rules/exporters/_rules2excel.py +0 -213
- cognite/neat/legacy/rules/exporters/_rules2graphql.py +0 -183
- cognite/neat/legacy/rules/exporters/_rules2ontology.py +0 -524
- cognite/neat/legacy/rules/exporters/_rules2pydantic_models.py +0 -748
- cognite/neat/legacy/rules/exporters/_rules2rules.py +0 -105
- cognite/neat/legacy/rules/exporters/_rules2triples.py +0 -38
- cognite/neat/legacy/rules/exporters/_validation.py +0 -146
- cognite/neat/legacy/rules/importers/__init__.py +0 -22
- cognite/neat/legacy/rules/importers/_base.py +0 -66
- cognite/neat/legacy/rules/importers/_dict2rules.py +0 -158
- cognite/neat/legacy/rules/importers/_dms2rules.py +0 -194
- cognite/neat/legacy/rules/importers/_graph2rules.py +0 -308
- cognite/neat/legacy/rules/importers/_json2rules.py +0 -39
- cognite/neat/legacy/rules/importers/_owl2rules/__init__.py +0 -3
- cognite/neat/legacy/rules/importers/_owl2rules/_owl2classes.py +0 -239
- cognite/neat/legacy/rules/importers/_owl2rules/_owl2metadata.py +0 -260
- cognite/neat/legacy/rules/importers/_owl2rules/_owl2properties.py +0 -217
- cognite/neat/legacy/rules/importers/_owl2rules/_owl2rules.py +0 -290
- cognite/neat/legacy/rules/importers/_spreadsheet2rules.py +0 -45
- cognite/neat/legacy/rules/importers/_xsd2rules.py +0 -20
- cognite/neat/legacy/rules/importers/_yaml2rules.py +0 -39
- cognite/neat/legacy/rules/models/__init__.py +0 -5
- cognite/neat/legacy/rules/models/_base.py +0 -151
- cognite/neat/legacy/rules/models/raw_rules.py +0 -316
- cognite/neat/legacy/rules/models/rdfpath.py +0 -237
- cognite/neat/legacy/rules/models/rules.py +0 -1289
- cognite/neat/legacy/rules/models/tables.py +0 -9
- cognite/neat/legacy/rules/models/value_types.py +0 -118
- cognite/neat/legacy/workflows/examples/Export_DMS/workflow.yaml +0 -89
- cognite/neat/legacy/workflows/examples/Export_Rules_to_Ontology/workflow.yaml +0 -152
- cognite/neat/legacy/workflows/examples/Extract_DEXPI_Graph_and_Export_Rules/workflow.yaml +0 -139
- cognite/neat/legacy/workflows/examples/Extract_RDF_Graph_and_Generate_Assets/workflow.yaml +0 -270
- cognite/neat/legacy/workflows/examples/Import_DMS/workflow.yaml +0 -65
- cognite/neat/legacy/workflows/examples/Ontology_to_Data_Model/workflow.yaml +0 -116
- cognite/neat/legacy/workflows/examples/Validate_Rules/workflow.yaml +0 -67
- cognite/neat/legacy/workflows/examples/Validate_Solution_Model/workflow.yaml +0 -64
- cognite/neat/legacy/workflows/examples/Visualize_Data_Model_Using_Mock_Graph/workflow.yaml +0 -95
- cognite/neat/legacy/workflows/examples/Visualize_Semantic_Data_Model/workflow.yaml +0 -111
- cognite/neat/rules/exceptions.py +0 -2972
- cognite/neat/rules/models/_types/_base.py +0 -16
- cognite/neat/workflows/examples/Export_Rules_to_Ontology/workflow.yaml +0 -152
- cognite/neat/workflows/examples/Extract_DEXPI_Graph_and_Export_Rules/workflow.yaml +0 -139
- cognite/neat/workflows/examples/Extract_RDF_Graph_and_Generate_Assets/workflow.yaml +0 -270
- cognite/neat/workflows/examples/Ontology_to_Data_Model/workflow.yaml +0 -116
- cognite/neat/workflows/migration/__init__.py +0 -0
- cognite/neat/workflows/migration/steps.py +0 -91
- cognite/neat/workflows/migration/wf_manifests.py +0 -33
- cognite/neat/workflows/steps/lib/legacy/__init__.py +0 -7
- cognite/neat/workflows/steps/lib/legacy/graph_contextualization.py +0 -82
- cognite/neat/workflows/steps/lib/legacy/graph_extractor.py +0 -746
- cognite/neat/workflows/steps/lib/legacy/graph_loader.py +0 -606
- cognite/neat/workflows/steps/lib/legacy/graph_store.py +0 -307
- cognite/neat/workflows/steps/lib/legacy/graph_transformer.py +0 -58
- cognite/neat/workflows/steps/lib/legacy/rules_exporter.py +0 -511
- cognite/neat/workflows/steps/lib/legacy/rules_importer.py +0 -612
- cognite_neat-0.87.6.dist-info/RECORD +0 -319
- {cognite_neat-0.87.6.dist-info → cognite_neat-0.88.1.dist-info}/LICENSE +0 -0
- {cognite_neat-0.87.6.dist-info → cognite_neat-0.88.1.dist-info}/WHEEL +0 -0
- {cognite_neat-0.87.6.dist-info → cognite_neat-0.88.1.dist-info}/entry_points.txt +0 -0
|
@@ -1,511 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
import sys
|
|
3
|
-
from collections import defaultdict
|
|
4
|
-
from collections.abc import Iterable
|
|
5
|
-
from dataclasses import dataclass, fields
|
|
6
|
-
from datetime import datetime
|
|
7
|
-
from itertools import groupby
|
|
8
|
-
from typing import Any, Literal, overload
|
|
9
|
-
|
|
10
|
-
from cognite.client import CogniteClient
|
|
11
|
-
from cognite.client.data_classes import AssetWrite, LabelDefinitionWrite, RelationshipWrite, RelationshipWriteList
|
|
12
|
-
from pydantic_core import ErrorDetails
|
|
13
|
-
from rdflib.query import ResultRow
|
|
14
|
-
|
|
15
|
-
from cognite.neat.legacy.graph.stores import NeatGraphStoreBase
|
|
16
|
-
from cognite.neat.legacy.rules.models import Rules
|
|
17
|
-
from cognite.neat.legacy.rules.models.rules import Property
|
|
18
|
-
from cognite.neat.utils.rdf_ import remove_namespace_from_uri
|
|
19
|
-
from cognite.neat.utils.time_ import epoch_now_ms
|
|
20
|
-
|
|
21
|
-
from ._base import CogniteLoader
|
|
22
|
-
|
|
23
|
-
if sys.version_info >= (3, 11):
|
|
24
|
-
from datetime import UTC
|
|
25
|
-
else:
|
|
26
|
-
from datetime import timezone
|
|
27
|
-
|
|
28
|
-
UTC = timezone.utc
|
|
29
|
-
|
|
30
|
-
METADATA_VALUE_MAX_LENGTH = 5120
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
@dataclass(frozen=True)
|
|
34
|
-
class AssetLoaderMetadataKeys:
|
|
35
|
-
"""Class holding mapping between NEAT metadata key names and their desired names
|
|
36
|
-
in CDF Asset metadata
|
|
37
|
-
|
|
38
|
-
Args:
|
|
39
|
-
start_time: Start time key name
|
|
40
|
-
end_time: End time key name
|
|
41
|
-
update_time: Update time key name
|
|
42
|
-
resurrection_time: Resurrection time key name
|
|
43
|
-
identifier: Identifier key name
|
|
44
|
-
active: Active key name
|
|
45
|
-
type: Type key name
|
|
46
|
-
"""
|
|
47
|
-
|
|
48
|
-
start_time: str = "start_time"
|
|
49
|
-
end_time: str = "end_time"
|
|
50
|
-
update_time: str = "update_time"
|
|
51
|
-
resurrection_time: str = "resurrection_time"
|
|
52
|
-
identifier: str = "identifier"
|
|
53
|
-
active: str = "active"
|
|
54
|
-
type: str = "type"
|
|
55
|
-
|
|
56
|
-
def as_aliases(self) -> dict[str, str]:
|
|
57
|
-
return {str(field.default): getattr(self, field.name) for field in fields(self)}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
AssetResource = AssetWrite | RelationshipWrite | LabelDefinitionWrite
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
class AssetLoader(CogniteLoader[AssetResource]):
|
|
64
|
-
"""The Asset Loader is used to load a triple store into the CDF core Asset Hierarchy model.
|
|
65
|
-
|
|
66
|
-
Args:
|
|
67
|
-
rules: The transformation rules to use
|
|
68
|
-
graph_store: The graph store to load from
|
|
69
|
-
data_set_id: The data set id to load into
|
|
70
|
-
label_data_set_id: The data set id to load labels into. If not set, the same as data_set_id will be used.
|
|
71
|
-
use_orphanage: Whether to use an orphanage for assets without a parent
|
|
72
|
-
use_labels: Whether to use labels attached to the assets and relationships.
|
|
73
|
-
asset_external_id_prefix: Prefix to add to all external ids
|
|
74
|
-
default_metadata_value: Default metadata value to use for assets without a value. If set to None,
|
|
75
|
-
the metadata key will be omitted. Setting this to an empty string will set the metadata key to an empty
|
|
76
|
-
string, thus ensuring that all assets have the metadata keys.
|
|
77
|
-
metadata_keys: Metadata key names to use
|
|
78
|
-
always_store_in_metadata: Whether to store all properties in metadata. This will be the same as setting
|
|
79
|
-
resource_type_property to metadata for all properties. For example, if you have the property `Terminal.name`
|
|
80
|
-
set with resource_type_property = ["name"], then the property will be stored in metadata as
|
|
81
|
-
`Terminal.name=<Value>`. This also includes properties that are relationships.
|
|
82
|
-
"""
|
|
83
|
-
|
|
84
|
-
# This is guaranteed ot be in the data
|
|
85
|
-
_identifier: str = "identifier"
|
|
86
|
-
# This label is added to all assets if use_labels is True
|
|
87
|
-
_non_historic_label: str = "non-historic"
|
|
88
|
-
|
|
89
|
-
def __init__(
|
|
90
|
-
self,
|
|
91
|
-
rules: Rules,
|
|
92
|
-
graph_store: NeatGraphStoreBase,
|
|
93
|
-
data_set_id: int,
|
|
94
|
-
label_data_set_id: int | None = None,
|
|
95
|
-
use_orphanage: bool = True,
|
|
96
|
-
use_labels: bool = True,
|
|
97
|
-
asset_external_id_prefix: str | None = None,
|
|
98
|
-
default_metadata_value: str | None = "",
|
|
99
|
-
metadata_keys: AssetLoaderMetadataKeys | None = None,
|
|
100
|
-
always_store_in_metadata: bool = False,
|
|
101
|
-
):
|
|
102
|
-
super().__init__(rules, graph_store)
|
|
103
|
-
self._data_set_id = data_set_id
|
|
104
|
-
self._label_data_set_id = label_data_set_id or data_set_id
|
|
105
|
-
self._use_labels = use_labels
|
|
106
|
-
self._use_orphanage = use_orphanage
|
|
107
|
-
self._orphanage_external_id = (
|
|
108
|
-
f"{asset_external_id_prefix or ''}orphanage-{data_set_id}" if use_orphanage else None
|
|
109
|
-
)
|
|
110
|
-
self._asset_external_id_prefix = asset_external_id_prefix
|
|
111
|
-
self._default_metadata_value = default_metadata_value
|
|
112
|
-
self._metadata_keys = metadata_keys or AssetLoaderMetadataKeys()
|
|
113
|
-
# This is used in a hot loop, so we cache it
|
|
114
|
-
self._metadata_key_aliases = self._metadata_keys.as_aliases()
|
|
115
|
-
self._always_store_in_metadata = always_store_in_metadata
|
|
116
|
-
|
|
117
|
-
# State:
|
|
118
|
-
self._loaded_assets: set[str] = set()
|
|
119
|
-
self._loaded_labels: set[str] = set()
|
|
120
|
-
|
|
121
|
-
@overload
|
|
122
|
-
def load(self, stop_on_exception: Literal[True]) -> Iterable[AssetResource]: ...
|
|
123
|
-
|
|
124
|
-
@overload
|
|
125
|
-
def load(self, stop_on_exception: Literal[False] = False) -> Iterable[AssetResource | ErrorDetails]: ...
|
|
126
|
-
|
|
127
|
-
def load(self, stop_on_exception: bool = False) -> Iterable[AssetResource | ErrorDetails]:
|
|
128
|
-
if self.rules.metadata.namespace is None:
|
|
129
|
-
raise ValueError("Namespace must be provided in transformation rules!")
|
|
130
|
-
namespace = self.rules.metadata.namespace
|
|
131
|
-
|
|
132
|
-
properties_by_class_name: dict[str, list[Property]] = defaultdict(list)
|
|
133
|
-
for prop in self.rules.properties.values():
|
|
134
|
-
properties_by_class_name[prop.class_id].append(prop)
|
|
135
|
-
|
|
136
|
-
if self._use_labels:
|
|
137
|
-
self._loaded_labels.add(self._non_historic_label)
|
|
138
|
-
yield LabelDefinitionWrite(
|
|
139
|
-
external_id=self._non_historic_label, name=self._non_historic_label, data_set_id=self._label_data_set_id
|
|
140
|
-
)
|
|
141
|
-
|
|
142
|
-
# Todo Extend rules to sort topological sorting to ensure that parents are loaded before children
|
|
143
|
-
counter = 0
|
|
144
|
-
for class_name in self.rules.classes.keys():
|
|
145
|
-
if self._use_labels:
|
|
146
|
-
self._loaded_labels.add(class_name)
|
|
147
|
-
yield LabelDefinitionWrite(external_id=class_name, name=class_name, data_set_id=self._label_data_set_id)
|
|
148
|
-
|
|
149
|
-
class_uri = namespace[class_name]
|
|
150
|
-
logging.debug(f"Processing class <{class_uri}>.")
|
|
151
|
-
|
|
152
|
-
try:
|
|
153
|
-
result = self.graph_store.queries.list_instances_of_type(class_uri)
|
|
154
|
-
except Exception as e:
|
|
155
|
-
logging.error(f"Error while querying for instances of class <{class_uri}> into cache. Reason: {e}")
|
|
156
|
-
if stop_on_exception:
|
|
157
|
-
raise e
|
|
158
|
-
yield ErrorDetails(
|
|
159
|
-
input={"class_uri": class_uri},
|
|
160
|
-
loc=("AssetLoader", "load"),
|
|
161
|
-
msg=f"Error while querying instances of class <{class_uri}> into cache. Reason: {e}",
|
|
162
|
-
type=f"Exception of type {type(e).__name__} occurred when processing instance of {class_name}",
|
|
163
|
-
)
|
|
164
|
-
continue
|
|
165
|
-
|
|
166
|
-
logging.debug(f"Class <{class_name}> has {len(result)} instances")
|
|
167
|
-
|
|
168
|
-
for instance_uri, properties_values in groupby(result, lambda x: x[0]):
|
|
169
|
-
instance_id = remove_namespace_from_uri(instance_uri)
|
|
170
|
-
values_by_property = self._prepare_instance_data(instance_id, properties_values)
|
|
171
|
-
try:
|
|
172
|
-
asset = self._load_asset(
|
|
173
|
-
properties_by_class_name[class_name],
|
|
174
|
-
values_by_property,
|
|
175
|
-
instance_id,
|
|
176
|
-
class_name,
|
|
177
|
-
)
|
|
178
|
-
except Exception as e:
|
|
179
|
-
logging.error(f"Error while loading asset from instance <{instance_id}>. Reason: {e}")
|
|
180
|
-
if stop_on_exception:
|
|
181
|
-
raise e
|
|
182
|
-
yield ErrorDetails(
|
|
183
|
-
input={"instance_id": instance_id},
|
|
184
|
-
loc=("AssetLoader", "load"),
|
|
185
|
-
msg=f"Error while loading asset from <{instance_id}>. Reason: {e}",
|
|
186
|
-
type=f"Exception of type {type(e).__name__} occurred when processing instance of {class_name}",
|
|
187
|
-
)
|
|
188
|
-
continue
|
|
189
|
-
else:
|
|
190
|
-
# We know that external_id is always set
|
|
191
|
-
self._loaded_assets.add(asset.external_id) # type: ignore[arg-type]
|
|
192
|
-
yield asset
|
|
193
|
-
|
|
194
|
-
try:
|
|
195
|
-
relationships = self._load_relationships(
|
|
196
|
-
properties_by_class_name[class_name],
|
|
197
|
-
values_by_property,
|
|
198
|
-
remove_namespace_from_uri(instance_id),
|
|
199
|
-
class_name,
|
|
200
|
-
)
|
|
201
|
-
except Exception as e:
|
|
202
|
-
logging.error(f"Error while loading relationships from instance <{instance_id}>. Reason: {e}")
|
|
203
|
-
if stop_on_exception:
|
|
204
|
-
raise e
|
|
205
|
-
yield ErrorDetails(
|
|
206
|
-
input={"instance_id": instance_id},
|
|
207
|
-
loc=("AssetLoader", "load"),
|
|
208
|
-
msg=f"Error while loading relationships from <{instance_id}>. Reason: {e}",
|
|
209
|
-
type=f"Exception of type {type(e).__name__} occurred when processing instance of {class_name}",
|
|
210
|
-
)
|
|
211
|
-
continue
|
|
212
|
-
else:
|
|
213
|
-
for relationship in relationships:
|
|
214
|
-
for label in relationship.labels or []:
|
|
215
|
-
if label.external_id and label.external_id not in self._loaded_labels:
|
|
216
|
-
self._loaded_labels.add(label.external_id)
|
|
217
|
-
yield LabelDefinitionWrite(
|
|
218
|
-
name=label.external_id,
|
|
219
|
-
external_id=label.external_id,
|
|
220
|
-
data_set_id=self._label_data_set_id,
|
|
221
|
-
)
|
|
222
|
-
|
|
223
|
-
yield from relationships
|
|
224
|
-
|
|
225
|
-
counter += 1
|
|
226
|
-
# log every 10000 assets
|
|
227
|
-
if counter % 10_000 == 0:
|
|
228
|
-
logging.info(" Next 10,000 Assets processed")
|
|
229
|
-
|
|
230
|
-
logging.debug(f"Class <{class_name}> processed")
|
|
231
|
-
|
|
232
|
-
# Todo Move orphanage to the beginning to ensure that it is loaded first.
|
|
233
|
-
if self._use_orphanage and self._orphanage_external_id not in self._loaded_assets:
|
|
234
|
-
logging.warning(f"Orphanage with external id {self._orphanage_external_id} not found in asset hierarchy!")
|
|
235
|
-
logging.warning(f"Adding default orphanage with external id {self._orphanage_external_id}")
|
|
236
|
-
now = str(datetime.now(UTC))
|
|
237
|
-
if self._use_labels:
|
|
238
|
-
yield LabelDefinitionWrite(
|
|
239
|
-
external_id="Orphanage", name="Orphanage", data_set_id=self._label_data_set_id
|
|
240
|
-
)
|
|
241
|
-
|
|
242
|
-
yield AssetWrite(
|
|
243
|
-
external_id=self._orphanage_external_id,
|
|
244
|
-
name="Orphanage",
|
|
245
|
-
data_set_id=self._data_set_id,
|
|
246
|
-
parent_external_id=None,
|
|
247
|
-
description="Used to store all assets which parent does not exist",
|
|
248
|
-
labels=["Orphanage", self._non_historic_label] if self._use_labels else None,
|
|
249
|
-
metadata={
|
|
250
|
-
self._metadata_keys.type: "Orphanage",
|
|
251
|
-
"cdfResourceType": "Asset",
|
|
252
|
-
self._metadata_keys.start_time: now,
|
|
253
|
-
self._metadata_keys.update_time: now,
|
|
254
|
-
self._metadata_keys.identifier: "orphanage",
|
|
255
|
-
self._metadata_keys.active: "true",
|
|
256
|
-
},
|
|
257
|
-
)
|
|
258
|
-
|
|
259
|
-
@overload
|
|
260
|
-
def load_assets(self, stop_on_exception: Literal[True]) -> Iterable[AssetWrite]: ...
|
|
261
|
-
|
|
262
|
-
@overload
|
|
263
|
-
def load_assets(self, stop_on_exception: Literal[False] = False) -> Iterable[AssetWrite | ErrorDetails]: ...
|
|
264
|
-
|
|
265
|
-
def load_assets(self, stop_on_exception: Literal[True, False] = False) -> Iterable[AssetWrite | ErrorDetails]:
|
|
266
|
-
for asset_resource in self.load(stop_on_exception):
|
|
267
|
-
if isinstance(asset_resource, AssetWrite):
|
|
268
|
-
yield asset_resource
|
|
269
|
-
|
|
270
|
-
@overload
|
|
271
|
-
def load_relationships(self, stop_on_exception: Literal[True]) -> Iterable[RelationshipWrite]: ...
|
|
272
|
-
|
|
273
|
-
@overload
|
|
274
|
-
def load_relationships(
|
|
275
|
-
self, stop_on_exception: Literal[False] = False
|
|
276
|
-
) -> Iterable[RelationshipWrite | ErrorDetails]: ...
|
|
277
|
-
|
|
278
|
-
def load_relationships(
|
|
279
|
-
self, stop_on_exception: Literal[True, False] = False
|
|
280
|
-
) -> Iterable[RelationshipWrite | ErrorDetails]:
|
|
281
|
-
for asset_resource in self.load(stop_on_exception):
|
|
282
|
-
if isinstance(asset_resource, RelationshipWrite):
|
|
283
|
-
yield asset_resource
|
|
284
|
-
|
|
285
|
-
def load_to_cdf(
|
|
286
|
-
self, client: CogniteClient, batch_size: int | None = 1000, max_retries: int = 1, retry_delay: int = 3
|
|
287
|
-
) -> None:
|
|
288
|
-
raise NotImplementedError
|
|
289
|
-
|
|
290
|
-
def _load_asset(
|
|
291
|
-
self, properties: list[Property], values_by_property: dict[str, str | list[str]], instance_id, class_name: str
|
|
292
|
-
) -> AssetWrite:
|
|
293
|
-
"""Converts a set of properties and values to an AssetWrite object."""
|
|
294
|
-
asset_raw = self._load_asset_data(properties, values_by_property, instance_id, class_name)
|
|
295
|
-
|
|
296
|
-
# Loading Asset assumes camel case.
|
|
297
|
-
# Todo Change rules to use camel case?
|
|
298
|
-
for snake_case, came_case in [
|
|
299
|
-
("external_id", "externalId"),
|
|
300
|
-
("parent_external_id", "parentExternalId"),
|
|
301
|
-
("geo_location", "geoLocation"),
|
|
302
|
-
]:
|
|
303
|
-
if snake_case in asset_raw:
|
|
304
|
-
asset_raw[came_case] = asset_raw.pop(snake_case)
|
|
305
|
-
|
|
306
|
-
return AssetWrite.load(asset_raw)
|
|
307
|
-
|
|
308
|
-
def _load_asset_data(
|
|
309
|
-
self,
|
|
310
|
-
properties: list[Property],
|
|
311
|
-
values_by_property: dict[str, str | list[str]],
|
|
312
|
-
instance_id: str,
|
|
313
|
-
class_name: str,
|
|
314
|
-
) -> dict[str, Any]:
|
|
315
|
-
"""Creates a raw asset dict from a set of properties and values."""
|
|
316
|
-
asset_raw, missing_metadata_properties = self._load_instance_data(properties, values_by_property)
|
|
317
|
-
|
|
318
|
-
self._append_missing_properties(asset_raw, missing_metadata_properties, instance_id, class_name)
|
|
319
|
-
|
|
320
|
-
asset_raw["dataSetId"] = self._data_set_id
|
|
321
|
-
|
|
322
|
-
# Neat specific metadata keys
|
|
323
|
-
if self._use_labels:
|
|
324
|
-
asset_raw["labels"] = [class_name, self._non_historic_label]
|
|
325
|
-
now = str(datetime.now(UTC))
|
|
326
|
-
asset_raw["metadata"][self._metadata_keys.start_time] = now
|
|
327
|
-
asset_raw["metadata"][self._metadata_keys.update_time] = now
|
|
328
|
-
asset_raw["metadata"][self._metadata_keys.identifier] = instance_id
|
|
329
|
-
asset_raw["metadata"][self._metadata_keys.active] = "true"
|
|
330
|
-
asset_raw["metadata"][self._metadata_keys.type] = class_name
|
|
331
|
-
|
|
332
|
-
# Rename metadata keys based on configuration
|
|
333
|
-
asset_raw["metadata"] = {self._metadata_key_aliases.get(k, k): v for k, v in asset_raw["metadata"].items()}
|
|
334
|
-
return asset_raw
|
|
335
|
-
|
|
336
|
-
def _prepare_instance_data(
|
|
337
|
-
self, instance_id: str, properties_values: Iterable[ResultRow]
|
|
338
|
-
) -> dict[str, str | list[str]]:
|
|
339
|
-
"""Groups the properties and values by property type.
|
|
340
|
-
|
|
341
|
-
Returns:
|
|
342
|
-
A dictionary with property type as key and a list of values as value.
|
|
343
|
-
"""
|
|
344
|
-
properties_value_tuples: list[tuple[str, str]] = [
|
|
345
|
-
remove_namespace_from_uri(prop, value) # type: ignore[misc]
|
|
346
|
-
for _, prop, value in properties_values
|
|
347
|
-
]
|
|
348
|
-
# We add an identifier which will be used as fallback for external_id
|
|
349
|
-
properties_value_tuples.append((self._identifier, remove_namespace_from_uri(instance_id)))
|
|
350
|
-
values_by_property: dict[str, str | list[str]] = {}
|
|
351
|
-
for prop, values in groupby(sorted(properties_value_tuples), lambda x: x[0]):
|
|
352
|
-
values_list: list[str] = [value for _, value in values] # type: ignore[misc, has-type]
|
|
353
|
-
if len(values_list) == 1:
|
|
354
|
-
values_by_property[prop] = values_list[0]
|
|
355
|
-
else:
|
|
356
|
-
values_by_property[prop] = values_list
|
|
357
|
-
return values_by_property
|
|
358
|
-
|
|
359
|
-
def _load_instance_data(
|
|
360
|
-
self, properties: list[Property], values_by_property: dict[str, str | list[str]]
|
|
361
|
-
) -> tuple[dict[str, Any], set[str]]:
|
|
362
|
-
"""This function loads the instance data into a raw asset dict. It also returns a set of metadata keys that
|
|
363
|
-
were not found in the instance data.
|
|
364
|
-
|
|
365
|
-
Returns:
|
|
366
|
-
A tuple with the raw asset dict and a set of metadata keys that were not found in the instance data.
|
|
367
|
-
"""
|
|
368
|
-
asset_raw: dict[str, Any] = {"metadata": {}}
|
|
369
|
-
missing_metadata_properties: set[str] = set()
|
|
370
|
-
for prop in properties:
|
|
371
|
-
if prop.property_name is None:
|
|
372
|
-
continue
|
|
373
|
-
is_relationship = "Asset" not in prop.cdf_resource_type
|
|
374
|
-
if not self._always_store_in_metadata and is_relationship:
|
|
375
|
-
continue
|
|
376
|
-
|
|
377
|
-
if prop.property_name not in values_by_property:
|
|
378
|
-
for property_type in prop.resource_type_property or []:
|
|
379
|
-
if property_type.casefold() == "metadata":
|
|
380
|
-
missing_metadata_properties.add(prop.property_name)
|
|
381
|
-
elif self._always_store_in_metadata:
|
|
382
|
-
missing_metadata_properties.add(prop.property_name)
|
|
383
|
-
continue
|
|
384
|
-
values = values_by_property[prop.property_name]
|
|
385
|
-
for property_type in prop.resource_type_property or []:
|
|
386
|
-
if property_type.casefold() == "metadata":
|
|
387
|
-
asset_raw["metadata"][prop.property_name] = self._to_metadata_value(values)
|
|
388
|
-
else:
|
|
389
|
-
if property_type not in asset_raw:
|
|
390
|
-
asset_raw[property_type] = values
|
|
391
|
-
if self._always_store_in_metadata and prop.property_name not in asset_raw["metadata"]:
|
|
392
|
-
asset_raw["metadata"][prop.property_name] = self._to_metadata_value(values)
|
|
393
|
-
if is_relationship:
|
|
394
|
-
asset_raw["metadata"][prop.property_name] = self._to_metadata_value(values)
|
|
395
|
-
|
|
396
|
-
return asset_raw, missing_metadata_properties
|
|
397
|
-
|
|
398
|
-
def _append_missing_properties(
|
|
399
|
-
self, asset_raw: dict[str, Any], missing_metadata_properties: set[str], identifier: str, class_name: str
|
|
400
|
-
) -> None:
|
|
401
|
-
"""This function ensures that the raw asset dict has all the required properties such as external_id, name,
|
|
402
|
-
and parent_external_id. It also ensures that the metadata dict has all the required keys."""
|
|
403
|
-
|
|
404
|
-
if "external_id" not in asset_raw:
|
|
405
|
-
msg = f"Missing external_id for {class_name} instance {identifier}. Using value <{identifier}>."
|
|
406
|
-
logging.debug(msg)
|
|
407
|
-
asset_raw["external_id"] = identifier
|
|
408
|
-
elif "external_id" in asset_raw and isinstance(asset_raw["external_id"], list):
|
|
409
|
-
external_ids = asset_raw["external_id"]
|
|
410
|
-
msg = (
|
|
411
|
-
f"Multiple values for {class_name} instance {identifier} external_id. "
|
|
412
|
-
f"Using the first one <{external_ids[0]}>."
|
|
413
|
-
)
|
|
414
|
-
logging.debug(msg)
|
|
415
|
-
asset_raw["external_id"] = external_ids[0]
|
|
416
|
-
|
|
417
|
-
if self._asset_external_id_prefix:
|
|
418
|
-
asset_raw["external_id"] = f"{self._asset_external_id_prefix}{asset_raw['external_id']}"
|
|
419
|
-
|
|
420
|
-
external_id = asset_raw["external_id"]
|
|
421
|
-
|
|
422
|
-
if "name" not in asset_raw:
|
|
423
|
-
msg = f"Missing name for {class_name} instance {external_id}. Using value <{identifier}>."
|
|
424
|
-
logging.debug(msg)
|
|
425
|
-
asset_raw["name"] = identifier
|
|
426
|
-
elif "name" in asset_raw and isinstance(asset_raw["name"], list):
|
|
427
|
-
msg = f"Multiple values for {class_name} instance {external_id} name. Joining them into one."
|
|
428
|
-
logging.debug(msg)
|
|
429
|
-
asset_raw["name"] = self._to_metadata_value(asset_raw["name"])
|
|
430
|
-
|
|
431
|
-
if "description" in asset_raw and isinstance(asset_raw["description"], list):
|
|
432
|
-
msg = f"Multiple values for {class_name} instance {external_id} description. Joining them into one."
|
|
433
|
-
logging.debug(msg)
|
|
434
|
-
asset_raw["description"] = self._to_metadata_value(asset_raw["description"])
|
|
435
|
-
|
|
436
|
-
if "parent_external_id" not in asset_raw and self._orphanage_external_id is not None:
|
|
437
|
-
asset_raw["parent_external_id"] = self._orphanage_external_id
|
|
438
|
-
elif "parent_external_id" in asset_raw and isinstance(asset_raw["parent_external_id"], list):
|
|
439
|
-
msg = (
|
|
440
|
-
f"Multiple values for {class_name} instance {external_id} parent_external_id. "
|
|
441
|
-
f"Using the first one <{asset_raw['parent_external_id'][0]}>."
|
|
442
|
-
)
|
|
443
|
-
logging.debug(msg)
|
|
444
|
-
asset_raw["parent_external_id"] = asset_raw["parent_external_id"][0]
|
|
445
|
-
|
|
446
|
-
if "parent_external_id" in asset_raw:
|
|
447
|
-
asset_raw["parent_external_id"] = f"{self._asset_external_id_prefix or ''}{asset_raw['parent_external_id']}"
|
|
448
|
-
|
|
449
|
-
for metadata_key in missing_metadata_properties:
|
|
450
|
-
msg = f"{external_id} of type {class_name} is missing metadata key {metadata_key}."
|
|
451
|
-
logging.debug(msg)
|
|
452
|
-
if self._default_metadata_value is not None and metadata_key not in asset_raw["metadata"]:
|
|
453
|
-
asset_raw["metadata"][metadata_key] = self._default_metadata_value
|
|
454
|
-
logging.debug(f"\tKey {metadata_key} added to <{external_id}> metadata!")
|
|
455
|
-
|
|
456
|
-
@staticmethod
|
|
457
|
-
def _to_metadata_value(values: str | list[str]) -> str:
|
|
458
|
-
"""A helper function to convert a list of values to a metadata value string respecting metadata value length."""
|
|
459
|
-
# Sorting for deterministic results
|
|
460
|
-
return values if isinstance(values, str) else ", ".join(sorted(values))[: METADATA_VALUE_MAX_LENGTH - 1]
|
|
461
|
-
|
|
462
|
-
def _load_relationships(
|
|
463
|
-
self,
|
|
464
|
-
properties: list[Property],
|
|
465
|
-
values_by_property: dict[str, str | list[str]],
|
|
466
|
-
instance_id: str,
|
|
467
|
-
class_name: str,
|
|
468
|
-
) -> RelationshipWriteList:
|
|
469
|
-
"""Converts a set of properties and values to a RelationshipWriteList object."""
|
|
470
|
-
relationships = RelationshipWriteList([])
|
|
471
|
-
relationship_properties = [prop for prop in properties if "Relationship" in prop.cdf_resource_type]
|
|
472
|
-
epoch_now = epoch_now_ms()
|
|
473
|
-
for prop in relationship_properties:
|
|
474
|
-
if not prop.property_name:
|
|
475
|
-
continue
|
|
476
|
-
values = values_by_property.get(prop.property_name, [])
|
|
477
|
-
if not values:
|
|
478
|
-
continue
|
|
479
|
-
value_list = [values] if isinstance(values, str) else values
|
|
480
|
-
for value in value_list:
|
|
481
|
-
relationship = self._load_relationship(prop, value, instance_id, class_name, epoch_now)
|
|
482
|
-
relationships.append(relationship)
|
|
483
|
-
|
|
484
|
-
return relationships
|
|
485
|
-
|
|
486
|
-
def _load_relationship(
|
|
487
|
-
self,
|
|
488
|
-
prop: Property,
|
|
489
|
-
target_id: str,
|
|
490
|
-
instance_id: str,
|
|
491
|
-
class_name: str,
|
|
492
|
-
epoch_now: int,
|
|
493
|
-
) -> RelationshipWrite:
|
|
494
|
-
"""Converts a set of properties and values to a RelationshipWrite object."""
|
|
495
|
-
prefix = self._asset_external_id_prefix or ""
|
|
496
|
-
labels = (
|
|
497
|
-
[class_name, self._non_historic_label, prop.expected_value_type.suffix, prop.property_id]
|
|
498
|
-
if self._use_labels
|
|
499
|
-
else None
|
|
500
|
-
)
|
|
501
|
-
relationship_raw = {
|
|
502
|
-
"externalId": f"{prefix}{instance_id}:{prefix}{target_id}",
|
|
503
|
-
"sourceExternalId": f"{prefix}{instance_id}",
|
|
504
|
-
"targetExternalId": f"{prefix}{target_id}",
|
|
505
|
-
"sourceType": prop.source_type,
|
|
506
|
-
"targetType": prop.target_type,
|
|
507
|
-
"dataSetId": self._data_set_id,
|
|
508
|
-
"labels": labels,
|
|
509
|
-
"startTime": epoch_now,
|
|
510
|
-
}
|
|
511
|
-
return RelationshipWrite.load(relationship_raw)
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
from abc import ABC, abstractmethod
|
|
3
|
-
from collections.abc import Iterable
|
|
4
|
-
from typing import Generic, Literal, TypeVar, overload
|
|
5
|
-
|
|
6
|
-
from cognite.client import CogniteClient
|
|
7
|
-
from pydantic_core import ErrorDetails
|
|
8
|
-
|
|
9
|
-
from cognite.neat.legacy.graph.models import Triple
|
|
10
|
-
from cognite.neat.legacy.graph.stores import NeatGraphStoreBase
|
|
11
|
-
from cognite.neat.legacy.graph.transformations.query_generator.sparql import build_construct_query
|
|
12
|
-
from cognite.neat.legacy.rules.models import Rules
|
|
13
|
-
|
|
14
|
-
T_Output = TypeVar("T_Output")
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class BaseLoader(ABC, Generic[T_Output]):
|
|
18
|
-
"""Base class for all loaders.
|
|
19
|
-
|
|
20
|
-
A loader is a class that loads data from a source graph into
|
|
21
|
-
target outside Neat.
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
def __init__(self, rules: Rules, graph_store: NeatGraphStoreBase):
|
|
25
|
-
self.rules = rules
|
|
26
|
-
self.graph_store = graph_store
|
|
27
|
-
|
|
28
|
-
@overload
|
|
29
|
-
def load(self, stop_on_exception: Literal[True]) -> Iterable[T_Output]: ...
|
|
30
|
-
|
|
31
|
-
@overload
|
|
32
|
-
def load(self, stop_on_exception: Literal[False] = False) -> Iterable[T_Output | ErrorDetails]: ...
|
|
33
|
-
|
|
34
|
-
@abstractmethod
|
|
35
|
-
def load(self, stop_on_exception: bool = False) -> Iterable[T_Output | ErrorDetails]:
|
|
36
|
-
"""Load the graph with data."""
|
|
37
|
-
pass
|
|
38
|
-
|
|
39
|
-
def _iterate_class_triples(self, exclude_classes: set[str] | None = None) -> Iterable[tuple[str, Iterable[Triple]]]:
|
|
40
|
-
"""Iterate over all classes and their triples."""
|
|
41
|
-
for class_name in self.rules.classes:
|
|
42
|
-
if exclude_classes is not None and class_name in exclude_classes:
|
|
43
|
-
continue
|
|
44
|
-
try:
|
|
45
|
-
sparql_construct_query = build_construct_query(
|
|
46
|
-
self.graph_store.graph, class_name, self.rules, properties_optional=True
|
|
47
|
-
)
|
|
48
|
-
except Exception as e:
|
|
49
|
-
logging.error(f"Failed to build construct query for class {class_name}: {e}")
|
|
50
|
-
continue
|
|
51
|
-
|
|
52
|
-
yield class_name, self.graph_store.query_delayed(sparql_construct_query)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
class CogniteLoader(BaseLoader[T_Output], ABC):
|
|
56
|
-
"""Base class for all loaders.
|
|
57
|
-
|
|
58
|
-
A loader is a class that loads data from a source graph into
|
|
59
|
-
target outside Neat.
|
|
60
|
-
"""
|
|
61
|
-
|
|
62
|
-
@abstractmethod
|
|
63
|
-
def load_to_cdf(
|
|
64
|
-
self, client: CogniteClient, batch_size: int | None = 1000, max_retries: int = 1, retry_delay: int = 3
|
|
65
|
-
) -> None:
|
|
66
|
-
"""Load the graph with data."""
|
|
67
|
-
pass
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
"""This module contains the definition of validation errors and warnings raised by various extractors"""
|
|
2
|
-
|
|
3
|
-
from pydantic_core import ErrorDetails, PydanticCustomError
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class NeatError(Exception):
|
|
7
|
-
type_: str
|
|
8
|
-
code: int
|
|
9
|
-
description: str
|
|
10
|
-
example: str
|
|
11
|
-
fix: str
|
|
12
|
-
message: str
|
|
13
|
-
|
|
14
|
-
def to_pydantic_custom_error(self):
|
|
15
|
-
return PydanticCustomError(
|
|
16
|
-
self.type_,
|
|
17
|
-
self.message,
|
|
18
|
-
dict(type_=self.type_, code=self.code, description=self.description, example=self.example, fix=self.fix),
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
def to_error_dict(self) -> ErrorDetails:
|
|
22
|
-
return {
|
|
23
|
-
"type": self.type_,
|
|
24
|
-
"loc": (),
|
|
25
|
-
"msg": self.message,
|
|
26
|
-
"input": None,
|
|
27
|
-
"ctx": dict(
|
|
28
|
-
type_=self.type_,
|
|
29
|
-
code=self.code,
|
|
30
|
-
description=self.description,
|
|
31
|
-
example=self.example,
|
|
32
|
-
fix=self.fix,
|
|
33
|
-
),
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
class NeatWarning(UserWarning):
|
|
38
|
-
type_: str
|
|
39
|
-
code: int
|
|
40
|
-
description: str
|
|
41
|
-
example: str
|
|
42
|
-
fix: str
|
|
43
|
-
message: str
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
class Warning1(NeatWarning):
|
|
47
|
-
type_: str = "OWLGeneratedTransformationRulesHasErrors"
|
|
48
|
-
code: int = 1
|
|
49
|
-
description: str = (
|
|
50
|
-
"This warning occurs when generating transformation rules from OWL ontology are invalid/incomplete."
|
|
51
|
-
)
|
|
52
|
-
example: str = ""
|
|
53
|
-
fix: str = "Go through the generated report file and fix the warnings in generated Transformation Rules."
|
|
54
|
-
|
|
55
|
-
def __init__(self, verbose=False):
|
|
56
|
-
self.message = (
|
|
57
|
-
"Transformation rules generated from OWL ontology are invalid!"
|
|
58
|
-
" Consult report.txt for details on the errors and fix them before using the rules file."
|
|
59
|
-
)
|
|
60
|
-
if verbose:
|
|
61
|
-
self.message += f"\nDescription: {self.description}"
|
|
62
|
-
self.message += f"\nExample: {self.example}"
|
|
63
|
-
self.message += f"\nFix: {self.fix}"
|
|
64
|
-
# hint on a specific web docs page
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
class Warning2(NeatWarning):
|
|
68
|
-
type_: str = "OWLGeneratedTransformationRulesHasWarnings"
|
|
69
|
-
code: int = 2
|
|
70
|
-
description: str = (
|
|
71
|
-
"This warning occurs when generating transformation rules from OWL ontology are invalid/incomplete."
|
|
72
|
-
)
|
|
73
|
-
example: str = ""
|
|
74
|
-
fix: str = "Go through the generated report file and fix the warnings in generated Transformation Rules."
|
|
75
|
-
|
|
76
|
-
def __init__(self, verbose=False):
|
|
77
|
-
self.message = (
|
|
78
|
-
"Transformation rules generated from OWL ontology raised warnings!"
|
|
79
|
-
" Consult report.txt for details on warnings, and fix them prior using the rules file."
|
|
80
|
-
)
|
|
81
|
-
if verbose:
|
|
82
|
-
self.message += f"\nDescription: {self.description}"
|
|
83
|
-
self.message += f"\nExample: {self.example}"
|
|
84
|
-
self.message += f"\nFix: {self.fix}"
|
|
85
|
-
# hint on a specific web docs page
|
|
File without changes
|