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.

Files changed (67) hide show
  1. cognite/neat/_constants.py +35 -1
  2. cognite/neat/_graph/_shared.py +4 -0
  3. cognite/neat/_graph/extractors/__init__.py +5 -1
  4. cognite/neat/_graph/extractors/_base.py +32 -0
  5. cognite/neat/_graph/extractors/_classic_cdf/_base.py +128 -14
  6. cognite/neat/_graph/extractors/_classic_cdf/_classic.py +156 -12
  7. cognite/neat/_graph/extractors/_classic_cdf/_relationships.py +50 -12
  8. cognite/neat/_graph/extractors/_classic_cdf/_sequences.py +26 -1
  9. cognite/neat/_graph/extractors/_dms.py +196 -47
  10. cognite/neat/_graph/extractors/_dms_graph.py +199 -0
  11. cognite/neat/_graph/extractors/_mock_graph_generator.py +1 -1
  12. cognite/neat/_graph/extractors/_rdf_file.py +33 -5
  13. cognite/neat/_graph/loaders/__init__.py +1 -3
  14. cognite/neat/_graph/loaders/_rdf2dms.py +123 -19
  15. cognite/neat/_graph/queries/_base.py +140 -84
  16. cognite/neat/_graph/queries/_construct.py +2 -2
  17. cognite/neat/_graph/transformers/__init__.py +8 -1
  18. cognite/neat/_graph/transformers/_base.py +9 -1
  19. cognite/neat/_graph/transformers/_classic_cdf.py +90 -3
  20. cognite/neat/_graph/transformers/_rdfpath.py +3 -3
  21. cognite/neat/_graph/transformers/_value_type.py +106 -45
  22. cognite/neat/_issues/errors/_resources.py +1 -1
  23. cognite/neat/_issues/warnings/__init__.py +0 -2
  24. cognite/neat/_issues/warnings/_models.py +1 -1
  25. cognite/neat/_issues/warnings/_properties.py +0 -8
  26. cognite/neat/_rules/analysis/_base.py +1 -1
  27. cognite/neat/_rules/analysis/_information.py +14 -13
  28. cognite/neat/_rules/catalog/__init__.py +1 -0
  29. cognite/neat/_rules/catalog/classic_model.xlsx +0 -0
  30. cognite/neat/_rules/catalog/info-rules-imf.xlsx +0 -0
  31. cognite/neat/_rules/exporters/_rules2instance_template.py +3 -3
  32. cognite/neat/_rules/importers/__init__.py +3 -1
  33. cognite/neat/_rules/importers/_dms2rules.py +7 -5
  34. cognite/neat/_rules/importers/_dtdl2rules/spec.py +1 -2
  35. cognite/neat/_rules/importers/_rdf/__init__.py +2 -2
  36. cognite/neat/_rules/importers/_rdf/_base.py +2 -2
  37. cognite/neat/_rules/importers/_rdf/_inference2rules.py +242 -19
  38. cognite/neat/_rules/models/_base_rules.py +13 -15
  39. cognite/neat/_rules/models/_types.py +5 -0
  40. cognite/neat/_rules/models/dms/_rules.py +51 -10
  41. cognite/neat/_rules/models/dms/_rules_input.py +4 -0
  42. cognite/neat/_rules/models/information/_rules.py +48 -5
  43. cognite/neat/_rules/models/information/_rules_input.py +6 -1
  44. cognite/neat/_rules/models/mapping/_classic2core.py +4 -5
  45. cognite/neat/_rules/transformers/__init__.py +10 -0
  46. cognite/neat/_rules/transformers/_converters.py +300 -62
  47. cognite/neat/_session/_base.py +57 -10
  48. cognite/neat/_session/_drop.py +5 -1
  49. cognite/neat/_session/_inspect.py +3 -2
  50. cognite/neat/_session/_mapping.py +17 -6
  51. cognite/neat/_session/_prepare.py +0 -47
  52. cognite/neat/_session/_read.py +115 -10
  53. cognite/neat/_session/_set.py +27 -0
  54. cognite/neat/_session/_show.py +4 -4
  55. cognite/neat/_session/_state.py +12 -1
  56. cognite/neat/_session/_to.py +43 -2
  57. cognite/neat/_session/_wizard.py +1 -1
  58. cognite/neat/_session/exceptions.py +8 -3
  59. cognite/neat/_store/_graph_store.py +331 -136
  60. cognite/neat/_store/_rules_store.py +130 -1
  61. cognite/neat/_utils/auth.py +3 -1
  62. cognite/neat/_version.py +1 -1
  63. {cognite_neat-0.106.0.dist-info → cognite_neat-0.108.0.dist-info}/METADATA +2 -2
  64. {cognite_neat-0.106.0.dist-info → cognite_neat-0.108.0.dist-info}/RECORD +67 -65
  65. {cognite_neat-0.106.0.dist-info → cognite_neat-0.108.0.dist-info}/WHEEL +1 -1
  66. {cognite_neat-0.106.0.dist-info → cognite_neat-0.108.0.dist-info}/LICENSE +0 -0
  67. {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_.transformation.traversal.class_.prefix
39
- suffix = property_.transformation.traversal.class_.suffix
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_.transformation = RDFPath(traversal=traversal)
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, XSD, Graph, Namespace, URIRef
7
+ from rdflib import RDF, Literal, Namespace, URIRef
8
8
  from rdflib.query import ResultRow
9
9
 
10
- from cognite.neat._constants import UNKNOWN_TYPE
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 BaseTransformer, BaseTransformerStandardised, RowTransformationOutput
15
+ from ._base import BaseTransformerStandardised, RowTransformationOutput
17
16
 
18
17
 
19
- # TODO: Standardise
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
- _object_property_template: str = """SELECT ?s ?o WHERE{{
26
+ def __init__(self, unknown_type: URIRef | None = None) -> None:
27
+ self.unknown_type = unknown_type or NEAT.UnknownType
29
28
 
30
- ?s a <{subject_uri}> .
31
- ?s <{property_uri}> ?o .
32
- ?o a <{object_uri}> .
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
- _datatype_property_template: str = """SELECT ?s ?o WHERE {{
61
+ BIND(<{property_uri}> AS ?p)
37
62
 
38
- ?s a <{subject_uri}> .
39
- ?s <{property_uri}> ?o .
40
- FILTER (datatype(?o) = <{object_uri}>)
63
+ BIND(IF(isLiteral(?o), DATATYPE(?o),
64
+ IF(BOUND(?type),?type,
65
+ <{unknownType}>)) AS ?valueType)
41
66
 
42
- }}"""
67
+ }} """
43
68
 
44
- _unknown_property_template: str = """SELECT ?s ?o WHERE {{
69
+ return query.format(unknownType=self.unknown_type, subject_uri=type_, property_uri=property_)
45
70
 
46
- ?s a <{subject_uri}> .
47
- ?s <{property_uri}> ?o .
48
- FILTER NOT EXISTS {{ ?o a ?objectType }}
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 transform(self, graph: Graph) -> None:
52
- # handle multi value type object properties
53
- for subject_uri, property_uri, value_types in Queries(graph).multi_value_type_property():
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
- # Case 1: Unknown value type
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
- # Case 2: Datatype value type
66
- elif value_type_uri.startswith(str(XSD)):
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
- # Case 3: Object value type
70
- else:
71
- iterator = graph.query(self._object_property_template.format(**_args))
84
+ row_output.instances_modified_count += 1
72
85
 
73
- for s, o in iterator: # type: ignore [misc]
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_.transformation, RDFPath)
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_.transformation and isinstance(prop_.transformation.traversal, Hop) for prop_ in self.rules.properties
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_.transformation and isinstance(prop_.transformation.traversal, SelfReferenceProperty)
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_.transformation and isinstance(prop_.transformation.traversal, SelfReferenceProperty)
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.transformation)
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 neat_id_to_transformation_property_uri(self, property_neat_id: URIRef) -> URIRef | None:
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_.transformation
108
+ and property_.instance_source
108
109
  and isinstance(
109
- property_.transformation.traversal,
110
+ property_.instance_source.traversal,
110
111
  SingleProperty,
111
112
  )
112
113
  and (
113
- property_.transformation.traversal.property.prefix in self.rules.prefixes
114
- or property_.transformation.traversal.property.prefix == self.rules.metadata.prefix
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_.transformation.traversal.property.prefix == self.rules.metadata.prefix
120
- else self.rules.prefixes[property_.transformation.traversal.property.prefix]
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_.transformation.traversal.property.suffix]
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_.transformation).traversal.class_)
141
+ classes.append(cast(RDFPath, property_.instance_source).traversal.class_)
141
142
 
142
143
  return cast(ClassEntity, most_occurring_element(classes))
143
144
  else:
@@ -5,3 +5,4 @@ from pathlib import Path
5
5
  _CATALOG = Path(__file__).parent
6
6
  imf_attributes = _CATALOG / "info-rules-imf.xlsx"
7
7
  hello_world_pump = _CATALOG / "hello_world_pump.xlsx"
8
+ classic_model = _CATALOG / "classic_model.xlsx"
@@ -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
- user_models = cls._find_model_in_list(data_models, data_model_id)
119
- if len(user_models) == 0:
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
- user_model = user_models.latest_version()
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 = NeatClient(client).schema.retrieve_data_model(user_model)
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(user_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.graph,
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: