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.

Files changed (171) hide show
  1. cognite/neat/_version.py +1 -1
  2. cognite/neat/app/api/data_classes/rest.py +0 -19
  3. cognite/neat/app/api/explorer.py +6 -4
  4. cognite/neat/app/api/routers/configuration.py +1 -1
  5. cognite/neat/app/api/routers/crud.py +11 -21
  6. cognite/neat/app/api/routers/workflows.py +24 -94
  7. cognite/neat/app/ui/neat-app/build/asset-manifest.json +7 -7
  8. cognite/neat/app/ui/neat-app/build/index.html +1 -1
  9. cognite/neat/app/ui/neat-app/build/static/css/{main.38a62222.css → main.72e3d92e.css} +2 -2
  10. cognite/neat/app/ui/neat-app/build/static/css/main.72e3d92e.css.map +1 -0
  11. cognite/neat/app/ui/neat-app/build/static/js/main.5a52cf09.js +3 -0
  12. cognite/neat/app/ui/neat-app/build/static/js/{main.ec7f72e2.js.LICENSE.txt → main.5a52cf09.js.LICENSE.txt} +0 -9
  13. cognite/neat/app/ui/neat-app/build/static/js/main.5a52cf09.js.map +1 -0
  14. cognite/neat/config.py +44 -27
  15. cognite/neat/exceptions.py +6 -0
  16. cognite/neat/graph/extractors/_classic_cdf/_assets.py +21 -73
  17. cognite/neat/graph/extractors/_classic_cdf/_base.py +102 -0
  18. cognite/neat/graph/extractors/_classic_cdf/_events.py +46 -42
  19. cognite/neat/graph/extractors/_classic_cdf/_files.py +41 -45
  20. cognite/neat/graph/extractors/_classic_cdf/_labels.py +75 -52
  21. cognite/neat/graph/extractors/_classic_cdf/_relationships.py +49 -27
  22. cognite/neat/graph/extractors/_classic_cdf/_sequences.py +47 -50
  23. cognite/neat/graph/extractors/_classic_cdf/_timeseries.py +47 -49
  24. cognite/neat/graph/queries/_base.py +22 -29
  25. cognite/neat/graph/queries/_shared.py +1 -1
  26. cognite/neat/graph/stores/_base.py +24 -11
  27. cognite/neat/graph/transformers/_rdfpath.py +3 -2
  28. cognite/neat/issues.py +8 -0
  29. cognite/neat/rules/exporters/_rules2ontology.py +28 -20
  30. cognite/neat/rules/exporters/_validation.py +15 -21
  31. cognite/neat/rules/importers/_inference2rules.py +31 -35
  32. cognite/neat/rules/importers/_owl2rules/_owl2metadata.py +3 -7
  33. cognite/neat/rules/importers/_spreadsheet2rules.py +30 -27
  34. cognite/neat/rules/issues/dms.py +20 -0
  35. cognite/neat/rules/issues/importing.py +15 -0
  36. cognite/neat/rules/issues/ontology.py +298 -0
  37. cognite/neat/rules/issues/spreadsheet.py +48 -0
  38. cognite/neat/rules/issues/tables.py +72 -0
  39. cognite/neat/rules/models/_rdfpath.py +4 -4
  40. cognite/neat/rules/models/_types/_field.py +9 -19
  41. cognite/neat/rules/models/information/_rules.py +5 -4
  42. cognite/neat/utils/rdf_.py +17 -9
  43. cognite/neat/utils/regex_patterns.py +52 -0
  44. cognite/neat/workflows/steps/data_contracts.py +17 -43
  45. cognite/neat/workflows/steps/lib/current/graph_extractor.py +28 -24
  46. cognite/neat/workflows/steps/lib/current/graph_loader.py +4 -21
  47. cognite/neat/workflows/steps/lib/current/graph_store.py +18 -134
  48. cognite/neat/workflows/steps_registry.py +5 -7
  49. {cognite_neat-0.87.6.dist-info → cognite_neat-0.88.1.dist-info}/METADATA +2 -6
  50. cognite_neat-0.88.1.dist-info/RECORD +209 -0
  51. cognite/neat/app/api/routers/core.py +0 -91
  52. cognite/neat/app/api/routers/data_exploration.py +0 -336
  53. cognite/neat/app/api/routers/rules.py +0 -203
  54. cognite/neat/app/ui/neat-app/build/static/css/main.38a62222.css.map +0 -1
  55. cognite/neat/app/ui/neat-app/build/static/js/main.ec7f72e2.js +0 -3
  56. cognite/neat/app/ui/neat-app/build/static/js/main.ec7f72e2.js.map +0 -1
  57. cognite/neat/graph/stores/_oxrdflib.py +0 -247
  58. cognite/neat/legacy/__init__.py +0 -0
  59. cognite/neat/legacy/graph/__init__.py +0 -3
  60. cognite/neat/legacy/graph/examples/Knowledge-Graph-Nordic44-dirty.xml +0 -20182
  61. cognite/neat/legacy/graph/examples/Knowledge-Graph-Nordic44.xml +0 -20163
  62. cognite/neat/legacy/graph/examples/__init__.py +0 -10
  63. cognite/neat/legacy/graph/examples/skos-capturing-sheet-wind-topics.xlsx +0 -0
  64. cognite/neat/legacy/graph/exceptions.py +0 -90
  65. cognite/neat/legacy/graph/extractors/__init__.py +0 -6
  66. cognite/neat/legacy/graph/extractors/_base.py +0 -14
  67. cognite/neat/legacy/graph/extractors/_dexpi.py +0 -44
  68. cognite/neat/legacy/graph/extractors/_graph_capturing_sheet.py +0 -403
  69. cognite/neat/legacy/graph/extractors/_mock_graph_generator.py +0 -361
  70. cognite/neat/legacy/graph/loaders/__init__.py +0 -23
  71. cognite/neat/legacy/graph/loaders/_asset_loader.py +0 -511
  72. cognite/neat/legacy/graph/loaders/_base.py +0 -67
  73. cognite/neat/legacy/graph/loaders/_exceptions.py +0 -85
  74. cognite/neat/legacy/graph/loaders/core/__init__.py +0 -0
  75. cognite/neat/legacy/graph/loaders/core/labels.py +0 -58
  76. cognite/neat/legacy/graph/loaders/core/models.py +0 -136
  77. cognite/neat/legacy/graph/loaders/core/rdf_to_assets.py +0 -1046
  78. cognite/neat/legacy/graph/loaders/core/rdf_to_relationships.py +0 -559
  79. cognite/neat/legacy/graph/loaders/rdf_to_dms.py +0 -309
  80. cognite/neat/legacy/graph/loaders/validator.py +0 -87
  81. cognite/neat/legacy/graph/models.py +0 -6
  82. cognite/neat/legacy/graph/stores/__init__.py +0 -13
  83. cognite/neat/legacy/graph/stores/_base.py +0 -400
  84. cognite/neat/legacy/graph/stores/_graphdb_store.py +0 -52
  85. cognite/neat/legacy/graph/stores/_memory_store.py +0 -43
  86. cognite/neat/legacy/graph/stores/_oxigraph_store.py +0 -151
  87. cognite/neat/legacy/graph/stores/_oxrdflib.py +0 -247
  88. cognite/neat/legacy/graph/stores/_rdf_to_graph.py +0 -42
  89. cognite/neat/legacy/graph/transformations/__init__.py +0 -0
  90. cognite/neat/legacy/graph/transformations/entity_matcher.py +0 -101
  91. cognite/neat/legacy/graph/transformations/query_generator/__init__.py +0 -3
  92. cognite/neat/legacy/graph/transformations/query_generator/sparql.py +0 -575
  93. cognite/neat/legacy/graph/transformations/transformer.py +0 -322
  94. cognite/neat/legacy/rules/__init__.py +0 -0
  95. cognite/neat/legacy/rules/analysis.py +0 -231
  96. cognite/neat/legacy/rules/examples/Rules-Nordic44-to-graphql.xlsx +0 -0
  97. cognite/neat/legacy/rules/examples/Rules-Nordic44.xlsx +0 -0
  98. cognite/neat/legacy/rules/examples/__init__.py +0 -18
  99. cognite/neat/legacy/rules/examples/power-grid-containers.yaml +0 -124
  100. cognite/neat/legacy/rules/examples/power-grid-example.xlsx +0 -0
  101. cognite/neat/legacy/rules/examples/power-grid-model.yaml +0 -224
  102. cognite/neat/legacy/rules/examples/rules-template.xlsx +0 -0
  103. cognite/neat/legacy/rules/examples/sheet2cdf-transformation-rules.xlsx +0 -0
  104. cognite/neat/legacy/rules/examples/skos-rules.xlsx +0 -0
  105. cognite/neat/legacy/rules/examples/source-to-solution-mapping-rules.xlsx +0 -0
  106. cognite/neat/legacy/rules/examples/wind-energy.owl +0 -1511
  107. cognite/neat/legacy/rules/exceptions.py +0 -2972
  108. cognite/neat/legacy/rules/exporters/__init__.py +0 -20
  109. cognite/neat/legacy/rules/exporters/_base.py +0 -45
  110. cognite/neat/legacy/rules/exporters/_core/__init__.py +0 -5
  111. cognite/neat/legacy/rules/exporters/_core/rules2labels.py +0 -24
  112. cognite/neat/legacy/rules/exporters/_rules2dms.py +0 -885
  113. cognite/neat/legacy/rules/exporters/_rules2excel.py +0 -213
  114. cognite/neat/legacy/rules/exporters/_rules2graphql.py +0 -183
  115. cognite/neat/legacy/rules/exporters/_rules2ontology.py +0 -524
  116. cognite/neat/legacy/rules/exporters/_rules2pydantic_models.py +0 -748
  117. cognite/neat/legacy/rules/exporters/_rules2rules.py +0 -105
  118. cognite/neat/legacy/rules/exporters/_rules2triples.py +0 -38
  119. cognite/neat/legacy/rules/exporters/_validation.py +0 -146
  120. cognite/neat/legacy/rules/importers/__init__.py +0 -22
  121. cognite/neat/legacy/rules/importers/_base.py +0 -66
  122. cognite/neat/legacy/rules/importers/_dict2rules.py +0 -158
  123. cognite/neat/legacy/rules/importers/_dms2rules.py +0 -194
  124. cognite/neat/legacy/rules/importers/_graph2rules.py +0 -308
  125. cognite/neat/legacy/rules/importers/_json2rules.py +0 -39
  126. cognite/neat/legacy/rules/importers/_owl2rules/__init__.py +0 -3
  127. cognite/neat/legacy/rules/importers/_owl2rules/_owl2classes.py +0 -239
  128. cognite/neat/legacy/rules/importers/_owl2rules/_owl2metadata.py +0 -260
  129. cognite/neat/legacy/rules/importers/_owl2rules/_owl2properties.py +0 -217
  130. cognite/neat/legacy/rules/importers/_owl2rules/_owl2rules.py +0 -290
  131. cognite/neat/legacy/rules/importers/_spreadsheet2rules.py +0 -45
  132. cognite/neat/legacy/rules/importers/_xsd2rules.py +0 -20
  133. cognite/neat/legacy/rules/importers/_yaml2rules.py +0 -39
  134. cognite/neat/legacy/rules/models/__init__.py +0 -5
  135. cognite/neat/legacy/rules/models/_base.py +0 -151
  136. cognite/neat/legacy/rules/models/raw_rules.py +0 -316
  137. cognite/neat/legacy/rules/models/rdfpath.py +0 -237
  138. cognite/neat/legacy/rules/models/rules.py +0 -1289
  139. cognite/neat/legacy/rules/models/tables.py +0 -9
  140. cognite/neat/legacy/rules/models/value_types.py +0 -118
  141. cognite/neat/legacy/workflows/examples/Export_DMS/workflow.yaml +0 -89
  142. cognite/neat/legacy/workflows/examples/Export_Rules_to_Ontology/workflow.yaml +0 -152
  143. cognite/neat/legacy/workflows/examples/Extract_DEXPI_Graph_and_Export_Rules/workflow.yaml +0 -139
  144. cognite/neat/legacy/workflows/examples/Extract_RDF_Graph_and_Generate_Assets/workflow.yaml +0 -270
  145. cognite/neat/legacy/workflows/examples/Import_DMS/workflow.yaml +0 -65
  146. cognite/neat/legacy/workflows/examples/Ontology_to_Data_Model/workflow.yaml +0 -116
  147. cognite/neat/legacy/workflows/examples/Validate_Rules/workflow.yaml +0 -67
  148. cognite/neat/legacy/workflows/examples/Validate_Solution_Model/workflow.yaml +0 -64
  149. cognite/neat/legacy/workflows/examples/Visualize_Data_Model_Using_Mock_Graph/workflow.yaml +0 -95
  150. cognite/neat/legacy/workflows/examples/Visualize_Semantic_Data_Model/workflow.yaml +0 -111
  151. cognite/neat/rules/exceptions.py +0 -2972
  152. cognite/neat/rules/models/_types/_base.py +0 -16
  153. cognite/neat/workflows/examples/Export_Rules_to_Ontology/workflow.yaml +0 -152
  154. cognite/neat/workflows/examples/Extract_DEXPI_Graph_and_Export_Rules/workflow.yaml +0 -139
  155. cognite/neat/workflows/examples/Extract_RDF_Graph_and_Generate_Assets/workflow.yaml +0 -270
  156. cognite/neat/workflows/examples/Ontology_to_Data_Model/workflow.yaml +0 -116
  157. cognite/neat/workflows/migration/__init__.py +0 -0
  158. cognite/neat/workflows/migration/steps.py +0 -91
  159. cognite/neat/workflows/migration/wf_manifests.py +0 -33
  160. cognite/neat/workflows/steps/lib/legacy/__init__.py +0 -7
  161. cognite/neat/workflows/steps/lib/legacy/graph_contextualization.py +0 -82
  162. cognite/neat/workflows/steps/lib/legacy/graph_extractor.py +0 -746
  163. cognite/neat/workflows/steps/lib/legacy/graph_loader.py +0 -606
  164. cognite/neat/workflows/steps/lib/legacy/graph_store.py +0 -307
  165. cognite/neat/workflows/steps/lib/legacy/graph_transformer.py +0 -58
  166. cognite/neat/workflows/steps/lib/legacy/rules_exporter.py +0 -511
  167. cognite/neat/workflows/steps/lib/legacy/rules_importer.py +0 -612
  168. cognite_neat-0.87.6.dist-info/RECORD +0 -319
  169. {cognite_neat-0.87.6.dist-info → cognite_neat-0.88.1.dist-info}/LICENSE +0 -0
  170. {cognite_neat-0.87.6.dist-info → cognite_neat-0.88.1.dist-info}/WHEEL +0 -0
  171. {cognite_neat-0.87.6.dist-info → cognite_neat-0.88.1.dist-info}/entry_points.txt +0 -0
