cognite-neat 0.123.2__py3-none-any.whl → 0.123.4__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.
cognite/neat/_version.py CHANGED
@@ -1,2 +1,2 @@
1
- __version__ = "0.123.2"
1
+ __version__ = "0.123.4"
2
2
  __engine__ = "^2.0.4"
@@ -1,31 +1,21 @@
1
1
  from ._base import BaseImporter
2
2
  from ._dict2data_model import DictImporter
3
3
  from ._dms2data_model import DMSImporter
4
- from ._dtdl2data_model import DTDLImporter
5
- from ._rdf import IMFImporter, InferenceImporter, OWLImporter, SubclassInferenceImporter
4
+ from ._rdf import InferenceImporter, OWLImporter, SubclassInferenceImporter
6
5
  from ._spreadsheet2data_model import ExcelImporter
7
6
 
8
7
  __all__ = [
9
8
  "BaseImporter",
10
9
  "DMSImporter",
11
- "DTDLImporter",
12
10
  "DictImporter",
13
11
  "ExcelImporter",
14
- "IMFImporter",
15
12
  "InferenceImporter",
16
13
  "OWLImporter",
17
14
  "SubclassInferenceImporter",
18
15
  ]
19
16
 
20
17
  DataModelImporters = (
21
- OWLImporter
22
- | IMFImporter
23
- | DMSImporter
24
- | ExcelImporter
25
- | DTDLImporter
26
- | DictImporter
27
- | InferenceImporter
28
- | SubclassInferenceImporter
18
+ OWLImporter | DMSImporter | ExcelImporter | DictImporter | InferenceImporter | SubclassInferenceImporter
29
19
  )
30
20
 
31
21
 
@@ -1,5 +1,4 @@
1
- from ._imf2data_model import IMFImporter
2
1
  from ._inference2rdata_model import InferenceImporter, SubclassInferenceImporter
3
2
  from ._owl2data_model import OWLImporter
4
3
 
5
- __all__ = ["IMFImporter", "InferenceImporter", "OWLImporter", "SubclassInferenceImporter"]
4
+ __all__ = ["InferenceImporter", "OWLImporter", "SubclassInferenceImporter"]
@@ -826,29 +826,6 @@ class RDFReadAPI(BaseReadAPI):
826
826
  importer = importers.OWLImporter.from_file(reader.materialize_path(), source_name=f"file {reader!s}")
827
827
  return self._state.data_model_import(importer)
828
828
 
829
- def imf(self, io: Any) -> IssueList:
830
- """Reads IMF Types provided as SHACL shapes into NeatSession.
831
-
832
- Args:
833
- io: file path or url to the IMF file
834
-
835
- Example:
836
- ```python
837
- neat.read.rdf.imf("url_or_path_to_imf_source")
838
- ```
839
- """
840
- warnings.filterwarnings("default")
841
- ExperimentalFlags.imf_read.warn()
842
-
843
- self._state._raise_exception_if_condition_not_met(
844
- "Read IMF file",
845
- empty_data_model_store_required=True,
846
- )
847
-
848
- reader = NeatReader.create(io)
849
- importer = importers.IMFImporter.from_file(reader.materialize_path(), source_name=f"file {reader!s}")
850
- return self._state.data_model_import(importer)
851
-
852
829
  def instances(self, io: Any) -> IssueList:
