1
+ """Invert a transformation specification."""
2
+
1
3
import logging
2
4
import re
3
5
from copy import copy
19
21
logger = logging .getLogger (__name__ )
20
22
21
23
22
- class NonInvertibleSpecification (ValueError ):
23
- pass
24
+ class NonInvertibleSpecificationError (ValueError ):
25
+ """Error thrown when a specification is not invertible."""
24
26
25
27
26
28
@dataclass
@@ -40,7 +42,7 @@ class TransformationSpecificationInverter:
40
42
41
43
strict : bool = field (default = True )
42
44
43
- def invert (self , spec : TransformationSpecification ):
45
+ def invert (self , spec : TransformationSpecification ) -> TransformationSpecification :
44
46
"""
45
47
Invert a transformation specification.
46
48
@@ -57,7 +59,9 @@ def invert(self, spec: TransformationSpecification):
57
59
inverted_spec .enum_derivations [inverted_ed .name ] = inverted_ed
58
60
return inverted_spec
59
61
60
- def invert_class_derivation (self , cd : ClassDerivation , spec : TransformationSpecification ):
62
+ def invert_class_derivation (
63
+ self , cd : ClassDerivation , spec : TransformationSpecification
64
+ ) -> ClassDerivation :
61
65
"""
62
66
Invert a class derivation.
63
67
@@ -73,10 +77,13 @@ def invert_class_derivation(self, cd: ClassDerivation, spec: TransformationSpeci
73
77
if inverted_sd :
74
78
inverted_cd .slot_derivations [inverted_sd .name ] = inverted_sd
75
79
elif self .strict :
76
- raise NonInvertibleSpecification (f"Cannot invert slot derivation: { sd .name } " )
80
+ msg = f"Cannot invert slot derivation: { sd .name } "
81
+ raise NonInvertibleSpecificationError (msg )
77
82
return inverted_cd
78
83
79
- def invert_enum_derivation (self , ed : EnumDerivation , spec : TransformationSpecification ):
84
+ def invert_enum_derivation (
85
+ self , ed : EnumDerivation , spec : TransformationSpecification
86
+ ) -> EnumDerivation :
80
87
"""
81
88
Invert an enum derivation.
82
89
@@ -88,7 +95,8 @@ def invert_enum_derivation(self, ed: EnumDerivation, spec: TransformationSpecifi
88
95
name = ed .populated_from if ed .populated_from else ed .name , populated_from = ed .name
89
96
)
90
97
if inverted_ed .expr :
91
- raise NonInvertibleSpecification ("TODO: invert enum derivation with expression" )
98
+ msg = "TODO: invert enum derivation with expression"
99
+ raise NonInvertibleSpecificationError (msg )
92
100
for pv_deriv in ed .permissible_value_derivations .values ():
93
101
inverted_pv_deriv = PermissibleValueDerivation (
94
102
name = pv_deriv .populated_from if pv_deriv .populated_from else pv_deriv .name ,
@@ -116,15 +124,13 @@ def invert_slot_derivation(
116
124
if not self .strict :
117
125
return None
118
126
# TODO: add logic for reversible expressions
119
- raise NonInvertibleSpecification (
120
- f"Cannot invert expression { sd . expr } in slot derivation: { sd . name } "
121
- )
127
+ msg = f"Cannot invert expression { sd . expr } in slot derivation: { sd . name } "
128
+ raise NonInvertibleSpecificationError ( msg )
129
+
122
130
if not populated_from :
123
131
# use defaults. TODO: decide on semantics of defaults
124
132
populated_from = sd .name
125
- # raise NonInvertibleSpecification(f"No populate_from or expr in slot derivation: {sd.name}")
126
133
inverted_sd = SlotDerivation (name = populated_from , populated_from = sd .name )
127
- # source_cls_name = spec.class_derivations[cd.populated_from].name
128
134
source_cls_name = cd .populated_from
129
135
if (
130
136
source_cls_name is None or source_cls_name in self .source_schemaview .all_classes ()
@@ -133,7 +139,6 @@ def invert_slot_derivation(
133
139
else :
134
140
source_slot = None
135
141
if sd .range :
136
- # source_slot = self.source_schemaview.induced_slot(sd.populated_from, source_cls_name)
137
142
inverted_sd .range = source_slot .range
138
143
if source_slot .range in self .source_schemaview .all_classes ():
139
144
id_slot = self .source_schemaview .get_identifier_slot (
@@ -144,14 +149,13 @@ def invert_slot_derivation(
144
149
if source_slot and source_slot .multivalued :
145
150
if source_slot .inlined_as_list :
146
151
inverted_sd .cast_collection_as = CollectionType .MultiValuedList
147
- elif source_slot .inlined :
148
- if source_slot .range in self .source_schemaview .all_classes ():
149
- id_slot = self .source_schemaview .get_identifier_slot (
150
- source_slot .range , use_key = True
151
- )
152
- if id_slot :
153
- inverted_sd .cast_collection_as = CollectionType .MultiValuedDict
154
- inverted_sd .dictionary_key = id_slot .name
152
+ elif source_slot .inlined and source_slot .range in self .source_schemaview .all_classes ():
153
+ id_slot = self .source_schemaview .get_identifier_slot (
154
+ source_slot .range , use_key = True
155
+ )
156
+ if id_slot :
157
+ inverted_sd .cast_collection_as = CollectionType .MultiValuedDict
158
+ inverted_sd .dictionary_key = id_slot .name
155
159
if sd .unit_conversion :
156
160
source_slot = self .source_schemaview .induced_slot (sd .populated_from , source_cls_name )
157
161
target_unit = None
@@ -165,8 +169,6 @@ def invert_slot_derivation(
165
169
inverted_uc = UnitConversionConfiguration (
166
170
target_unit = target_unit , target_unit_scheme = target_unit_scheme
167
171
)
168
- # if sd.unit_conversion.target_unit:
169
- # inverted_uc.source_unit = sd.unit_conversion.target_unit
170
172
if sd .unit_conversion .source_unit_slot :
171
173
inverted_uc .target_unit_slot = sd .unit_conversion .source_unit_slot
172
174
if sd .unit_conversion .source_magnitude_slot :
0 commit comments