@@ -1,524 +0,0 @@
1
- import sys
2
- import warnings
3
- from abc import ABC
4
- from pathlib import Path
5
- from typing import ClassVar
6
-
7
- from pydantic import BaseModel, ConfigDict, ValidationInfo, field_validator
8
- from rdflib import DCTERMS, OWL, RDF, RDFS, XSD, BNode, Graph, Literal, Namespace, URIRef
9
- from rdflib.collection import Collection as GraphCollection
10
-
11
- from cognite.neat.legacy.rules import exceptions
12
- from cognite.neat.legacy.rules.analysis import to_class_property_pairs, to_property_dict
13
- from cognite.neat.legacy.rules.exporters._base import BaseExporter
14
- from cognite.neat.legacy.rules.exporters._validation import are_properties_redefined
15
- from cognite.neat.legacy.rules.models.rules import Class, Metadata, Property, Rules
16
- from cognite.neat.legacy.rules.models.value_types import XSD_VALUE_TYPE_MAPPINGS
17
- from cognite.neat.utils.auxiliary import generate_exception_report
18
- from cognite.neat.utils.rdf_ import remove_namespace_from_uri
19
-
20
- if sys.version_info >= (3, 11):
21
- from typing import Self
22
- else:
23
- from typing_extensions import Self
24
-
25
-
26
- class GraphExporter(BaseExporter[Graph], ABC):
27
- def _export_to_file(self, filepath: Path) -> None:
28
- self.export().serialize(destination=filepath)
29
-
30
-
31
- class OWLExporter(GraphExporter):
32
- def export(self) -> Graph:
33
- return Ontology.from_rules(self.rules).as_owl()
34
-
35
-
36
- class SHACLExporter(GraphExporter):
37
- def export(self) -> Graph:
38
- return Ontology.from_rules(self.rules).as_shacl()
39
-
40
-
41
- class SemanticDataModelExporter(GraphExporter):
42
- def export(self) -> Graph:
43
- return Ontology.from_rules(self.rules).as_semantic_data_model()
44
-
45
-
46
- class OntologyModel(BaseModel):
47
- model_config: ClassVar[ConfigDict] = ConfigDict(arbitrary_types_allowed=True, strict=False, extra="allow")
48
-
49
-
50
- class Ontology(OntologyModel):
51
- """
52
- Represents an ontology. Thi class is used to generate an OWL ontology from a set of transformation rules.
53
-
54
- Args:
55
- properties: A list of OWL properties.
56
- classes: A list of OWL classes.
57
- shapes: A list of SHACL node shapes.
58
- metadata: Metadata about the ontology.
59
- prefixes: A dictionary of prefixes and namespaces.
60
- """
61
-
62
- properties: list["OWLProperty"]
63
- classes: list["OWLClass"]
64
- shapes: list["SHACLNodeShape"]
65
- metadata: "OWLMetadata"
66
- prefixes: dict[str, Namespace]
67
-
68
- @classmethod
69
- def from_rules(cls, rules: Rules) -> Self:
70
- """
71
- Generates an ontology from a set of transformation rules.
72
-
73
- Args:
74
- transformation_rules: Instance of TransformationRules.
75
-
76
- Returns:
77
- An instance of Ontology.
78
- """
79
- properties_redefined, redefinition_warnings = are_properties_redefined(rules, return_report=True)
80
- if properties_redefined:
81
- raise exceptions.PropertiesDefinedMultipleTimes(report=generate_exception_report(redefinition_warnings))
82
-
83
- if rules.prefixes is None:
84
- raise exceptions.PrefixMissing()
85
-
86
- if rules.metadata.namespace is None:
87
- raise exceptions.MissingDataModelPrefixOrNamespace()
88
-
89
- return cls(
90
- properties=[
91
- OWLProperty.from_list_of_properties(definition, rules.metadata.namespace)
92
- for definition in to_property_dict(rules).values()
93
- ],
94
- classes=[
95
- OWLClass.from_class(definition, rules.metadata.namespace, rules.prefixes)
96
- for definition in rules.classes.values()
97
- ],
98
- shapes=[
99
- SHACLNodeShape.from_rules(
100
- rules.classes[class_],
101
- list(properties.values()),
102
- rules.metadata.namespace,
103
- )
104
- for class_, properties in to_class_property_pairs(rules).items()
105
- ],
106
- metadata=OWLMetadata(**rules.metadata.model_dump()),
107
- prefixes=rules.prefixes,
108
- )
109
-
110
- def as_shacl(self) -> Graph:
111
- """
112
- Generates a SHACL graph from the ontology.
113
-
114
- Returns:
115
- A SHACL graph.
116
- """
117
-
118
- shacl = Graph()
119
- shacl.bind(self.metadata.prefix, self.metadata.namespace)
120
- for prefix, namespace in self.prefixes.items():
121
- shacl.bind(prefix, namespace)
122
-
123
- for shape in self.shapes:
124
- for triple in shape.triples:
125
- shacl.add(triple) # type: ignore[arg-type]
126
-
127
- return shacl
128
-
129
- def as_owl(self) -> Graph:
130
- """
131
- Generates an OWL graph from the ontology.
132
-
133
- Returns:
134
- An OWL graph.
135
- """
136
- owl = Graph()
137
- owl.bind(self.metadata.prefix, self.metadata.namespace)
138
- for prefix, namespace in self.prefixes.items():
139
- owl.bind(prefix, namespace)
140
-
141
- if self.metadata.namespace is None:
142
- raise exceptions.MetadataSheetNamespaceNotDefined()
143
-
144
- owl.add((URIRef(self.metadata.namespace), RDF.type, OWL.Ontology))
145
- for property_ in self.properties:
146
- for triple in property_.triples:
147
- owl.add(triple) # type: ignore[arg-type]
148
-
149
- for class_ in self.classes:
150
- for triple in class_.triples:
151
- owl.add(triple) # type: ignore[arg-type]
152
-
153
- for triple in self.metadata.triples:
154
- owl.add(triple) # type: ignore[arg-type]
155
-
156
- return owl
157
-
158
- def as_semantic_data_model(self) -> Graph:
159
- return self.as_owl() + self.as_shacl()
160
-
161
- @property
162
- def owl_triples(self) -> list[tuple]:
163
- return list(self.as_owl())
164
-
165
- @property
166
- def shacl_triples(self) -> list[tuple]:
167
- return list(self.as_shacl())
168
-
169
- @property
170
- def triples(self) -> list[tuple]:
171
- return self.owl_triples + self.shacl_triples
172
-
173
- @property
174
- def ontology(self) -> str:
175
- return self.as_owl().serialize()
176
-
177
- @property
178
- def constraints(self) -> str:
179
- return self.as_shacl().serialize()
180
-
181
- @property
182
- def semantic_data_model(self) -> str:
183
- return (self.as_owl() + self.as_shacl()).serialize()
184
-
185
-
186
- class OWLMetadata(Metadata):
187
- @property
188
- def triples(self) -> list[tuple]:
189
- # Mandatory triples originating from Metadata mandatory fields
190
- if self.namespace is None:
191
- raise exceptions.MetadataSheetNamespaceNotDefined()
192
- triples: list[tuple] = [
193
- (URIRef(self.namespace), DCTERMS.hasVersion, Literal(self.version)),
194
- (URIRef(self.namespace), OWL.versionInfo, Literal(self.version)),
195
- (URIRef(self.namespace), RDFS.label, Literal(self.name)),
196
- (URIRef(self.namespace), DCTERMS.title, Literal(self.name)),
197
- (URIRef(self.namespace), DCTERMS.created, Literal(self.created, datatype=XSD.dateTime)),
198
- (URIRef(self.namespace), DCTERMS.description, Literal(self.description)),
199
- ]
200
- if isinstance(self.creator, list):
201
- triples.extend([(URIRef(self.namespace), DCTERMS.creator, Literal(creator)) for creator in self.creator])
202
- else:
203
- triples.append((URIRef(self.namespace), DCTERMS.creator, Literal(self.creator)))
204
-
205
- # Optional triples originating from Metadata optional fields
206
- if self.updated:
207
- triples.append((URIRef(self.namespace), DCTERMS.modified, Literal(self.updated, datatype=XSD.dateTime)))
208
- if self.rights:
209
- triples.append((URIRef(self.namespace), DCTERMS.rights, Literal(self.rights)))
210
-
211
- if self.contributor and isinstance(self.contributor, list):
212
- triples.extend(
213
- [
214
- (URIRef(self.namespace), DCTERMS.contributor, Literal(contributor))
215
- for contributor in self.contributor
216
- ]
217
- )
218
- elif self.contributor:
219
- triples.append((URIRef(self.namespace), DCTERMS.contributor, Literal(self.contributor)))
220
-
221
- return triples
222
-
223
-
224
- class OWLClass(OntologyModel):
225
- id_: URIRef
226
- type_: URIRef = OWL.Class
227
- label: str | None
228
- comment: str | None
229
- sub_class_of: list[URIRef] | None
230
- namespace: Namespace
231
-
232
- @classmethod
233
- def from_class(cls, definition: Class, namespace: Namespace, prefixes: dict) -> Self:
234
- if definition.parent_class and isinstance(definition.parent_class, list):
235
- sub_class_of = []
236
- for parent_class in definition.parent_class:
237
- try:
238
- sub_class_of.append(prefixes[parent_class.prefix][parent_class.suffix])
239
- except KeyError:
240
- sub_class_of.append(namespace[parent_class.suffix])
241
- else:
242
- sub_class_of = None
243
-
244
- return cls(
245
- id_=namespace[definition.class_id],
246
- label=definition.class_name,
247
- comment=definition.description,
248
- sub_class_of=sub_class_of,
249
- namespace=namespace,
250
- )
251
-
252
- @property
253
- def type_triples(self) -> list[tuple]:
254
- return [(self.id_, RDF.type, self.type_)]
255
-
256
- @property
257
- def label_triples(self) -> list[tuple]:
258
- return [(self.id_, RDFS.label, Literal(self.label))]
259
-
260
- @property
261
- def comment_triples(self) -> list[tuple]:
262
- return [(self.id_, RDFS.comment, Literal(self.comment))]
263
-
264
- @property
265
- def subclass_triples(self) -> list[tuple]:
266
- if self.sub_class_of:
267
- return [(self.id_, RDFS.subClassOf, sub_class_of) for sub_class_of in self.sub_class_of]
268
- else:
269
- return []
270
-
271
- @property
272
- def triples(self) -> list[tuple]:
273
- return self.type_triples + self.label_triples + self.comment_triples + self.subclass_triples
274
-
275
-
276
- class OWLProperty(OntologyModel):
277
- id_: URIRef
278
- type_: set[URIRef]
279
- label: set[str]
280
- comment: set[str]
281
- domain: set[URIRef]
282
- range_: set[URIRef]
283
- namespace: Namespace
284
-
285
- @staticmethod
286
- def same_property_id(definitions: list[Property]) -> bool:
287
- return len({definition.property_id for definition in definitions}) == 1
288
-
289
- @classmethod
290
- def from_list_of_properties(cls, definitions: list[Property], namespace: Namespace) -> "OWLProperty":
291
- """Here list of properties is a list of properties with the same id, but different definitions."""
292
-
293
- if not cls.same_property_id(definitions):
294
- raise exceptions.PropertyDefinitionsNotForSameProperty()
295
-
296
- owl_property = cls.model_construct(
297
- id_=namespace[definitions[0].property_id],
298
- namespace=namespace,
299
- label=set(),
300
- comment=set(),
301
- domain=set(),
302
- range_=set(),
303
- type_=set(),
304
- )
305
- for definition in definitions:
306
- owl_property.type_.add(OWL[definition.property_type])
307
- owl_property.range_.add(
308
- XSD[definition.expected_value_type.suffix]
309
- if definition.expected_value_type.suffix in XSD_VALUE_TYPE_MAPPINGS
310
- else namespace[definition.expected_value_type.suffix]
311
- )
312
- owl_property.domain.add(namespace[definition.class_id])
313
-
314
- if definition.property_name:
315
- owl_property.label.add(definition.property_name)
316
- if definition.description:
317
- owl_property.comment.add(definition.description)
318
-
319
- return owl_property
320
-
321
- @field_validator("type_")
322
- def is_multi_type(cls, v, info: ValidationInfo):
323
- if len(v) > 1:
324
- warnings.warn(
325
- exceptions.OntologyMultiTypeProperty(
326
- remove_namespace_from_uri(info.data["id_"]), [remove_namespace_from_uri(t) for t in v]
327
- ).message,
328
- category=exceptions.OntologyMultiTypeProperty,
329
- stacklevel=2,
330
- )
331
- return v
332
-
333
- @field_validator("range_")
334
- def is_multi_range(cls, v, info: ValidationInfo):
335
- if len(v) > 1:
336
- warnings.warn(
337
- exceptions.OntologyMultiRangeProperty(
338
- remove_namespace_from_uri(info.data["id_"]), [remove_namespace_from_uri(t) for t in v]
339
- ).message,
340
- category=exceptions.OntologyMultiRangeProperty,
341
- stacklevel=2,
342
- )
343
- return v
344
-
345
- @field_validator("domain")
346
- def is_multi_domain(cls, v, info: ValidationInfo):
347
- if len(v) > 1:
348
- warnings.warn(
349
- exceptions.OntologyMultiDomainProperty(
350
- remove_namespace_from_uri(info.data["id_"]), [remove_namespace_from_uri(t) for t in v]
351
- ).message,
352
- category=exceptions.OntologyMultiDomainProperty,
353
- stacklevel=2,
354
- )
355
- return v
356
-
357
- @field_validator("label")
358
- def has_multi_name(cls, v, info: ValidationInfo):
359
- if len(v) > 1:
360
- warnings.warn(
361
- exceptions.OntologyMultiLabeledProperty(remove_namespace_from_uri(info.data["id_"]), v).message,
362
- category=exceptions.OntologyMultiLabeledProperty,
363
- stacklevel=2,
364
- )
365
- return v
366
-
367
- @field_validator("comment")
368
- def has_multi_comment(cls, v, info: ValidationInfo):
369
- if len(v) > 1:
370
- warnings.warn(
371
- exceptions.OntologyMultiDefinitionProperty(remove_namespace_from_uri(info.data["id_"])).message,
372
- category=exceptions.OntologyMultiDefinitionProperty,
373
- stacklevel=2,
374
- )
375
- return v
376
-
377
- @property
378
- def domain_triples(self) -> list[tuple]:
379
- triples: list[tuple] = []
380
- if len(self.domain) == 1:
381
- triples.append((self.id_, RDFS.domain, next(iter(self.domain))))
382
- else:
383
- _graph = Graph()
384
- b_union = BNode()
385
- b_domain = BNode()
386
- _graph.add((self.id_, RDFS.domain, b_domain))
387
- _graph.add((b_domain, OWL.unionOf, b_union))
388
- _graph.add((b_domain, RDF.type, OWL.Class))
389
- _ = GraphCollection(_graph, b_union, list(self.domain))
390
- triples.extend(list(_graph))
391
- return triples
392
-
393
- @property
394
- def range_triples(self) -> list[tuple]:
395
- triples: list[tuple] = []
396
- if len(self.range_) == 1:
397
- triples.append((self.id_, RDFS.range, next(iter(self.range_))))
398
- else:
399
- _graph = Graph()
400
- b_union = BNode()
401
- b_range = BNode()
402
- _graph.add((self.id_, RDFS.range, b_range))
403
- _graph.add((b_range, OWL.unionOf, b_union))
404
- _graph.add((b_range, RDF.type, OWL.Class))
405
- _graph.add((b_range, OWL.unionOf, b_union))
406
- _graph.add((b_range, RDF.type, OWL.Class))
407
- _ = GraphCollection(_graph, b_union, list(self.range_))
408
- triples.extend(list(_graph))
409
- return triples
410
-
411
- @property
412
- def type_triples(self) -> list[tuple]:
413
- return [(self.id_, RDF.type, type_) for type_ in self.type_]
414
-
415
- @property
416
- def label_triples(self) -> list[tuple]:
417
- label = list(filter(None, self.label))
418
- return [(self.id_, RDFS.label, Literal(label[0] if label else self.id_))]
419
-
420
- @property
421
- def comment_triples(self) -> list[tuple]:
422
- return [(self.id_, RDFS.comment, Literal("\n".join(filter(None, self.comment))))]
423
-
424
- @property
425
- def triples(self) -> list[tuple]:
426
- return self.type_triples + self.label_triples + self.comment_triples + self.domain_triples + self.range_triples
427
-
428
-
429
- SHACL = Namespace("http://www.w3.org/ns/shacl#")
430
-
431
-
432
- class SHACLNodeShape(OntologyModel):
433
- id_: URIRef
434
- type_: URIRef = SHACL.NodeShape
435
- target_class: URIRef
436
- property_shapes: list["SHACLPropertyShape"]
437
- namespace: Namespace
438
-
439
- @property
440
- def type_triples(self) -> list[tuple]:
441
- return [(self.id_, RDF.type, self.type_)]
442
-
443
- @property
444
- def target_class_triples(self) -> list[tuple]:
445
- return [(self.id_, SHACL.targetClass, self.target_class)]
446
-
447
- @property
448
- def property_shapes_triples(self) -> list[tuple]:
449
- triples: list[tuple] = []
450
- for property_shape in self.property_shapes:
451
- triples.append((self.id_, SHACL.property, property_shape.id_))
452
- triples.extend(property_shape.triples)
453
- return triples
454
-
455
- @property
456
- def triples(self) -> list[tuple]:
457
- return self.type_triples + self.target_class_triples + self.property_shapes_triples
458
-
459
- @classmethod
460
- def from_rules(
461
- cls, class_definition: Class, property_definitions: list[Property], namespace: Namespace
462
- ) -> "SHACLNodeShape":
463
- return cls(
464
- id_=namespace[f"{class_definition.class_id}Shape"],
465
- target_class=namespace[class_definition.class_id],
466
- property_shapes=[SHACLPropertyShape.from_property(prop, namespace) for prop in property_definitions],
467
- namespace=namespace,
468
- )
469
-
470
-
471
- class SHACLPropertyShape(OntologyModel):
472
- id_: BNode
473
- type_: URIRef = SHACL.property
474
- path: URIRef # URIRef to property in OWL
475
- node_kind: URIRef # SHACL.IRI or SHACL.Literal
476
- expected_value_type: URIRef
477
- min_count: int | None
478
- max_count: int | None
479
- namespace: Namespace
480
-
481
- @property
482
- def path_triples(self) -> list[tuple]:
483
- return [(self.id_, SHACL.path, self.path)]
484
-
485
- @property
486
- def node_kind_triples(self) -> list[tuple]:
487
- triples: list[tuple] = [(self.id_, SHACL.nodeKind, self.node_kind)]
488
-
489
- if self.node_kind == SHACL.Literal:
490
- triples.append((self.id_, SHACL.datatype, self.expected_value_type))
491
- else:
492
- triples.append((self.id_, SHACL.node, self.expected_value_type))
493
-
494
- return triples
495
-
496
- @property
497
- def cardinality_triples(self) -> list[tuple]:
498
- triples: list[tuple] = []
499
- if self.min_count:
500
- triples.append((self.id_, SHACL.minCount, Literal(self.min_count)))
501
- if self.max_count:
502
- triples.append((self.id_, SHACL.maxCount, Literal(self.max_count)))
503
-
504
- return triples
505
-
506
- @property
507
- def triples(self) -> list[tuple]:
508
- return self.path_triples + self.node_kind_triples + self.cardinality_triples
509
-
510
- @classmethod
511
- def from_property(cls, definition: Property, namespace: Namespace) -> "SHACLPropertyShape":
512
- return cls(
513
- id_=BNode(),
514
- path=namespace[definition.property_id],
515
- node_kind=SHACL.IRI if definition.property_type == "ObjectProperty" else SHACL.Literal,
516
- expected_value_type=(
517
- namespace[f"{definition.expected_value_type.suffix}Shape"]
518
- if definition.property_type == "ObjectProperty"
519
- else XSD[definition.expected_value_type.suffix]
520
- ),
521
- min_count=definition.min_count,
522
- max_count=definition.max_count,
523
- namespace=namespace,
524
- )