853
830
  self._state._raise_exception_if_condition_not_met(
854
831
  "Read RDF Instances",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cognite-neat
3
- Version: 0.123.2
3
+ Version: 0.123.4
4
4
  Summary: Knowledge graph transformation
5
5
  Project-URL: Documentation, https://cognite-neat.readthedocs-hosted.com/
6
6
  Project-URL: Homepage, https://cognite-neat.readthedocs-hosted.com/
@@ -1,5 +1,5 @@
1
1
  cognite/neat/__init__.py,sha256=12StS1dzH9_MElqxGvLWrNsxCJl9Hv8A2a9D0E5OD_U,193
2
- cognite/neat/_version.py,sha256=HP2O0I_4JuG1TczHFazc53TQqD0Z8qh9R2SVWsXmlSQ,46
2
+ cognite/neat/_version.py,sha256=8hU8Ii91v2mPVi02JvAjqdizS1HMfV4lF6LA_zsFYGc,46
3
3
  cognite/neat/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  cognite/neat/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  cognite/neat/core/_config.py,sha256=WT1BS8uADcFvGoUYOOfwFOVq_VBl472TisdoA3wLick,280
@@ -34,20 +34,14 @@ cognite/neat/core/_data_model/exporters/_data_model2excel.py,sha256=mRVJzUCEWfm2
34
34
  cognite/neat/core/_data_model/exporters/_data_model2instance_template.py,sha256=9k8A70b1paeOHjvJRtbl6Xror1GD8AIMdo3cCx5aejE,6103
35
35
  cognite/neat/core/_data_model/exporters/_data_model2ontology.py,sha256=YrLTwPAvOOyLFHFJaNs4I82HCp1llJnkF1BRdoIQMck,23409
36
36
  cognite/neat/core/_data_model/exporters/_data_model2yaml.py,sha256=1dlb-v4sV8BArnX_6J4wpjQT7r-FinFAvoPDoMNkHYw,3284
37
- cognite/neat/core/_data_model/importers/__init__.py,sha256=ipImLDSse0vAHX4AWvtPI-LnnkIPajA4mwuEvpSXPT0,1336
37
+ cognite/neat/core/_data_model/importers/__init__.py,sha256=5KqFRDz69FlXRcmqu7ejQl3YVXrpLXx-Q-HpwAeDbfA,1184
38
38
  cognite/neat/core/_data_model/importers/_base.py,sha256=pKe2OK86Wdj6CTj5bUgjY33ejZhRfD2eJbjcCapHD58,2013
39
39
  cognite/neat/core/_data_model/importers/_base_file_reader.py,sha256=m7CwMujEybYMfHWbTQOb7wBvLl2X1TmROkPelJMSaDA,1621
40
40
  cognite/neat/core/_data_model/importers/_dict2data_model.py,sha256=-1zmo8JkxJ9qiWuC7sUH7oSlpnPPKTMxZtm4WrRPO5A,4709
41
41
  cognite/neat/core/_data_model/importers/_dms2data_model.py,sha256=1luEyqEu51rNcFcEh-MjTnUY_5mnQU0761MDVHOuteo,29132
42
42
  cognite/neat/core/_data_model/importers/_spreadsheet2data_model.py,sha256=2QqrxQ9AI3LT9toH_gryIR52UecMsR-v44ljXedDCp4,11972
43
- cognite/neat/core/_data_model/importers/_dtdl2data_model/__init__.py,sha256=CNR-sUihs2mnR1bPMKs3j3L4ds3vFTsrl6YycExZTfU,68
44
- cognite/neat/core/_data_model/importers/_dtdl2data_model/_unit_lookup.py,sha256=wW4saKva61Q_i17guY0dc4OseJDQfqHy_QZBtm0OD6g,12134
45
- cognite/neat/core/_data_model/importers/_dtdl2data_model/dtdl_converter.py,sha256=mjouy5XQCJoybUkCnEoZFrFtWBQrBQRPIM4DwfMDUkw,11879
46
- cognite/neat/core/_data_model/importers/_dtdl2data_model/dtdl_importer.py,sha256=t5EkawmYPuQ-dJ1J-IhqhdX_CkaCwQLQDAcpmx7QdS0,6288
47
- cognite/neat/core/_data_model/importers/_dtdl2data_model/spec.py,sha256=HnKUZbp42pl4DSexo0N6t_20tsvlsxyHHnNak5SVgzg,12182
48
- cognite/neat/core/_data_model/importers/_rdf/__init__.py,sha256=CYZd6Oj5PR2wv-eh4DYvKt4SDQgYRf1zW5QhN1Rg9AU,255
43
+ cognite/neat/core/_data_model/importers/_rdf/__init__.py,sha256=1yOjV2PKCxwH7uCTXVZhSdxtn5etmFX40cksvwtKcZ8,199
49
44
  cognite/neat/core/_data_model/importers/_rdf/_base.py,sha256=FKceKumKmhEGpMZvo1BwEewnUvfAsTF3Ax9fo1nxsGE,6020
50
- cognite/neat/core/_data_model/importers/_rdf/_imf2data_model.py,sha256=f5kAkv7-d5DtqzaACkyA-vLXrQ2xArwEd9zg7yX-MfA,3777
51
45
  cognite/neat/core/_data_model/importers/_rdf/_inference2rdata_model.py,sha256=PCgM9-qGSLlupN7tYCFLHjivgICtMiahNry1ub8JCYk,28934
52
46
  cognite/neat/core/_data_model/importers/_rdf/_owl2data_model.py,sha256=WmncZNpELeZnt6mdw6X8yWnr7XsFXZGfoVe5wTd0HH4,3438
53
47
  cognite/neat/core/_data_model/importers/_rdf/_shared.py,sha256=yB4BkupiPhizWSHNKdaspj3xE_6pKDiNG-_IHtTN1gI,5961
@@ -177,7 +171,7 @@ cognite/neat/session/_inspect.py,sha256=AESQd2SOidR_pDTFk5B_JdPnKZ5PNNskdAQBepH2
177
171
  cognite/neat/session/_mapping.py,sha256=ItEXhXo_8V3069hktHMxdpBsLNeTck3gZBvhlm12Oxw,2895
178
172
  cognite/neat/session/_plugin.py,sha256=diFvZUFRvY037iVy_HxnIGMSfrauOpwYCSvFEPOzchQ,2282
179
173
  cognite/neat/session/_prepare.py,sha256=pskEVNgcnVJVRvYKk5xI55V89vKDO_kgjszj5flY8Zs,12778
180
- cognite/neat/session/_read.py,sha256=sKtSw7Ub--vR6wfEexNzzaEHb0MZCHj3kzCEnF5wjf0,35349
174
+ cognite/neat/session/_read.py,sha256=rd1MeXPt_fS50WYrpM6UqDTKOQkDrOIn8TPS0WOVoSw,34607
181
175
  cognite/neat/session/_set.py,sha256=PU4lKI-LGtKFVyvdtfZkk-zLw9e_rnFHzuV9IyrOrTM,4593
182
176
  cognite/neat/session/_show.py,sha256=YLt6K4ukG1s_I_FhuVrIVPtw_btvvOL50Rwrx-vo7VQ,10743
183
177
  cognite/neat/session/_state.py,sha256=DLEm9wn3GtOuTGhy5-M1IK2v9qvLnTYEruWPidzAP_Q,6580
@@ -191,7 +185,7 @@ cognite/neat/session/engine/__init__.py,sha256=D3MxUorEs6-NtgoICqtZ8PISQrjrr4dvc
191
185
  cognite/neat/session/engine/_import.py,sha256=1QxA2_EK613lXYAHKQbZyw2yjo5P9XuiX4Z6_6-WMNQ,169
192
186
  cognite/neat/session/engine/_interface.py,sha256=3W-cYr493c_mW3P5O6MKN1xEQg3cA7NHR_ev3zdF9Vk,533
193
187
  cognite/neat/session/engine/_load.py,sha256=g52uYakQM03VqHt_RDHtpHso1-mFFifH5M4T2ScuH8A,5198
194
- cognite_neat-0.123.2.dist-info/METADATA,sha256=S0A0bAMepNWiOxj_BGAZL_nSetJnWlVdrgA8JOps3rI,9171
195
- cognite_neat-0.123.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
196
- cognite_neat-0.123.2.dist-info/licenses/LICENSE,sha256=W8VmvFia4WHa3Gqxq1Ygrq85McUNqIGDVgtdvzT-XqA,11351
197
- cognite_neat-0.123.2.dist-info/RECORD,,
188
+ cognite_neat-0.123.4.dist-info/METADATA,sha256=PxEsDokXeHFbmzASWwu40eFyMdFDUNDEqOw0X2zQ8Co,9171
189
+ cognite_neat-0.123.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
190
+ cognite_neat-0.123.4.dist-info/licenses/LICENSE,sha256=W8VmvFia4WHa3Gqxq1Ygrq85McUNqIGDVgtdvzT-XqA,11351
191
+ cognite_neat-0.123.4.dist-info/RECORD,,
@@ -1,3 +0,0 @@
1
- from .dtdl_importer import DTDLImporter
2
-
3
- __all__ = ["DTDLImporter"]
@@ -1,224 +0,0 @@
1
- from dataclasses import dataclass
2
-
3
-
4
- @dataclass
5
- class UnitEntry:
6
- semantic_type: str
7
- unit_type: str
8
- unit: str
9
-
10
-
11
- _UNIT_ENTRIES = [
12
- UnitEntry("Acceleration", "AccelerationUnit", "centimetrePerSecondSquared"),
13
- UnitEntry("Acceleration", "AccelerationUnit", "gForce"),
14
- UnitEntry("Acceleration", "AccelerationUnit", "metrePerSecondSquared"),
15
- UnitEntry("Angle", "AngleUnit", "degreeOfArc"),
16
- UnitEntry("Angle", "AngleUnit", "minuteOfArc"),
17
- UnitEntry("Angle", "AngleUnit", "radian"),
18
- UnitEntry("Angle", "AngleUnit", "secondOfArc"),
19
- UnitEntry("Angle", "AngleUnit", "turn"),
20
- UnitEntry("AngularAcceleration", "AngularAccelerationUnit", "radianPerSecondSquared"),
21
- UnitEntry("AngularVelocity", "AngularVelocityUnit", "degreePerSecond"),
22
- UnitEntry("AngularVelocity", "AngularVelocityUnit", "radianPerSecond"),
23
- UnitEntry("AngularVelocity", "AngularVelocityUnit", "revolutionPerMinute"),
24
- UnitEntry("AngularVelocity", "AngularVelocityUnit", "revolutionPerSecond"),
25
- UnitEntry("Area", "AreaUnit", "acre"),
26
- UnitEntry("Area", "AreaUnit", "hectare"),
27
- UnitEntry("Area", "AreaUnit", "squareCentimetre"),
28
- UnitEntry("Area", "AreaUnit", "squareFoot"),
29
- UnitEntry("Area", "AreaUnit", "squareInch"),
30
- UnitEntry("Area", "AreaUnit", "squareKilometre"),
31
- UnitEntry("Area", "AreaUnit", "squareMetre"),
32
- UnitEntry("Area", "AreaUnit", "squareMillimetre"),
33
- UnitEntry("Capacitance", "CapacitanceUnit", "farad"),
34
- UnitEntry("Capacitance", "CapacitanceUnit", "microfarad"),
35
- UnitEntry("Capacitance", "CapacitanceUnit", "millifarad"),
36
- UnitEntry("Capacitance", "CapacitanceUnit", "nanofarad"),
37
- UnitEntry("Capacitance", "CapacitanceUnit", "picofarad"),
38
- UnitEntry("Current", "CurrentUnit", "ampere"),
39
- UnitEntry("Current", "CurrentUnit", "microampere"),
40
- UnitEntry("Current", "CurrentUnit", "milliampere"),
41
- UnitEntry("DataRate", "DataRateUnit", "bitPerSecond"),
42
- UnitEntry("DataRate", "DataRateUnit", "bytePerSecond"),
43
- UnitEntry("DataRate", "DataRateUnit", "exbibitPerSecond"),
44
- UnitEntry("DataRate", "DataRateUnit", "exbibytePerSecond"),
45
- UnitEntry("DataRate", "DataRateUnit", "gibibitPerSecond"),
46
- UnitEntry("DataRate", "DataRateUnit", "gibibytePerSecond"),
47
- UnitEntry("DataRate", "DataRateUnit", "kibibitPerSecond"),
48
- UnitEntry("DataRate", "DataRateUnit", "kibibytePerSecond"),
49
- UnitEntry("DataRate", "DataRateUnit", "mebibitPerSecond"),
50
- UnitEntry("DataRate", "DataRateUnit", "mebibytePerSecond"),
51
- UnitEntry("DataRate", "DataRateUnit", "tebibitPerSecond"),
52
- UnitEntry("DataRate", "DataRateUnit", "tebibytePerSecond"),
53
- UnitEntry("DataRate", "DataRateUnit", "yobibitPerSecond"),
54
- UnitEntry("DataRate", "DataRateUnit", "yobibytePerSecond"),
55
- UnitEntry("DataRate", "DataRateUnit", "zebibitPerSecond"),
56
- UnitEntry("DataRate", "DataRateUnit", "zebibytePerSecond"),
57
- UnitEntry("DataSize", "DataSizeUnit", "bit"),
58
- UnitEntry("DataSize", "DataSizeUnit", "byte"),
59
- UnitEntry("DataSize", "DataSizeUnit", "exbibit"),
60
- UnitEntry("DataSize", "DataSizeUnit", "exbibyte"),
61
- UnitEntry("DataSize", "DataSizeUnit", "gibibit"),
62
- UnitEntry("DataSize", "DataSizeUnit", "gibibyte"),
63
- UnitEntry("DataSize", "DataSizeUnit", "kibibit"),
64
- UnitEntry("DataSize", "DataSizeUnit", "kibibyte"),
65
- UnitEntry("DataSize", "DataSizeUnit", "mebibit"),
66
- UnitEntry("DataSize", "DataSizeUnit", "mebibyte"),
67
- UnitEntry("DataSize", "DataSizeUnit", "tebibit"),
68
- UnitEntry("DataSize", "DataSizeUnit", "tebibyte"),
69
- UnitEntry("DataSize", "DataSizeUnit", "yobibit"),
70
- UnitEntry("DataSize", "DataSizeUnit", "yobibyte"),
71
- UnitEntry("DataSize", "DataSizeUnit", "zebibit"),
72
- UnitEntry("DataSize", "DataSizeUnit", "zebibyte"),
73
- UnitEntry("Density", "DensityUnit", "gramPerCubicMetre"),
74
- UnitEntry("Density", "DensityUnit", "kilogramPerCubicMetre"),
75
- UnitEntry("Distance", "LengthUnit", "astronomicalUnit"),
76
- UnitEntry("Distance", "LengthUnit", "centimetre"),
77
- UnitEntry("Distance", "LengthUnit", "foot"),
78
- UnitEntry("Distance", "LengthUnit", "inch"),
79
- UnitEntry("Distance", "LengthUnit", "kilometre"),
80
- UnitEntry("Distance", "LengthUnit", "metre"),
81
- UnitEntry("Distance", "LengthUnit", "micrometre"),
82
- UnitEntry("Distance", "LengthUnit", "mile"),
83
- UnitEntry("Distance", "LengthUnit", "millimetre"),
84
- UnitEntry("Distance", "LengthUnit", "nanometre"),
85
- UnitEntry("Distance", "LengthUnit", "nauticalMile"),
86
- UnitEntry("ElectricCharge", "ChargeUnit", "coulomb"),
87
- UnitEntry("Energy", "EnergyUnit", "electronvolt"),
88
- UnitEntry("Energy", "EnergyUnit", "gigajoule"),
89
- UnitEntry("Energy", "EnergyUnit", "joule"),
90
- UnitEntry("Energy", "EnergyUnit", "kilojoule"),
91
- UnitEntry("Energy", "EnergyUnit", "kilowattHour"),
92
- UnitEntry("Energy", "EnergyUnit", "megaelectronvolt"),
93
- UnitEntry("Energy", "EnergyUnit", "megajoule"),
94
- UnitEntry("Force", "ForceUnit", "newton"),
95
- UnitEntry("Force", "ForceUnit", "ounce"),
96
- UnitEntry("Force", "ForceUnit", "pound"),
97
- UnitEntry("Force", "ForceUnit", "ton"),
98
- UnitEntry("Frequency", "FrequencyUnit", "gigahertz"),
99
- UnitEntry("Frequency", "FrequencyUnit", "hertz"),
100
- UnitEntry("Frequency", "FrequencyUnit", "kilohertz"),
101
- UnitEntry("Frequency", "FrequencyUnit", "megahertz"),
102
- UnitEntry("Humidity", "DensityUnit", "gramPerCubicMetre"),
103
- UnitEntry("Humidity", "DensityUnit", "kilogramPerCubicMetre"),
104
- UnitEntry("Illuminance", "IlluminanceUnit", "footcandle"),
105
- UnitEntry("Illuminance", "IlluminanceUnit", "lux"),
106
- UnitEntry("Inductance", "InductanceUnit", "henry"),
107
- UnitEntry("Inductance", "InductanceUnit", "microhenry"),
108
- UnitEntry("Inductance", "InductanceUnit", "millihenry"),
109
- UnitEntry("Latitude", "AngleUnit", "degreeOfArc"),
110
- UnitEntry("Latitude", "AngleUnit", "minuteOfArc"),
111
- UnitEntry("Latitude", "AngleUnit", "radian"),
112
- UnitEntry("Latitude", "AngleUnit", "secondOfArc"),
113
- UnitEntry("Latitude", "AngleUnit", "turn"),
114
- UnitEntry("Length", "LengthUnit", "astronomicalUnit"),
115
- UnitEntry("Length", "LengthUnit", "centimetre"),
116
- UnitEntry("Length", "LengthUnit", "foot"),
117
- UnitEntry("Length", "LengthUnit", "inch"),
118
- UnitEntry("Length", "LengthUnit", "kilometre"),
119
- UnitEntry("Length", "LengthUnit", "metre"),
120
- UnitEntry("Length", "LengthUnit", "micrometre"),
121
- UnitEntry("Length", "LengthUnit", "mile"),
122
- UnitEntry("Length", "LengthUnit", "millimetre"),
123
- UnitEntry("Length", "LengthUnit", "nanometre"),
124
- UnitEntry("Length", "LengthUnit", "nauticalMile"),
125
- UnitEntry("Longitude", "AngleUnit", "degreeOfArc"),
126
- UnitEntry("Longitude", "AngleUnit", "minuteOfArc"),
127
- UnitEntry("Longitude", "AngleUnit", "radian"),
128
- UnitEntry("Longitude", "AngleUnit", "secondOfArc"),
129
- UnitEntry("Longitude", "AngleUnit", "turn"),
130
- UnitEntry("Luminance", "LuminanceUnit", "candelaPerSquareMetre"),
131
- UnitEntry("Luminosity", "PowerUnit", "gigawatt"),
132
- UnitEntry("Luminosity", "PowerUnit", "horsepower"),
133
- UnitEntry("Luminosity", "PowerUnit", "kilowatt"),
134
- UnitEntry("Luminosity", "PowerUnit", "kilowattHourPerYear"),
135
- UnitEntry("Luminosity", "PowerUnit", "megawatt"),
136
- UnitEntry("Luminosity", "PowerUnit", "microwatt"),
137
- UnitEntry("Luminosity", "PowerUnit", "milliwatt"),
138
- UnitEntry("Luminosity", "PowerUnit", "watt"),
139
- UnitEntry("LuminousFlux", "LuminousFluxUnit", "lumen"),
140
- UnitEntry("LuminousIntensity", "LuminousIntensityUnit", "candela"),
141
- UnitEntry("MagneticFlux", "MagneticFluxUnit", "maxwell"),
142
- UnitEntry("MagneticFlux", "MagneticFluxUnit", "weber"),
143
- UnitEntry("MagneticInduction", "MagneticInductionUnit", "tesla"),
144
- UnitEntry("Mass", "MassUnit", "gram"),
145
- UnitEntry("Mass", "MassUnit", "kilogram"),
146
- UnitEntry("Mass", "MassUnit", "microgram"),
147
- UnitEntry("Mass", "MassUnit", "milligram"),
148
- UnitEntry("Mass", "MassUnit", "slug"),
149
- UnitEntry("Mass", "MassUnit", "tonne"),
150
- UnitEntry("MassFlowRate", "MassFlowRateUnit", "gramPerHour"),
151
- UnitEntry("MassFlowRate", "MassFlowRateUnit", "gramPerSecond"),
152
- UnitEntry("MassFlowRate", "MassFlowRateUnit", "kilogramPerHour"),
153
- UnitEntry("MassFlowRate", "MassFlowRateUnit", "kilogramPerSecond"),
154
- UnitEntry("Power", "PowerUnit", "gigawatt"),
155
- UnitEntry("Power", "PowerUnit", "horsepower"),
156
- UnitEntry("Power", "PowerUnit", "kilowatt"),
157
- UnitEntry("Power", "PowerUnit", "kilowattHour"),
158
- UnitEntry("Power", "PowerUnit", "megawatt"),
159
- UnitEntry("Power", "PowerUnit", "microwatt"),
160
- UnitEntry("Power", "PowerUnit", "milliwatt"),
161
- UnitEntry("Power", "PowerUnit", "watt"),
162
- UnitEntry("Pressure", "PressureUnit", "bar"),
163
- UnitEntry("Pressure", "PressureUnit", "inchesOfMercury"),
164
- UnitEntry("Pressure", "PressureUnit", "inchesOfWater"),
165
- UnitEntry("Pressure", "PressureUnit", "kilopascal"),
166
- UnitEntry("Pressure", "PressureUnit", "millibar"),
167
- UnitEntry("Pressure", "PressureUnit", "millimetresOfMercury"),
168
- UnitEntry("Pressure", "PressureUnit", "pascal"),
169
- UnitEntry("Pressure", "PressureUnit", "poundPerSquareInch"),
170
- UnitEntry("RelativeHumidity", "Unitless", "percent"),
171
- UnitEntry("RelativeHumidity", "Unitless", "unity"),
172
- UnitEntry("Resistance", "ResistanceUnit", "kiloohm"),
173
- UnitEntry("Resistance", "ResistanceUnit", "megaohm"),
174
- UnitEntry("Resistance", "ResistanceUnit", "milliohm"),
175
- UnitEntry("Resistance", "ResistanceUnit", "ohm"),
176
- UnitEntry("SoundPressure", "SoundPressureUnit", "bel"),
177
- UnitEntry("SoundPressure", "SoundPressureUnit", "decibel"),
178
- UnitEntry("Temperature", "TemperatureUnit", "degreeCelsius"),
179
- UnitEntry("Temperature", "TemperatureUnit", "degreeFahrenheit"),
180
- UnitEntry("Temperature", "TemperatureUnit", "kelvin"),
181
- UnitEntry("Thrust", "ForceUnit", "newton"),
182
- UnitEntry("Thrust", "ForceUnit", "ounce"),
183
- UnitEntry("Thrust", "ForceUnit", "pound"),
184
- UnitEntry("Thrust", "ForceUnit", "ton"),
185
- UnitEntry("TimeSpan", "TimeUnit", "day"),
186
- UnitEntry("TimeSpan", "TimeUnit", "hour"),
187
- UnitEntry("TimeSpan", "TimeUnit", "microsecond"),
188
- UnitEntry("TimeSpan", "TimeUnit", "millisecond"),
189
- UnitEntry("TimeSpan", "TimeUnit", "minute"),
190
- UnitEntry("TimeSpan", "TimeUnit", "nanosecond"),
191
- UnitEntry("TimeSpan", "TimeUnit", "second"),
192
- UnitEntry("TimeSpan", "TimeUnit", "year"),
193
- UnitEntry("Torque", "TorqueUnit", "newtonMetre"),
194
- UnitEntry("Velocity", "VelocityUnit", "centimetrePerSecond"),
195
- UnitEntry("Velocity", "VelocityUnit", "kilometrePerHour"),
196
- UnitEntry("Velocity", "VelocityUnit", "kilometrePerSecond"),
197
- UnitEntry("Velocity", "VelocityUnit", "knot"),
198
- UnitEntry("Velocity", "VelocityUnit", "metrePerHour"),
199
- UnitEntry("Velocity", "VelocityUnit", "metrePerSecond"),
200
- UnitEntry("Velocity", "VelocityUnit", "milePerHour"),
201
- UnitEntry("Velocity", "VelocityUnit", "milePerSecond"),
202
- UnitEntry("Voltage", "VoltageUnit", "kilovolt"),
203
- UnitEntry("Voltage", "VoltageUnit", "megavolt"),
204
- UnitEntry("Voltage", "VoltageUnit", "microvolt"),
205
- UnitEntry("Voltage", "VoltageUnit", "millivolt"),
206
- UnitEntry("Voltage", "VoltageUnit", "volt"),
207
- UnitEntry("Volume", "VolumeUnit", "cubicCentimetre"),
208
- UnitEntry("Volume", "VolumeUnit", "cubicFoot"),
209
- UnitEntry("Volume", "VolumeUnit", "cubicInch"),
210
- UnitEntry("Volume", "VolumeUnit", "cubicMetre"),
211
- UnitEntry("Volume", "VolumeUnit", "fluidOunce"),
212
- UnitEntry("Volume", "VolumeUnit", "gallon"),
213
- UnitEntry("Volume", "VolumeUnit", "litre"),
214
- UnitEntry("Volume", "VolumeUnit", "millilitre"),
215
- UnitEntry("VolumeFlowRate", "VolumeFlowRateUnit", "litrePerHour"),
216
- UnitEntry("VolumeFlowRate", "VolumeFlowRateUnit", "litrePerSecond"),
217
- UnitEntry("VolumeFlowRate", "VolumeFlowRateUnit", "millilitrePerHour"),
218
- UnitEntry("VolumeFlowRate", "VolumeFlowRateUnit", "millilitrePerSecond"),
219
- ]
220
-
221
- UNIT_TYPE_BY_SEMANTIC_TYPE = {entry.semantic_type: entry.unit_type for entry in _UNIT_ENTRIES}
222
- # This is a bit dangerous, as unit names are not unique across types
223
- # It is only used as a backup in the parsing of units.
224
- ENTRY_BY_UNIT = {entry.unit: entry for entry in _UNIT_ENTRIES}
@@ -1,320 +0,0 @@
1
- from collections import Counter
2
- from collections.abc import Callable, Sequence
3
-
4
- from cognite.neat.core._data_model.importers._dtdl2data_model.spec import (
5
- DTMI,
6
- Command,
7
- CommandV2,
8
- Component,
9
- DTDLBase,
10
- DTDLBaseWithName,
11
- Enum,
12
- Interface,
13
- Object,
14
- Property,
15
- PropertyV2,
16
- Relationship,
17
- Schema,
18
- Telemetry,
19
- TelemetryV2,
20
- )
21
- from cognite.neat.core._data_model.models.conceptual import (
22
- UnverifiedConcept,
23
- UnverifiedConceptualProperty,
24
- )
25
- from cognite.neat.core._data_model.models.data_types import (
26
- _DATA_TYPE_BY_NAME,
27
- DataType,
28
- Json,
29
- String,
30
- )
31
- from cognite.neat.core._data_model.models.entities import ConceptEntity
32
- from cognite.neat.core._issues import IssueList
33
- from cognite.neat.core._issues.errors import (
34
- PropertyTypeNotSupportedError,
35
- ResourceMissingIdentifierError,
36
- ResourceNotFoundError,
37
- )
38
- from cognite.neat.core._issues.warnings import (
39
- PropertyTypeNotSupportedWarning,
40
- ResourceTypeNotSupportedWarning,
41
- )
42
-
43
-
44
- class _DTDLConverter:
45
- def __init__(self, issues: IssueList | None = None) -> None:
46
- self.issues = IssueList(issues or [])
47
- self.properties: list[UnverifiedConceptualProperty] = []
48
- self.classes: list[UnverifiedConcept] = []
49
- self._item_by_id: dict[DTMI, DTDLBase] = {}
50
-
51
- self._method_by_type = {
52
- Interface: self.convert_interface, # type: ignore[dict-item]
53
- Property: self.convert_property, # type: ignore[dict-item]
54
- PropertyV2: self.convert_property, # type: ignore[dict-item]
55
- Relationship: self.convert_relationship, # type: ignore[dict-item]
56
- Object: self.convert_object, # type: ignore[dict-item]
57
- Telemetry: self.convert_telemetry, # type: ignore[dict-item]
58
- TelemetryV2: self.convert_telemetry, # type: ignore[dict-item]
59
- Command: self.convert_command, # type: ignore[dict-item]
60
- CommandV2: self.convert_command, # type: ignore[dict-item]
61
- Component: self.convert_component, # type: ignore[dict-item]
62
- }
63
-
64
- def get_most_common_prefix(self) -> str:
65
- if not self.classes:
66
- raise ValueError("No classes found")
67
- counted = Counter(
68
- class_.prefix
69
- for class_ in (cls_.concept for cls_ in self.classes)
70
- if isinstance(class_, ConceptEntity) and isinstance(class_.prefix, str)
71
- )
72
- if not counted:
73
- raise ValueError("No prefixes found")
74
- return counted.most_common(1)[0][0]
75
-
76
- def convert(self, items: Sequence[DTDLBase]) -> None:
77
- self._item_by_id.update({item.id_: item for item in items if item.id_ is not None})
78
- # Update schema objects which are reusable
79
- self._item_by_id.update(
80
- {
81
- schema.id_: schema
82
- for item in items
83
- if isinstance(item, Interface)
84
- for schema in item.schemas or []
85
- if isinstance(schema.id_, DTMI) and isinstance(schema, DTDLBase)
86
- }
87
- )
88
-
89
- for item in items:
90
- self.convert_item(item)
91
-
92
- def convert_item(self, item: DTDLBase, parent: str | None = None) -> None:
93
- # Bug in mypy https://github.com/python/mypy/issues/17478
94
- convert_method: Callable[[DTDLBase, str | None], None] | None = self._method_by_type.get(type(item)) # type: ignore[assignment]
95
- if convert_method is not None:
96
- convert_method(item, parent)
97
- else:
98
- self.issues.append(
99
- ResourceTypeNotSupportedWarning(
100
- item.identifier_with_fallback,
101
- item.type,
102
- ),
103
- )
104
-
105
- def convert_interface(self, item: Interface, _: str | None) -> None:
106
- class_ = UnverifiedConcept(
107
- concept=item.id_.as_concept_entity(),
108
- name=item.display_name,
109
- description=item.description,
110
- implements=[parent.as_concept_entity() for parent in item.extends or []] or None,
111
- )
112
- self.classes.append(class_)
113
- for sub_item_or_id in item.contents or []:
114
- if isinstance(sub_item_or_id, DTMI) and sub_item_or_id not in self._item_by_id:
115
- self.issues.append(
116
- PropertyTypeNotSupportedWarning(
117
- item.id_.model_dump() or item.display_name or "missing",
118
- item.type,
119
- sub_item_or_id.path[-1],
120
- ".".join(sub_item_or_id.path),
121
- )
122
- )
123
- elif isinstance(sub_item_or_id, DTMI):
124
- sub_item = self._item_by_id[sub_item_or_id]
125
- self.convert_item(sub_item, class_.concept_str)
126
- else:
127
- self.convert_item(sub_item_or_id, class_.concept_str)
128
- # interface.schema objects are handled in the convert method
129
-
130
- def convert_property(
131
- self, item: Property | Telemetry, parent: str | None, min_count: int | None = 0, max_count: int | None = 1
132
- ) -> None:
133
- if parent is None:
134
- self._missing_parent_warning(item)
135
- return None
136
- value_type = self.schema_to_value_type(item.schema_, item)
137
- if value_type is None:
138
- return None
139
-
140
- prop = UnverifiedConceptualProperty(
141
- concept=ConceptEntity.load(parent),
142
- property_=item.name,
143
- name=item.display_name,
144
- description=item.description,
145
- value_type=value_type,
146
- min_count=min_count,
147
- max_count=max_count,
148
- )
149
- self.properties.append(prop)
150
-
151
- def _missing_parent_warning(self, item: DTDLBaseWithName) -> None:
152
- self.issues.append(
153
- ResourceNotFoundError(
154
- "UNKNOWN",
155
- "parent",
156
- item.identifier_with_fallback,
157
- item.type,
158
- )
159
- )
160
-
161
- def convert_telemetry(self, item: Telemetry, parent: str | None) -> None:
162
- return self.convert_property(
163
- item,
164
- parent,
165
- )
166
-
167
- def convert_command(self, item: Command | CommandV2, parent: str | None) -> None:
168
- if parent is None:
169
- self._missing_parent_warning(item)
170
- return None
171
- if item.request is None:
172
- self.issues.append(
173
- ResourceTypeNotSupportedWarning[str](
174
- item.identifier_with_fallback,
175
- f"{item.type}.request",
176
- ),
177
- )
178
- return None
179
- if item.response is not None:
180
- # Currently, we do not know how to handle response
181
- self.issues.append(ResourceTypeNotSupportedWarning[str](f"{parent}.response", "Command.Response"))
182
- value_type = self.schema_to_value_type(item.request.schema_, item)
183
- if value_type is None:
184
- return
185
- prop = UnverifiedConceptualProperty(
186
- concept=ConceptEntity.load(parent),
187
- property_=item.name,
188
- name=item.display_name,
189
- description=item.description,
190
- value_type=value_type,
191
- min_count=0,
192
- max_count=1,
193
- )
194
- self.properties.append(prop)
195
-
196
- def convert_component(self, item: Component, parent: str | None) -> None:
197
- if parent is None:
198
- self._missing_parent_warning(item)
199
- return None
200
-
201
- value_type = self.schema_to_value_type(item.schema_, item)
202
- if value_type is None:
203
- return
204
- prop = UnverifiedConceptualProperty(
205
- concept=ConceptEntity.load(parent),
206
- property_=item.name,
207
- name=item.display_name,
208
- description=item.description,
209
- value_type=value_type,
210
- min_count=0,
211
- max_count=1,
212
- )
213
- self.properties.append(prop)
214
-
215
- def convert_relationship(self, item: Relationship, parent: str | None) -> None:
216
- if parent is None:
217
- self._missing_parent_warning(item)
218
- return None
219
- if item.target is not None:
220
- value_type: DataType | ConceptEntity
221
- if item.target in self._item_by_id:
222
- value_type = item.target.as_concept_entity()
223
- else:
224
- # Falling back to json
225
- self.issues.append(
226
- ResourceMissingIdentifierError(
227
- "unknown",
228
- item.target.model_dump(),
229
- )
230
- )
231
- value_type = Json()
232
-
233
- prop = UnverifiedConceptualProperty(
234
- concept=ConceptEntity.load(parent),
235
- property_=item.name,
236
- name=item.display_name,
237
- description=item.description,
238
- min_count=item.min_multiplicity or 0,
239
- max_count=item.max_multiplicity or 1,
240
- value_type=value_type,
241
- )
242
- self.properties.append(prop)
243
- elif item.properties is not None:
244
- for prop_ in item.properties or []:
245
- self.convert_property(prop_, parent, item.min_multiplicity, item.max_multiplicity)
246
-
247
- def convert_object(self, item: Object, _: str | None) -> None:
248
- if item.id_ is None:
249
- self.issues.append(
250
- ResourceMissingIdentifierError(
251
- resource_type=item.type,
252
- name=item.display_name,
253
- )
254
- )
255
- return None
256
-
257
- class_ = UnverifiedConcept(
258
- concept=item.id_.as_concept_entity(),
259
- name=item.display_name,
260
- description=item.description,
261
- )
262
- self.classes.append(class_)
263
-
264
- for field_ in item.fields or []:
265
- value_type = self.schema_to_value_type(field_.schema_, item)
266
- if value_type is None:
267
- continue
268
- prop = UnverifiedConceptualProperty(
269
- concept=class_.concept,
270
- name=field_.name,
271
- description=field_.description,
272
- property_=field_.name,
273
- value_type=value_type,
274
- min_count=0,
275
- max_count=1,
276
- )
277
- self.properties.append(prop)
278
-
279
- def schema_to_value_type(
280
- self, schema: Schema | Interface | DTMI | None, item: DTDLBase
281
- ) -> DataType | ConceptEntity | None:
282
- input_type = self._item_by_id.get(schema) if isinstance(schema, DTMI) else schema
283
-
284
- if isinstance(input_type, Enum):
285
- return String()
286
- elif isinstance(input_type, str) and input_type.casefold() in _DATA_TYPE_BY_NAME:
287
- return _DATA_TYPE_BY_NAME[input_type.casefold()]()
288
- elif isinstance(input_type, str):
289
- self.issues.append(
290
- PropertyTypeNotSupportedError(
291
- item.identifier_with_fallback,
292
- item.type,
293
- "schema",
294
- input_type,
295
- )
296
- )
297
- return None
298
- elif isinstance(input_type, Object | Interface):
299
- if input_type.id_ is None:
300
- self.issues.append(
301
- ResourceMissingIdentifierError(
302
- input_type.type,
303
- input_type.display_name,
304
- )
305
- )
306
- return Json()
307
- else:
308
- if isinstance(input_type, Object):
309
- self.convert_object(input_type, None)
310
- return input_type.id_.as_concept_entity()
311
- else:
312
- self.issues.append(
313
- PropertyTypeNotSupportedWarning(
314
- item.identifier_with_fallback,
315
- item.type, # type: ignore[arg-type]
316
- "schema",
317
- input_type.type if input_type else "missing",
318
- )
319
- )
320
- return None
@@ -1,155 +0,0 @@
1
- import json
2
- import zipfile
3
- from collections.abc import Iterable, Sequence
4
- from pathlib import Path
5
-
6
- from pydantic import ValidationError
7
-
8
- from cognite.neat.core._data_model._shared import ImportedDataModel
9
- from cognite.neat.core._data_model.importers._base import BaseImporter
10
- from cognite.neat.core._data_model.importers._dtdl2data_model.dtdl_converter import _DTDLConverter
11
- from cognite.neat.core._data_model.importers._dtdl2data_model.spec import (
12
- DTDL_CLS_BY_TYPE_BY_SPEC,
13
- DTDLBase,
14
- Interface,
15
- )
16
- from cognite.neat.core._data_model.models import UnverifiedConceptualDataModel
17
- from cognite.neat.core._data_model.models.conceptual import UnverifiedConceptualMetadata
18
- from cognite.neat.core._issues import IssueList, MultiValueError, NeatIssue
19
- from cognite.neat.core._issues.warnings import (
20
- FileItemNotSupportedWarning,
21
- FileMissingRequiredFieldWarning,
22
- FileReadWarning,
23
- FileTypeUnexpectedWarning,
24
- NeatValueWarning,
25
- )
26
- from cognite.neat.core._utils.text import humanize_collection, to_pascal_case
27
-
28
-
29
- class DTDLImporter(BaseImporter[UnverifiedConceptualDataModel]):
30
- """Importer from Azure Digital Twin - DTDL (Digital Twin Definition Language).
31
-
32
- This importer supports DTDL v2.0 and v3.0.
33
-
34
- It is recommended to use the class methods `from_directory` and `from_zip` to create an instance of this class.
35
-
36
- Args:
37
- items (Sequence[DTDLBase]): A sequence of DTDLBase objects.
38
- name (str, optional): Name of the data model. Defaults to None.
39
- read_issues (list[ValidationIssue], optional): A list of issues that occurred during reading. Defaults to None.
40
- schema (SchemaCompleteness, optional): Schema completeness. Defaults to SchemaCompleteness.partial.
41
-
42
- """
43
-
44
- def __init__(
45
- self,
46
- items: Sequence[DTDLBase],
47
- name: str | None = None,
48
- read_issues: list[NeatIssue] | None = None,
49
- ) -> None:
50
- self._items = items
51
- self.name = name
52
- self._read_issues = IssueList(read_issues)
53
-
54
- @classmethod
55
- def _from_file_content(cls, file_content: str, filepath: Path) -> Iterable[DTDLBase | NeatIssue]:
56
- raw = json.loads(file_content)
57
- if isinstance(raw, dict):
58
- if (context := raw.get("@context")) is None:
59
- yield FileMissingRequiredFieldWarning(filepath, "@context", "Missing '@context' key.")
60
- return
61
- raw_list = [raw]
62
- elif isinstance(raw, list):
63
- context = next(
64
- (entry["@context"] for entry in raw if isinstance(entry, dict) and "@context" in entry), None
65
- )
66
- if context is None:
67
- yield FileMissingRequiredFieldWarning(filepath, "@context", "Missing '@context' key.")
68
- return
69
- raw_list = raw
70
- else:
71
- yield FileTypeUnexpectedWarning(filepath, frozenset(["dict", "list"]), "Content is not an object or array.")
72
- return
73
-
74
- if isinstance(context, list):
75
- context = context[0]
76
- Interface.default_context = context
77
- spec_version = context.split(";")[1]
78
- try:
79
- cls_by_type = DTDL_CLS_BY_TYPE_BY_SPEC[spec_version]
80
- except KeyError:
81
- yield NeatValueWarning(
82
- f"Unsupported DTDL spec version: {spec_version} in {filepath}. "
83
- f"Supported versions are {humanize_collection(DTDL_CLS_BY_TYPE_BY_SPEC.keys())}."
84
- " The file will be skipped."
85
- )
86
- return
87
-
88
- for item in raw_list:
89
- if not (type_ := item.get("@type")):
90
- yield FileMissingRequiredFieldWarning(filepath, "@type", "Missing '@type' key.")
91
- continue
92
- cls_ = cls_by_type.get(type_)
93
- if cls_ is None:
94
- yield FileItemNotSupportedWarning(f"Unknown '@type' {type_}.", filepath=filepath)
95
- continue
96
- try:
97
- yield cls_.model_validate(item)
98
- except ValidationError as e:
99
- yield FileTypeUnexpectedWarning(filepath, frozenset([cls.__name__]), str(e))
100
- except Exception as e:
101
- yield FileReadWarning(filepath=filepath, reason=str(e))
102
-
103
- @classmethod
104
- def from_directory(cls, directory: Path) -> "DTDLImporter":
105
- items: list[DTDLBase] = []
106
- issues: list[NeatIssue] = []
107
- for filepath in directory.glob("**/*.json"):
108
- for item in cls._from_file_content(filepath.read_text(), filepath):
109
- if isinstance(item, NeatIssue):
110
- issues.append(item)
111
- else:
112
- items.append(item)
113
- return cls(items, directory.stem, read_issues=issues)
114
-
115
- @classmethod
116
- def from_zip(cls, zip_file: Path) -> "DTDLImporter":
117
- items: list[DTDLBase] = []
118
- issues: list[NeatIssue] = []
119
- with zipfile.ZipFile(zip_file) as z:
120
- for filepath in z.namelist():
121
- if filepath.endswith(".json"):
122
- for item in cls._from_file_content(z.read(filepath).decode(), Path(filepath)):
123
- if isinstance(item, NeatIssue):
124
- issues.append(item)
125
- else:
126
- items.append(item)
127
- return cls(items, zip_file.stem, read_issues=issues)
128
-
129
- def to_data_model(self) -> ImportedDataModel[UnverifiedConceptualDataModel]:
130
- converter = _DTDLConverter(self._read_issues)
131
-
132
- converter.convert(self._items)
133
-
134
- metadata = self._default_metadata()
135
-
136
- if self.name:
137
- metadata["name"] = to_pascal_case(self.name)
138
- try:
139
- most_common_prefix = converter.get_most_common_prefix()
140
- except ValueError:
141
- # No prefixes are defined so we just use the default prefix...
142
- ...
143
- else:
144
- metadata["space"] = most_common_prefix
145
-
146
- data_model = UnverifiedConceptualDataModel(
147
- metadata=UnverifiedConceptualMetadata.load(metadata),
148
- properties=converter.properties,
149
- concepts=converter.classes,
150
- )
151
- converter.issues.trigger_warnings()
152
- if converter.issues.has_errors:
153
- raise MultiValueError(converter.issues.errors)
154
-
155
- return ImportedDataModel(data_model, {})
@@ -1,363 +0,0 @@
1
- """
2
- This is a pydantic validation implementation of the DTDL v2 and v3 specifications.
3
-
4
- The specs are taken from:
5
-
6
- * Spec v2: https://github.com/Azure/opendigitaltwins-dtdl/blob/master/DTDL/v2/DTDL.v2.md
7
- * Spec v3: https://github.com/Azure/opendigitaltwins-dtdl/blob/master/DTDL/v3/DTDL.v3.md
8
- """
9
-
10
- import re
11
- import warnings
12
- from abc import ABC
13
- from typing import TYPE_CHECKING, Any, ClassVar, Literal, TypeAlias
14
-
15
- from pydantic import BaseModel, Field, field_validator, model_serializer, model_validator
16
- from pydantic.fields import FieldInfo
17
-
18
- from cognite.neat.core._data_model.models.entities import ConceptEntity
19
-
20
- if TYPE_CHECKING:
21
- from pydantic.type_adapter import IncEx
22
-
23
-
24
- # Regex is from the spec: https://github.com/Azure/opendigitaltwins-dtdl/blob/master/DTMI/README.md#validation-regular-expressions
25
- _DTMI_REGEX = (
26
- r"^dtmi:(?:_+[A-Za-z0-9]|[A-Za-z])(?:[A-Za-z0-9_]*[A-Za-z0-9])?(?::(?:_+[A-Za-z0-9]|[A-Za-z])"
27
- r"(?:[A-Za-z0-9_]*[A-Za-z0-9])?)*(?:;[1-9][0-9]{0,8}(?:\.[1-9][0-9]{0,5})?)?$"
28
- )
29
-
30
- _DTMI_COMPILED = re.compile(_DTMI_REGEX)
31
-
32
-
33
- class DTMI(BaseModel):
34
- scheme: ClassVar[str] = "dtmi"
35
- path: list[str]
36
- version: str
37
-
38
- def as_concept_entity(self) -> ConceptEntity:
39
- return ConceptEntity(prefix="_".join(self.path[:-1]), suffix=self.path[-1], version=self.version)
40
-
41
- def __hash__(self) -> int:
42
- return hash(self.to_string())
43
-
44
- def __repr__(self) -> str:
45
- return self.to_string()
46
-
47
- @model_validator(mode="before")
48
- def from_string(cls, value: Any) -> Any:
49
- if not isinstance(value, str):
50
- return value
51
- if not _DTMI_COMPILED.match(value):
52
- raise ValueError(f"Invalid DTMI {value}")
53
- value = value.removeprefix(cls.scheme + ":")
54
- path_str, version = value.split(";", 1)
55
- return dict(path=path_str.split(":"), version=version)
56
-
57
- @model_serializer
58
- def to_string(self) -> str:
59
- return f"{self.scheme}:{':'.join(self.path)};{self.version}"
60
-
61
- if TYPE_CHECKING:
62
- # Ensure type checkers works correctly, ref
63
- # https://docs.pydantic.dev/latest/concepts/serialization/#overriding-the-return-type-when-dumping-a-model
64
- def model_dump( # type: ignore[override]
65
- self,
66
- *,
67
- mode: Literal["json", "python"] | str = "python",
68
- include: IncEx | None = None,
69
- exclude: IncEx | None = None,
70
- by_alias: bool = False,
71
- exclude_unset: bool = False,
72
- exclude_defaults: bool = False,
73
- exclude_none: bool = False,
74
- round_trip: bool = False,
75
- warnings: bool = True,
76
- ) -> str: ...
77
-
78
-
79
- IRI: TypeAlias = str
80
-
81
-
82
- class Unit(BaseModel, ABC):
83
- value: str
84
- semantic_type: str | None = Field(None, alias="semanticType")
85
- unit_type: str | None = Field(None, alias="unitType")
86
-
87
- def __hash__(self) -> int:
88
- return hash(self.to_string())
89
-
90
- def __repr__(self) -> str:
91
- return self.to_string()
92
-
93
- @model_validator(mode="before")
94
- def from_string(cls, value: Any) -> Any:
95
- if not isinstance(value, str):
96
- return value
97
- from ._unit_lookup import ENTRY_BY_UNIT
98
-
99
- if value not in ENTRY_BY_UNIT:
100
- return dict(unit=value)
101
- entry = ENTRY_BY_UNIT[value]
102
- return dict(
103
- value=value,
104
- semanticType=entry.semantic_type,
105
- unitType=entry.unit_type,
106
- )
107
-
108
- @model_serializer
109
- def to_string(self) -> str:
110
- return self.value
111
-
112
- if TYPE_CHECKING:
113
- # Ensure type checkers works correctly, ref
114
- # https://docs.pydantic.dev/latest/concepts/serialization/#overriding-the-return-type-when-dumping-a-model
115
- def model_dump( # type: ignore[override]
116
- self,
117
- *,
118
- mode: Literal["json", "python"] | str = "python",
119
- include: IncEx | None = None,
120
- exclude: IncEx | None = None,
121
- by_alias: bool = False,
122
- exclude_unset: bool = False,
123
- exclude_defaults: bool = False,
124
- exclude_none: bool = False,
125
- round_trip: bool = False,
126
- warnings: bool = True,
127
- ) -> str: ...
128
-
129
-
130
- class DTDLBase(BaseModel, ABC):
131
- type: ClassVar[str]
132
- spec_version: ClassVar[frozenset[str]]
133
- id_: DTMI | None = Field(None, alias="@id")
134
- comment: str | None = None
135
- display_name: str | None = Field(None, alias="displayName")
136
- description: str | None = None
137
-
138
- @property
139
- def identifier_with_fallback(self) -> str:
140
- return (self.id_.model_dump() if self.id_ else self.display_name) or "MISSING"
141
-
142
-
143
- PrimitiveSchema: TypeAlias = Literal[
144
- "boolean", "date", "dateTime", "double", "duration", "float", "integer", "long", "string", "time"
145
- ]
146
-
147
-
148
- class DTDLBaseWithName(DTDLBase, ABC):
149
- name: str
150
-
151
-
152
- class DTDLBaseWithSchema(DTDLBaseWithName, ABC):
153
- schema_: "Schema | DTMI | None" = Field(None, alias="schema") # type: ignore[assignment]
154
-
155
- @field_validator("schema_", mode="before")
156
- def select_schema_type(cls, value: Any) -> Any:
157
- if isinstance(value, dict) and (type_ := value.get("@type")):
158
- context = Interface.default_context
159
- spec_version = context.rsplit(";", maxsplit=1)[1]
160
- try:
161
- cls_by_type = DTDL_CLS_BY_TYPE_BY_SPEC[spec_version]
162
- except KeyError:
163
- raise ValueError(f"DTDL Spec v{spec_version} is not supported: {context}") from None
164
- if isinstance(type_, str) and (cls_ := cls_by_type.get(type_)) is not None:
165
- return cls_.model_validate(value)
166
- elif isinstance(type_, list) and len(type_) == 2 and (cls_ := cls_by_type.get(type_[0])) is not None:
167
- # In the spec v2, the type of Telemetry and Property can be a list of two strings,
168
- # [[Telemetry|Property, "Semantic Type"].
169
- from ._unit_lookup import UNIT_TYPE_BY_SEMANTIC_TYPE
170
-
171
- if unit_type := UNIT_TYPE_BY_SEMANTIC_TYPE.get(type_[1]) and "unit" in value:
172
- value["unit"] = {
173
- "value": value["unit"],
174
- "semanticType": type_[1],
175
- "unitType": unit_type,
176
- }
177
- return cls_.model_validate(value)
178
- return value
179
-
180
-
181
- class DTDLField(DTDLBaseWithSchema):
182
- type = "Field"
183
- spec_version = frozenset(["2", "3"])
184
-
185
-
186
- class Object(DTDLBase):
187
- type = "Object"
188
- spec_version = frozenset(["2", "3"])
189
- fields: list[DTDLField] | None = None
190
-
191
-
192
- class MapKey(DTDLBaseWithName):
193
- type = "MapKey"
194
- spec_version = frozenset(["2", "3"])
195
- schema_: str = Field(alias="schema")
196
-
197
-
198
- class MapValue(DTDLBaseWithSchema):
199
- type = "MapValue"
200
- spec_version = frozenset(["2", "3"])
201
-
202
-
203
- class Map(DTDLBase):
204
- type = "Map"
205
- spec_version = frozenset(["2", "3"])
206
- map_key: MapKey = Field(alias="mapKey")
207
- map_value: MapValue = Field(alias="mapValue")
208
-
209
-
210
- class EnumValue(DTDLBaseWithName):
211
- type = "EnumValue"
212
- spec_version = frozenset(["2", "3"])
213
- enum_value: str = Field(alias="enumValue")
214
-
215
-
216
- class Enum(DTDLBase):
217
- type = "Enum"
218
- spec_version = frozenset(["2", "3"])
219
- enum_values: list[EnumValue] = Field(alias="enumValues")
220
- value_schema: PrimitiveSchema = Field(alias="valueSchema")
221
-
222
-
223
- class Array(DTDLBase):
224
- type = "Array"
225
- spec_version = frozenset(["2", "3"])
226
- element_schema: "Schema" = Field(alias="elementSchema")
227
-
228
-
229
- ComplexSchema: TypeAlias = Array | Enum | Map | Object
230
-
231
- Schema: TypeAlias = PrimitiveSchema | ComplexSchema
232
-
233
-
234
- class Component(DTDLBaseWithSchema):
235
- type = "Component"
236
- spec_version = frozenset(["2", "3"])
237
- schema_: "Interface | DTMI" = Field(alias="schema") # type: ignore[assignment]
238
-
239
-
240
- class Property(DTDLBaseWithSchema):
241
- type = "Property"
242
- spec_version = frozenset(["3"])
243
- writable: bool | None = None
244
-
245
-
246
- class PropertyV2(Property):
247
- spec_version = frozenset(["2"])
248
- unit: Unit | None = None
249
-
250
-
251
- class Relationship(DTDLBaseWithName):
252
- type = "Relationship"
253
- spec_version = frozenset(["2", "3"])
254
- min_multiplicity: int | None = Field(None, alias="minMultiplicity", le=0, ge=0)
255
- max_multiplicity: int | None = Field(None, alias="maxMultiplicity", ge=1)
256
- properties: list[Property] | None = None
257
- target: DTMI | None = None
258
- writable: bool | None = None
259
-
260
-
261
- class CommandRequest(DTDLBaseWithSchema):
262
- type = "CommandRequest"
263
- spec_version = frozenset(["3"])
264
-
265
-
266
- class CommandResponse(DTDLBaseWithSchema):
267
- type = "CommandResponse"
268
- spec_version = frozenset(["3"])
269
-
270
-
271
- class CommandPayload(DTDLBaseWithSchema):
272
- type = "CommandPayload"
273
- spec_version = frozenset(["2"])
274
-
275
-
276
- class Command(DTDLBaseWithSchema):
277
- type = "Command"
278
- spec_version = frozenset(["3"])
279
- request: CommandRequest | None = None
280
- response: CommandResponse | None = None
281
-
282
-
283
- class CommandV2(DTDLBaseWithSchema):
284
- type = "Command"
285
- spec_version = frozenset(["2"])
286
- request: CommandPayload | None = None
287
- response: CommandPayload | None = None
288
-
289
-
290
- class Telemetry(DTDLBaseWithSchema):
291
- type = "Telemetry"
292
- spec_version = frozenset(["3"])
293
-
294
-
295
- class TelemetryV2(Telemetry):
296
- spec_version = frozenset(["2"])
297
- unit: Unit | None = None
298
-
299
-
300
- class Interface(DTDLBase):
301
- type = "Interface"
302
- spec_version = frozenset(["2", "3"])
303
- default_context: ClassVar[IRI] = Field(
304
- "dtmi:dtdl:context;3",
305
- description="This can be set directly on the class to change the default context used when parsing a document.",
306
- )
307
- id_: DTMI = Field(alias="@id") # type: ignore[assignment]
308
- context: IRI | None = Field(alias="@context")
309
- extends: list[DTMI] | None = None
310
- contents: list[Command | Component | Property | Relationship | Telemetry | DTMI | CommandV2] | None = None
311
- schemas: list[Array | Enum | Map | Object] | None = None
312
-
313
- @field_validator("context", mode="before")
314
- def list_to_string(cls, value: Any) -> Any:
315
- if isinstance(value, list) and len(value) == 1:
316
- return value[0]
317
- return value
318
-
319
- @field_validator("contents", "schemas", mode="before")
320
- def select_content_type(cls, value: Any, info: Any) -> Any:
321
- if not isinstance(value, list):
322
- return value
323
- context = info.data.get("@context", cls.default_context)
324
- if isinstance(context, FieldInfo):
325
- context = context.default
326
- spec_version = context.rsplit(";", maxsplit=1)[1]
327
- try:
328
- cls_by_type = DTDL_CLS_BY_TYPE_BY_SPEC[spec_version]
329
- except KeyError:
330
- raise ValueError(f"DTDL Spec v{spec_version} is not supported: {context}") from None
331
- output: list[DTDLBase] = []
332
- for item in value:
333
- if isinstance(item, dict) and (type_ := item.get("@type")):
334
- if isinstance(type_, str) and (cls_ := cls_by_type.get(type_)) is not None:
335
- item = cls_.model_validate(item)
336
- elif isinstance(type_, list) and len(type_) == 2 and (cls_ := cls_by_type.get(type_[0])) is not None:
337
- # In the spec v2, the type of Telemetry and Property can be a list of two strings,
338
- # [[Telemetry|Property, "Semantic Type"].
339
- from ._unit_lookup import UNIT_TYPE_BY_SEMANTIC_TYPE
340
-
341
- if (unit_type := UNIT_TYPE_BY_SEMANTIC_TYPE.get(type_[1])) and (unit := item.get("unit")):
342
- item["unit"] = {
343
- "value": unit,
344
- "semanticType": type_[1],
345
- "unitType": unit_type,
346
- }
347
- item = cls_.model_validate(item)
348
- else:
349
- warnings.warn(f"Invalid item {item} in {cls.__name__}.contents", stacklevel=2)
350
- output.append(item)
351
- return output
352
-
353
-
354
- DTDL_CLS_BY_TYPE_BY_SPEC: dict[str, dict[str, type[DTDLBase]]] = {}
355
- to_check = list(DTDLBase.__subclasses__())
356
- while to_check:
357
- cls = to_check.pop()
358
- to_check.extend(cls.__subclasses__())
359
- if ABC in cls.__bases__:
360
- continue
361
- for spec in cls.spec_version:
362
- DTDL_CLS_BY_TYPE_BY_SPEC.setdefault(spec, {})[cls.type] = cls
363
- del cls, to_check, spec
@@ -1,98 +0,0 @@
1
- """This module performs importing of various formats to one of serializations for which
2
- there are loaders to data model pydantic class."""
3
-
4
- from cognite.neat.core._data_model.importers._rdf._base import BaseRDFImporter
5
- from cognite.neat.core._data_model.importers._rdf._shared import (
6
- parse_concepts,
7
- parse_properties,
8
- )
9
-
10
- CLASSES_QUERY = """
11
- SELECT ?concept ?name ?description ?implements
12
- WHERE {{
13
- VALUES ?type {{ imf:BlockType imf:TerminalType imf:AttributeType }}
14
- ?concept a ?type .
15
-
16
- OPTIONAL {{?concept rdfs:subClassOf ?parent }}.
17
- OPTIONAL {{?concept rdfs:label|skos:prefLabel ?name }}.
18
- OPTIONAL {{?concept rdfs:comment|skos:definition ?description}}.
19
-
20
-
21
- # Add imf:Attribute as parent class when no parent is found
22
- BIND(IF(!bound(?parent) && ?type = imf:AttributeType, imf:Attribute, ?parent) AS ?implements)
23
-
24
- # FILTERS
25
- FILTER (!isBlank(?concept))
26
- FILTER (!bound(?implements) || !isBlank(?implements))
27
-
28
- FILTER (!bound(?name) || LANG(?name) = "" || LANGMATCHES(LANG(?name), "{language}"))
29
- FILTER (!bound(?description) || LANG(?description) = "" || LANGMATCHES(LANG(?description), "{language}"))
30
- }}
31
- """
32
-
33
- PROPERTIES_QUERY = """
34
- SELECT ?concept ?property_ ?name ?description ?value_type ?min_count ?max_count ?default
35
- WHERE
36
- {{
37
- # CASE 1: Handling Blocks and Terminals
38
- {{
39
- VALUES ?type {{ imf:BlockType imf:TerminalType }}
40
- ?concept a ?type ;
41
- sh:property ?propertyShape .
42
- ?propertyShape sh:path ?property_ .
43
-
44
- OPTIONAL {{ ?property_ skos:prefLabel ?name . }}
45
- OPTIONAL {{ ?property_ skos:definition ?description . }}
46
- OPTIONAL {{ ?property_ rdfs:range ?range . }}
47
-
48
- OPTIONAL {{ ?propertyShape sh:minCount ?min_count . }}
49
- OPTIONAL {{ ?propertyShape sh:maxCount ?max_count . }}
50
- OPTIONAL {{ ?propertyShape sh:hasValue ?default . }}
51
- OPTIONAL {{ ?propertyShape sh:class | sh:qualifiedValueShape/sh:class ?valueShape . }}
52
- }}
53
-
54
- UNION
55
-
56
- # CASE 2: Handling Attributes
57
- {{
58
- ?concept a imf:AttributeType .
59
- BIND(xsd:anyURI AS ?valueShape)
60
- BIND(imf:predicate AS ?property_)
61
- ?concept ?property_ ?defaultURI .
62
- BIND(STR(?defaultURI) AS ?default)
63
-
64
- }}
65
-
66
- # Set the value type for the property based on sh:class, sh:qualifiedValueType or rdfs:range
67
- BIND(IF(BOUND(?valueShape), ?valueShape, IF(BOUND(?range) , ?range , ?valueShape)) AS ?value_type)
68
-
69
- FILTER (!isBlank(?property_))
70
- FILTER (!bound(?concept) || !isBlank(?concept))
71
- FILTER (!bound(?name) || LANG(?name) = "" || LANGMATCHES(LANG(?name), "{language}"))
72
- FILTER (!bound(?description) || LANG(?description) = "" || LANGMATCHES(LANG(?description), "{language}"))
73
- }}
74
- """
75
-
76
-
77
- class IMFImporter(BaseRDFImporter):
78
- """Convert IMF Types provided as SHACL shapes to unverified data model."""
79
-
80
- @property
81
- def description(self) -> str:
82
- return f"IMF Types {self.source_name} read as unverified data model"
83
-
84
- def _to_data_model_components(
85
- self,
86
- ) -> dict:
87
- classes, issue_list = parse_concepts(self.graph, CLASSES_QUERY, self.language, self.issue_list)
88
- self.issue_list = issue_list
89
- properties, issue_list = parse_properties(self.graph, PROPERTIES_QUERY, self.language, self.issue_list)
90
- self.issue_list = issue_list
91
-
92
- components = {
93
- "Metadata": self._metadata,
94
- "Concepts": list(classes.values()) if classes else [],
95
- "Properties": list(properties.values()) if properties else [],
96
- }
97
-
98
- return components