cognite-neat 0.106.0__py3-none-any.whl → 0.108.0__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/_constants.py +35 -1
- cognite/neat/_graph/_shared.py +4 -0
- cognite/neat/_graph/extractors/__init__.py +5 -1
- cognite/neat/_graph/extractors/_base.py +32 -0
- cognite/neat/_graph/extractors/_classic_cdf/_base.py +128 -14
- cognite/neat/_graph/extractors/_classic_cdf/_classic.py +156 -12
- cognite/neat/_graph/extractors/_classic_cdf/_relationships.py +50 -12
- cognite/neat/_graph/extractors/_classic_cdf/_sequences.py +26 -1
- cognite/neat/_graph/extractors/_dms.py +196 -47
- cognite/neat/_graph/extractors/_dms_graph.py +199 -0
- cognite/neat/_graph/extractors/_mock_graph_generator.py +1 -1
- cognite/neat/_graph/extractors/_rdf_file.py +33 -5
- cognite/neat/_graph/loaders/__init__.py +1 -3
- cognite/neat/_graph/loaders/_rdf2dms.py +123 -19
- cognite/neat/_graph/queries/_base.py +140 -84
- cognite/neat/_graph/queries/_construct.py +2 -2
- cognite/neat/_graph/transformers/__init__.py +8 -1
- cognite/neat/_graph/transformers/_base.py +9 -1
- cognite/neat/_graph/transformers/_classic_cdf.py +90 -3
- cognite/neat/_graph/transformers/_rdfpath.py +3 -3
- cognite/neat/_graph/transformers/_value_type.py +106 -45
- cognite/neat/_issues/errors/_resources.py +1 -1
- cognite/neat/_issues/warnings/__init__.py +0 -2
- cognite/neat/_issues/warnings/_models.py +1 -1
- cognite/neat/_issues/warnings/_properties.py +0 -8
- cognite/neat/_rules/analysis/_base.py +1 -1
- cognite/neat/_rules/analysis/_information.py +14 -13
- cognite/neat/_rules/catalog/__init__.py +1 -0
- cognite/neat/_rules/catalog/classic_model.xlsx +0 -0
- cognite/neat/_rules/catalog/info-rules-imf.xlsx +0 -0
- cognite/neat/_rules/exporters/_rules2instance_template.py +3 -3
- cognite/neat/_rules/importers/__init__.py +3 -1
- cognite/neat/_rules/importers/_dms2rules.py +7 -5
- cognite/neat/_rules/importers/_dtdl2rules/spec.py +1 -2
- cognite/neat/_rules/importers/_rdf/__init__.py +2 -2
- cognite/neat/_rules/importers/_rdf/_base.py +2 -2
- cognite/neat/_rules/importers/_rdf/_inference2rules.py +242 -19
- cognite/neat/_rules/models/_base_rules.py +13 -15
- cognite/neat/_rules/models/_types.py +5 -0
- cognite/neat/_rules/models/dms/_rules.py +51 -10
- cognite/neat/_rules/models/dms/_rules_input.py +4 -0
- cognite/neat/_rules/models/information/_rules.py +48 -5
- cognite/neat/_rules/models/information/_rules_input.py +6 -1
- cognite/neat/_rules/models/mapping/_classic2core.py +4 -5
- cognite/neat/_rules/transformers/__init__.py +10 -0
- cognite/neat/_rules/transformers/_converters.py +300 -62
- cognite/neat/_session/_base.py +57 -10
- cognite/neat/_session/_drop.py +5 -1
- cognite/neat/_session/_inspect.py +3 -2
- cognite/neat/_session/_mapping.py +17 -6
- cognite/neat/_session/_prepare.py +0 -47
- cognite/neat/_session/_read.py +115 -10
- cognite/neat/_session/_set.py +27 -0
- cognite/neat/_session/_show.py +4 -4
- cognite/neat/_session/_state.py +12 -1
- cognite/neat/_session/_to.py +43 -2
- cognite/neat/_session/_wizard.py +1 -1
- cognite/neat/_session/exceptions.py +8 -3
- cognite/neat/_store/_graph_store.py +331 -136
- cognite/neat/_store/_rules_store.py +130 -1
- cognite/neat/_utils/auth.py +3 -1
- cognite/neat/_version.py +1 -1
- {cognite_neat-0.106.0.dist-info → cognite_neat-0.108.0.dist-info}/METADATA +2 -2
- {cognite_neat-0.106.0.dist-info → cognite_neat-0.108.0.dist-info}/RECORD +67 -65
- {cognite_neat-0.106.0.dist-info → cognite_neat-0.108.0.dist-info}/WHEEL +1 -1
- {cognite_neat-0.106.0.dist-info → cognite_neat-0.108.0.dist-info}/LICENSE +0 -0
- {cognite_neat-0.106.0.dist-info → cognite_neat-0.108.0.dist-info}/entry_points.txt +0 -0
|
@@ -35,8 +35,8 @@ class AddSelfReferenceProperty(BaseTransformer):
|
|
|
35
35
|
|
|
36
36
|
def transform(self, graph: Graph) -> None:
|
|
37
37
|
for property_ in self.properties:
|
|
38
|
-
prefix = property_.
|
|
39
|
-
suffix = property_.
|
|
38
|
+
prefix = property_.instance_source.traversal.class_.prefix
|
|
39
|
+
suffix = property_.instance_source.traversal.class_.suffix
|
|
40
40
|
|
|
41
41
|
namespace = self.rules.prefixes[prefix] if prefix in self.rules.prefixes else self.rules.metadata.namespace
|
|
42
42
|
|
|
@@ -54,7 +54,7 @@ class AddSelfReferenceProperty(BaseTransformer):
|
|
|
54
54
|
property_=f"{self.rules.metadata.prefix}:{property_.property_}",
|
|
55
55
|
)
|
|
56
56
|
|
|
57
|
-
property_.
|
|
57
|
+
property_.instance_source = RDFPath(traversal=traversal)
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
class MakeConnectionOnExactMatch(BaseTransformerStandardised):
|
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
import warnings
|
|
2
|
-
from collections.abc import Callable
|
|
2
|
+
from collections.abc import Callable, Iterator
|
|
3
3
|
from typing import Any, cast
|
|
4
4
|
from urllib.parse import quote
|
|
5
5
|
|
|
6
6
|
import rdflib
|
|
7
|
-
from rdflib import RDF,
|
|
7
|
+
from rdflib import RDF, Literal, Namespace, URIRef
|
|
8
8
|
from rdflib.query import ResultRow
|
|
9
9
|
|
|
10
|
-
from cognite.neat._constants import
|
|
11
|
-
from cognite.neat._graph.queries import Queries
|
|
10
|
+
from cognite.neat._constants import NEAT
|
|
12
11
|
from cognite.neat._issues.warnings import PropertyDataTypeConversionWarning
|
|
13
12
|
from cognite.neat._utils.auxiliary import string_to_ideal_type
|
|
14
|
-
from cognite.neat._utils.rdf_ import get_namespace, remove_namespace_from_uri
|
|
13
|
+
from cognite.neat._utils.rdf_ import Triple, get_namespace, remove_namespace_from_uri
|
|
15
14
|
|
|
16
|
-
from ._base import
|
|
15
|
+
from ._base import BaseTransformerStandardised, RowTransformationOutput
|
|
17
16
|
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
class SplitMultiValueProperty(BaseTransformer):
|
|
18
|
+
class SplitMultiValueProperty(BaseTransformerStandardised):
|
|
21
19
|
description: str = (
|
|
22
20
|
"SplitMultiValueProperty is a transformer that splits a "
|
|
23
21
|
"multi-value property into multiple single-value properties."
|
|
@@ -25,55 +23,67 @@ class SplitMultiValueProperty(BaseTransformer):
|
|
|
25
23
|
_use_only_once: bool = True
|
|
26
24
|
_need_changes = frozenset({})
|
|
27
25
|
|
|
28
|
-
|
|
26
|
+
def __init__(self, unknown_type: URIRef | None = None) -> None:
|
|
27
|
+
self.unknown_type = unknown_type or NEAT.UnknownType
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
def _iterate_query(self) -> str:
|
|
30
|
+
query = """SELECT ?subjectType ?property
|
|
31
|
+
(GROUP_CONCAT(DISTINCT STR(?valueType); SEPARATOR=",") AS ?valueTypes)
|
|
32
|
+
|
|
33
|
+
WHERE {{
|
|
34
|
+
?s ?property ?o .
|
|
35
|
+
?s a ?subjectType .
|
|
36
|
+
OPTIONAL {{ ?o a ?type }}
|
|
37
|
+
|
|
38
|
+
# Key part to determine value type: either object, data or unknown
|
|
39
|
+
BIND( IF(isLiteral(?o),DATATYPE(?o),
|
|
40
|
+
IF(BOUND(?type), ?type,
|
|
41
|
+
<{unknownType}>)) AS ?valueType)
|
|
42
|
+
}}
|
|
43
|
+
|
|
44
|
+
GROUP BY ?subjectType ?property
|
|
45
|
+
HAVING (COUNT(DISTINCT ?valueType) > 1)"""
|
|
46
|
+
|
|
47
|
+
return query.format(unknownType=self.unknown_type)
|
|
48
|
+
|
|
49
|
+
def _count_query(self) -> str:
|
|
50
|
+
query = """SELECT (COUNT(*) AS ?tripleCount)
|
|
51
|
+
WHERE {?s ?p ?o .}"""
|
|
52
|
+
return query
|
|
53
|
+
|
|
54
|
+
def _sub_iterate_query(self, type_: URIRef, property_: URIRef) -> str:
|
|
55
|
+
query = """ SELECT ?s ?p ?o ?valueType WHERE {{
|
|
56
|
+
?s a <{subject_uri}> .
|
|
57
|
+
?s <{property_uri}> ?o .
|
|
33
58
|
|
|
34
|
-
|
|
59
|
+
OPTIONAL {{ ?o a ?type }}
|
|
35
60
|
|
|
36
|
-
|
|
61
|
+
BIND(<{property_uri}> AS ?p)
|
|
37
62
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
63
|
+
BIND(IF(isLiteral(?o), DATATYPE(?o),
|
|
64
|
+
IF(BOUND(?type),?type,
|
|
65
|
+
<{unknownType}>)) AS ?valueType)
|
|
41
66
|
|
|
42
|
-
|
|
67
|
+
}} """
|
|
43
68
|
|
|
44
|
-
|
|
69
|
+
return query.format(unknownType=self.unknown_type, subject_uri=type_, property_uri=property_)
|
|
45
70
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}}"""
|
|
71
|
+
def _iterator(self, graph) -> Iterator:
|
|
72
|
+
for type_, property_, _ in graph.query(self._iterate_query()):
|
|
73
|
+
yield from graph.query(self._sub_iterate_query(type_, property_))
|
|
50
74
|
|
|
51
|
-
def
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
for value_type_uri in value_types:
|
|
55
|
-
_args = {
|
|
56
|
-
"subject_uri": subject_uri,
|
|
57
|
-
"property_uri": property_uri,
|
|
58
|
-
"object_uri": value_type_uri,
|
|
59
|
-
}
|
|
75
|
+
def operation(self, query_result_row: ResultRow) -> RowTransformationOutput:
|
|
76
|
+
row_output = RowTransformationOutput()
|
|
77
|
+
subject, old_property, object, value_type = query_result_row
|
|
60
78
|
|
|
61
|
-
|
|
62
|
-
if value_type_uri == UNKNOWN_TYPE:
|
|
63
|
-
iterator = graph.query(self._unknown_property_template.format(**_args))
|
|
79
|
+
new_property = URIRef(f"{old_property}_{remove_namespace_from_uri(value_type)}")
|
|
64
80
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
iterator = graph.query(self._datatype_property_template.format(**_args))
|
|
81
|
+
row_output.add_triples.append(cast(Triple, (subject, new_property, object)))
|
|
82
|
+
row_output.remove_triples.append(cast(Triple, (subject, old_property, object)))
|
|
68
83
|
|
|
69
|
-
|
|
70
|
-
else:
|
|
71
|
-
iterator = graph.query(self._object_property_template.format(**_args))
|
|
84
|
+
row_output.instances_modified_count += 1
|
|
72
85
|
|
|
73
|
-
|
|
74
|
-
graph.remove((s, property_uri, o))
|
|
75
|
-
new_property = URIRef(f"{property_uri}_{remove_namespace_from_uri(value_type_uri)}")
|
|
76
|
-
graph.add((s, new_property, o))
|
|
86
|
+
return row_output
|
|
77
87
|
|
|
78
88
|
|
|
79
89
|
class ConvertLiteral(BaseTransformerStandardised):
|
|
@@ -295,3 +305,54 @@ class ConnectionToLiteral(BaseTransformerStandardised):
|
|
|
295
305
|
row_output.instances_modified_count += 1
|
|
296
306
|
|
|
297
307
|
return row_output
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
class SetNeatType(BaseTransformerStandardised):
|
|
311
|
+
description = "Set the sub type of an instance based on the property"
|
|
312
|
+
|
|
313
|
+
def __init__(
|
|
314
|
+
self, subject_type: URIRef, subject_predicate: URIRef, drop_property: bool, namespace: Namespace | None = None
|
|
315
|
+
) -> None:
|
|
316
|
+
self.subject_type = subject_type
|
|
317
|
+
self.subject_predicate = subject_predicate
|
|
318
|
+
self.drop_property = drop_property
|
|
319
|
+
self._namespace = namespace or Namespace(get_namespace(subject_type))
|
|
320
|
+
|
|
321
|
+
def _count_query(self) -> str:
|
|
322
|
+
query = """SELECT (COUNT(?object) AS ?objectCount)
|
|
323
|
+
WHERE {{
|
|
324
|
+
?instance a <{subject_type}> .
|
|
325
|
+
?instance <{subject_predicate}> ?object
|
|
326
|
+
FILTER(isLiteral(?object))
|
|
327
|
+
}}"""
|
|
328
|
+
return query.format(subject_type=self.subject_type, subject_predicate=self.subject_predicate)
|
|
329
|
+
|
|
330
|
+
def _skip_count_query(self) -> str:
|
|
331
|
+
query = """SELECT (COUNT(?object) AS ?objectCount)
|
|
332
|
+
WHERE {{
|
|
333
|
+
?instance a <{subject_type}> .
|
|
334
|
+
?instance <{subject_predicate}> ?object
|
|
335
|
+
FILTER(isIRI(?object))
|
|
336
|
+
}}"""
|
|
337
|
+
return query.format(subject_type=self.subject_type, subject_predicate=self.subject_predicate)
|
|
338
|
+
|
|
339
|
+
def _iterate_query(self) -> str:
|
|
340
|
+
query = """SELECT ?instance ?object
|
|
341
|
+
WHERE {{
|
|
342
|
+
?instance a <{subject_type}> .
|
|
343
|
+
?instance <{subject_predicate}> ?object
|
|
344
|
+
FILTER(isLiteral(?object))
|
|
345
|
+
}}"""
|
|
346
|
+
return query.format(subject_type=self.subject_type, subject_predicate=self.subject_predicate)
|
|
347
|
+
|
|
348
|
+
def operation(self, query_result_row: ResultRow) -> RowTransformationOutput:
|
|
349
|
+
row_output = RowTransformationOutput()
|
|
350
|
+
|
|
351
|
+
instance, object_literal = cast(tuple[URIRef, Literal], query_result_row)
|
|
352
|
+
if self.drop_property:
|
|
353
|
+
row_output.remove_triples.append((instance, self.subject_predicate, object_literal))
|
|
354
|
+
|
|
355
|
+
row_output.add_triples.append((instance, NEAT.type, self._namespace[str(object_literal.toPython())]))
|
|
356
|
+
row_output.instances_modified_count += 1
|
|
357
|
+
|
|
358
|
+
return row_output
|
|
@@ -30,7 +30,7 @@ class ResourceRetrievalError(ResourceError[T_Identifier]):
|
|
|
30
30
|
|
|
31
31
|
@dataclass(unsafe_hash=True)
|
|
32
32
|
class ResourceNotFoundError(ResourceError, Generic[T_Identifier, T_ReferenceIdentifier]):
|
|
33
|
-
"""The {resource_type} with identifier {identifier} does not exist"""
|
|
33
|
+
"""The {resource_type} with identifier '{identifier}' does not exist"""
|
|
34
34
|
|
|
35
35
|
extra = " This is expected by {referred_type} {referred_by}."
|
|
36
36
|
|
|
@@ -31,7 +31,6 @@ from ._properties import (
|
|
|
31
31
|
PropertyDirectRelationLimitWarning,
|
|
32
32
|
PropertyNotFoundWarning,
|
|
33
33
|
PropertyOverwritingWarning,
|
|
34
|
-
PropertySkippedWarning,
|
|
35
34
|
PropertyTypeNotSupportedWarning,
|
|
36
35
|
PropertyValueTypeUndefinedWarning,
|
|
37
36
|
)
|
|
@@ -68,7 +67,6 @@ __all__ = [
|
|
|
68
67
|
"PropertyDirectRelationLimitWarning",
|
|
69
68
|
"PropertyNotFoundWarning",
|
|
70
69
|
"PropertyOverwritingWarning",
|
|
71
|
-
"PropertySkippedWarning",
|
|
72
70
|
"PropertyTypeNotSupportedWarning",
|
|
73
71
|
"PropertyValueTypeUndefinedWarning",
|
|
74
72
|
"RegexViolationWarning",
|
|
@@ -74,7 +74,7 @@ class CDFNotSupportedWarning(NeatWarning, ABC):
|
|
|
74
74
|
class NotSupportedViewContainerLimitWarning(CDFNotSupportedWarning):
|
|
75
75
|
"""The view {view_id} maps, {count} containers, which is more than the limit {limit}."""
|
|
76
76
|
|
|
77
|
-
fix = "Reduce the number of containers the view maps to."
|
|
77
|
+
fix = "Reduce the number of containers the view maps to."
|
|
78
78
|
|
|
79
79
|
view_id: ViewId
|
|
80
80
|
count: int
|
|
@@ -65,14 +65,6 @@ class PropertyOverwritingWarning(PropertyWarning[T_Identifier]):
|
|
|
65
65
|
overwriting: tuple[str, ...]
|
|
66
66
|
|
|
67
67
|
|
|
68
|
-
@dataclass(unsafe_hash=True)
|
|
69
|
-
class PropertySkippedWarning(PropertyWarning[T_Identifier]):
|
|
70
|
-
"""The {resource_type} with identifier {identifier} has a property {property_name}
|
|
71
|
-
which is skipped. {reason}."""
|
|
72
|
-
|
|
73
|
-
reason: str
|
|
74
|
-
|
|
75
|
-
|
|
76
68
|
@dataclass(unsafe_hash=True)
|
|
77
69
|
class PropertyDataTypeConversionWarning(PropertyWarning[T_Identifier]):
|
|
78
70
|
"""The {resource_type} with identifier {identifier} failed to convert the property {property_name}: {error}"""
|
|
@@ -251,7 +251,7 @@ class BaseAnalysis(ABC, Generic[T_Rules, T_Class, T_Property, T_ClassEntity, T_P
|
|
|
251
251
|
if (
|
|
252
252
|
only_rdfpath
|
|
253
253
|
and isinstance(property_, InformationProperty)
|
|
254
|
-
and isinstance(property_.
|
|
254
|
+
and isinstance(property_.instance_source, RDFPath)
|
|
255
255
|
) or not only_rdfpath:
|
|
256
256
|
processed_properties[prop_entity] = property_
|
|
257
257
|
class_property_pairs[class_] = processed_properties
|
|
@@ -55,12 +55,13 @@ class InformationAnalysis(BaseAnalysis[InformationRules, InformationClass, Infor
|
|
|
55
55
|
|
|
56
56
|
def has_hop_transformations(self):
|
|
57
57
|
return any(
|
|
58
|
-
prop_.
|
|
58
|
+
prop_.instance_source and isinstance(prop_.instance_source.traversal, Hop)
|
|
59
|
+
for prop_ in self.rules.properties
|
|
59
60
|
)
|
|
60
61
|
|
|
61
62
|
def has_self_reference_property_transformations(self):
|
|
62
63
|
return any(
|
|
63
|
-
prop_.
|
|
64
|
+
prop_.instance_source and isinstance(prop_.instance_source.traversal, SelfReferenceProperty)
|
|
64
65
|
for prop_ in self.rules.properties
|
|
65
66
|
)
|
|
66
67
|
|
|
@@ -68,7 +69,7 @@ class InformationAnalysis(BaseAnalysis[InformationRules, InformationClass, Infor
|
|
|
68
69
|
return [
|
|
69
70
|
prop_
|
|
70
71
|
for prop_ in self.rules.properties
|
|
71
|
-
if prop_.
|
|
72
|
+
if prop_.instance_source and isinstance(prop_.instance_source.traversal, SelfReferenceProperty)
|
|
72
73
|
]
|
|
73
74
|
|
|
74
75
|
def define_property_renaming_config(self, class_: ClassEntity) -> dict[str | URIRef, str]:
|
|
@@ -76,7 +77,7 @@ class InformationAnalysis(BaseAnalysis[InformationRules, InformationClass, Infor
|
|
|
76
77
|
|
|
77
78
|
if definitions := self.class_property_pairs(only_rdfpath=True, consider_inheritance=True).get(class_, None):
|
|
78
79
|
for property_id, definition in definitions.items():
|
|
79
|
-
transformation = cast(RDFPath, definition.
|
|
80
|
+
transformation = cast(RDFPath, definition.instance_source)
|
|
80
81
|
|
|
81
82
|
# use case we have a single property rdf path, and defined prefix
|
|
82
83
|
# in either metadata or prefixes of rules
|
|
@@ -101,26 +102,26 @@ class InformationAnalysis(BaseAnalysis[InformationRules, InformationClass, Infor
|
|
|
101
102
|
|
|
102
103
|
return property_renaming_configuration
|
|
103
104
|
|
|
104
|
-
def
|
|
105
|
+
def neat_id_to_instance_source_property_uri(self, property_neat_id: URIRef) -> URIRef | None:
|
|
105
106
|
if (
|
|
106
107
|
(property_ := self.properties_by_neat_id.get(property_neat_id))
|
|
107
|
-
and property_.
|
|
108
|
+
and property_.instance_source
|
|
108
109
|
and isinstance(
|
|
109
|
-
property_.
|
|
110
|
+
property_.instance_source.traversal,
|
|
110
111
|
SingleProperty,
|
|
111
112
|
)
|
|
112
113
|
and (
|
|
113
|
-
property_.
|
|
114
|
-
or property_.
|
|
114
|
+
property_.instance_source.traversal.property.prefix in self.rules.prefixes
|
|
115
|
+
or property_.instance_source.traversal.property.prefix == self.rules.metadata.prefix
|
|
115
116
|
)
|
|
116
117
|
):
|
|
117
118
|
namespace = (
|
|
118
119
|
self.rules.metadata.namespace
|
|
119
|
-
if property_.
|
|
120
|
-
else self.rules.prefixes[property_.
|
|
120
|
+
if property_.instance_source.traversal.property.prefix == self.rules.metadata.prefix
|
|
121
|
+
else self.rules.prefixes[property_.instance_source.traversal.property.prefix]
|
|
121
122
|
)
|
|
122
123
|
|
|
123
|
-
return namespace[property_.
|
|
124
|
+
return namespace[property_.instance_source.traversal.property.suffix]
|
|
124
125
|
return None
|
|
125
126
|
|
|
126
127
|
def property_types(self, class_: ClassEntity) -> dict[str, EntityTypes]:
|
|
@@ -137,7 +138,7 @@ class InformationAnalysis(BaseAnalysis[InformationRules, InformationClass, Infor
|
|
|
137
138
|
class_, None
|
|
138
139
|
):
|
|
139
140
|
for property_ in class_property_pairs.values():
|
|
140
|
-
classes.append(cast(RDFPath, property_.
|
|
141
|
+
classes.append(cast(RDFPath, property_.instance_source).traversal.class_)
|
|
141
142
|
|
|
142
143
|
return cast(ClassEntity, most_occurring_element(classes))
|
|
143
144
|
else:
|
|
Binary file
|
|
Binary file
|
|
@@ -96,13 +96,13 @@ class InstanceTemplateExporter(BaseExporter[InformationRules, Workbook]):
|
|
|
96
96
|
def _add_index_identifiers(workbook: Workbook, sheet: str, no_rows: int):
|
|
97
97
|
"""Adds index-based auto identifier to a sheet identifier column"""
|
|
98
98
|
for i in range(no_rows):
|
|
99
|
-
workbook[sheet][f"A{i+2}"] = f'=IF(ISBLANK(B{i+2}), "","{sheet}-{i+1}")'
|
|
99
|
+
workbook[sheet][f"A{i + 2}"] = f'=IF(ISBLANK(B{i + 2}), "","{sheet}-{i + 1}")'
|
|
100
100
|
|
|
101
101
|
|
|
102
102
|
def _add_uuid_identifiers(workbook: Workbook, sheet: str, no_rows: int):
|
|
103
103
|
"""Adds UUID-based auto identifier to a sheet identifier column"""
|
|
104
104
|
for i in range(no_rows):
|
|
105
|
-
workbook[sheet][f"A{i+2}"] = f'=IF(ISBLANK(B{i+2}), "","{sheet}-{uuid.uuid4()}")'
|
|
105
|
+
workbook[sheet][f"A{i + 2}"] = f'=IF(ISBLANK(B{i + 2}), "","{sheet}-{uuid.uuid4()}")'
|
|
106
106
|
|
|
107
107
|
|
|
108
108
|
def _add_drop_down_list(
|
|
@@ -122,7 +122,7 @@ def _add_drop_down_list(
|
|
|
122
122
|
workbook[sheet].add_data_validation(drop_down_list)
|
|
123
123
|
|
|
124
124
|
for i in range(no_rows):
|
|
125
|
-
drop_down_list.add(workbook[sheet][f"{column}{i+2}"])
|
|
125
|
+
drop_down_list.add(workbook[sheet][f"{column}{i + 2}"])
|
|
126
126
|
|
|
127
127
|
|
|
128
128
|
def _adjust_column_width(workbook: Workbook):
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from ._base import BaseImporter
|
|
2
2
|
from ._dms2rules import DMSImporter
|
|
3
3
|
from ._dtdl2rules import DTDLImporter
|
|
4
|
-
from ._rdf import IMFImporter, InferenceImporter, OWLImporter
|
|
4
|
+
from ._rdf import IMFImporter, InferenceImporter, OWLImporter, SubclassInferenceImporter
|
|
5
5
|
from ._spreadsheet2rules import ExcelImporter, GoogleSheetImporter
|
|
6
6
|
from ._yaml2rules import YAMLImporter
|
|
7
7
|
|
|
@@ -14,6 +14,7 @@ __all__ = [
|
|
|
14
14
|
"IMFImporter",
|
|
15
15
|
"InferenceImporter",
|
|
16
16
|
"OWLImporter",
|
|
17
|
+
"SubclassInferenceImporter",
|
|
17
18
|
"YAMLImporter",
|
|
18
19
|
]
|
|
19
20
|
|
|
@@ -26,6 +27,7 @@ RulesImporters = (
|
|
|
26
27
|
| DTDLImporter
|
|
27
28
|
| YAMLImporter
|
|
28
29
|
| InferenceImporter
|
|
30
|
+
| SubclassInferenceImporter
|
|
29
31
|
)
|
|
30
32
|
|
|
31
33
|
|
|
@@ -115,8 +115,8 @@ class DMSImporter(BaseImporter[DMSInputRules]):
|
|
|
115
115
|
data_model_ids = [data_model_id]
|
|
116
116
|
data_models = client.data_modeling.data_models.retrieve(data_model_ids, inline_views=True)
|
|
117
117
|
|
|
118
|
-
|
|
119
|
-
if len(
|
|
118
|
+
retrieved_models = cls._find_model_in_list(data_models, data_model_id)
|
|
119
|
+
if len(retrieved_models) == 0:
|
|
120
120
|
return cls(
|
|
121
121
|
DMSSchema(),
|
|
122
122
|
[
|
|
@@ -127,16 +127,18 @@ class DMSImporter(BaseImporter[DMSInputRules]):
|
|
|
127
127
|
)
|
|
128
128
|
],
|
|
129
129
|
)
|
|
130
|
-
|
|
130
|
+
return cls.from_data_model(client, retrieved_models.latest_version())
|
|
131
131
|
|
|
132
|
+
@classmethod
|
|
133
|
+
def from_data_model(cls, client: NeatClient, model: dm.DataModel[dm.View]) -> "DMSImporter":
|
|
132
134
|
issue_list = IssueList()
|
|
133
135
|
with _handle_issues(issue_list) as result:
|
|
134
|
-
schema =
|
|
136
|
+
schema = client.schema.retrieve_data_model(model)
|
|
135
137
|
|
|
136
138
|
if result.result == "failure" or issue_list.has_errors:
|
|
137
139
|
return cls(DMSSchema(), issue_list)
|
|
138
140
|
|
|
139
|
-
metadata = cls._create_metadata_from_model(
|
|
141
|
+
metadata = cls._create_metadata_from_model(model)
|
|
140
142
|
|
|
141
143
|
return cls(
|
|
142
144
|
schema,
|
|
@@ -302,8 +302,7 @@ class Interface(DTDLBase):
|
|
|
302
302
|
spec_version = frozenset(["2", "3"])
|
|
303
303
|
default_context: ClassVar[IRI] = Field(
|
|
304
304
|
"dtmi:dtdl:context;3",
|
|
305
|
-
description="This can be set directly on the class to change the "
|
|
306
|
-
"default context used when parsing a document.",
|
|
305
|
+
description="This can be set directly on the class to change the default context used when parsing a document.",
|
|
307
306
|
)
|
|
308
307
|
id_: DTMI = Field(alias="@id") # type: ignore[assignment]
|
|
309
308
|
context: IRI | None = Field(alias="@context")
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from ._imf2rules import IMFImporter
|
|
2
|
-
from ._inference2rules import InferenceImporter
|
|
2
|
+
from ._inference2rules import InferenceImporter, SubclassInferenceImporter
|
|
3
3
|
from ._owl2rules import OWLImporter
|
|
4
4
|
|
|
5
|
-
__all__ = ["IMFImporter", "InferenceImporter", "OWLImporter"]
|
|
5
|
+
__all__ = ["IMFImporter", "InferenceImporter", "OWLImporter", "SubclassInferenceImporter"]
|
|
@@ -72,7 +72,7 @@ class BaseRDFImporter(BaseImporter[InformationInputRules]):
|
|
|
72
72
|
):
|
|
73
73
|
return cls(
|
|
74
74
|
IssueList(title=f"{cls.__name__} issues"),
|
|
75
|
-
store.
|
|
75
|
+
store.dataset,
|
|
76
76
|
data_model_id=data_model_id,
|
|
77
77
|
max_number_of_instance=max_number_of_instance,
|
|
78
78
|
non_existing_node_type=non_existing_node_type,
|
|
@@ -140,7 +140,7 @@ class BaseRDFImporter(BaseImporter[InformationInputRules]):
|
|
|
140
140
|
prefixes: Dict of prefixes and namespaces
|
|
141
141
|
"""
|
|
142
142
|
if Namespace(get_namespace(URI)) not in prefixes.values():
|
|
143
|
-
prefixes[f"prefix_{len(prefixes)+1}"] = Namespace(get_namespace(URI))
|
|
143
|
+
prefixes[f"prefix_{len(prefixes) + 1}"] = Namespace(get_namespace(URI))
|
|
144
144
|
|
|
145
145
|
@property
|
|
146
146
|
def _metadata(self) -> dict:
|