pytrilogy 0.0.3.92__py3-none-any.whl → 0.0.3.93__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 pytrilogy might be problematic. Click here for more details.
- {pytrilogy-0.0.3.92.dist-info → pytrilogy-0.0.3.93.dist-info}/METADATA +1 -1
- {pytrilogy-0.0.3.92.dist-info → pytrilogy-0.0.3.93.dist-info}/RECORD +13 -12
- trilogy/__init__.py +1 -1
- trilogy/core/models/author.py +1 -1
- trilogy/core/models/build.py +136 -147
- trilogy/core/models/build_environment.py +2 -6
- trilogy/core/models/execute.py +3 -3
- trilogy/core/processing/node_generators/group_node.py +3 -7
- trilogy/core/processing/node_generators/select_merge_node_v2.py +792 -0
- {pytrilogy-0.0.3.92.dist-info → pytrilogy-0.0.3.93.dist-info}/WHEEL +0 -0
- {pytrilogy-0.0.3.92.dist-info → pytrilogy-0.0.3.93.dist-info}/entry_points.txt +0 -0
- {pytrilogy-0.0.3.92.dist-info → pytrilogy-0.0.3.93.dist-info}/licenses/LICENSE.md +0 -0
- {pytrilogy-0.0.3.92.dist-info → pytrilogy-0.0.3.93.dist-info}/top_level.txt +0 -0
trilogy/core/models/build.py
CHANGED
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from abc import ABC
|
|
4
4
|
from collections import defaultdict
|
|
5
|
+
from dataclasses import dataclass, field
|
|
5
6
|
from datetime import date, datetime
|
|
6
7
|
from functools import cached_property, singledispatchmethod
|
|
7
8
|
from typing import (
|
|
@@ -18,12 +19,7 @@ from typing import (
|
|
|
18
19
|
)
|
|
19
20
|
|
|
20
21
|
from pydantic import (
|
|
21
|
-
BaseModel,
|
|
22
22
|
ConfigDict,
|
|
23
|
-
Field,
|
|
24
|
-
ValidationInfo,
|
|
25
|
-
computed_field,
|
|
26
|
-
field_validator,
|
|
27
23
|
)
|
|
28
24
|
|
|
29
25
|
from trilogy.constants import DEFAULT_NAMESPACE, MagicConstants
|
|
@@ -170,17 +166,14 @@ def concepts_to_build_grain_concepts(
|
|
|
170
166
|
return final
|
|
171
167
|
|
|
172
168
|
|
|
173
|
-
|
|
169
|
+
@dataclass
|
|
170
|
+
class LooseBuildConceptList:
|
|
174
171
|
concepts: Sequence[BuildConcept]
|
|
175
172
|
|
|
176
173
|
@cached_property
|
|
177
174
|
def addresses(self) -> set[str]:
|
|
178
175
|
return {s.address for s in self.concepts}
|
|
179
176
|
|
|
180
|
-
@classmethod
|
|
181
|
-
def validate(cls, v):
|
|
182
|
-
return cls(v)
|
|
183
|
-
|
|
184
177
|
@cached_property
|
|
185
178
|
def sorted_addresses(self) -> List[str]:
|
|
186
179
|
return sorted(list(self.addresses))
|
|
@@ -248,7 +241,8 @@ def get_concept_arguments(expr) -> List["BuildConcept"]:
|
|
|
248
241
|
return output
|
|
249
242
|
|
|
250
243
|
|
|
251
|
-
|
|
244
|
+
@dataclass
|
|
245
|
+
class BuildParamaterizedConceptReference(DataTyped):
|
|
252
246
|
concept: BuildConcept
|
|
253
247
|
|
|
254
248
|
def __str__(self):
|
|
@@ -263,8 +257,9 @@ class BuildParamaterizedConceptReference(DataTyped, BaseModel):
|
|
|
263
257
|
return self.concept.output_datatype
|
|
264
258
|
|
|
265
259
|
|
|
266
|
-
|
|
267
|
-
|
|
260
|
+
@dataclass
|
|
261
|
+
class BuildGrain:
|
|
262
|
+
components: set[str] = field(default_factory=set)
|
|
268
263
|
where_clause: Optional[BuildWhereClause] = None
|
|
269
264
|
_str: str | None = None
|
|
270
265
|
_str_no_condition: str | None = None
|
|
@@ -272,7 +267,7 @@ class BuildGrain(BaseModel):
|
|
|
272
267
|
def without_condition(self):
|
|
273
268
|
if not self.where_clause:
|
|
274
269
|
return self
|
|
275
|
-
return BuildGrain
|
|
270
|
+
return BuildGrain(components=self.components)
|
|
276
271
|
|
|
277
272
|
@classmethod
|
|
278
273
|
def from_concepts(
|
|
@@ -282,30 +277,13 @@ class BuildGrain(BaseModel):
|
|
|
282
277
|
where_clause: BuildWhereClause | None = None,
|
|
283
278
|
) -> "BuildGrain":
|
|
284
279
|
|
|
285
|
-
return BuildGrain
|
|
280
|
+
return BuildGrain(
|
|
286
281
|
components=concepts_to_build_grain_concepts(
|
|
287
282
|
concepts, environment=environment
|
|
288
283
|
),
|
|
289
284
|
where_clause=where_clause,
|
|
290
285
|
)
|
|
291
286
|
|
|
292
|
-
@field_validator("components", mode="before")
|
|
293
|
-
def component_validator(cls, v, info: ValidationInfo):
|
|
294
|
-
output = set()
|
|
295
|
-
if isinstance(v, list):
|
|
296
|
-
for vc in v:
|
|
297
|
-
if isinstance(vc, BuildConcept):
|
|
298
|
-
output.add(vc.address)
|
|
299
|
-
else:
|
|
300
|
-
output.add(vc)
|
|
301
|
-
else:
|
|
302
|
-
output = v
|
|
303
|
-
if not isinstance(output, set):
|
|
304
|
-
raise ValueError(f"Invalid grain component {output}, is not set")
|
|
305
|
-
if not all(isinstance(x, str) for x in output):
|
|
306
|
-
raise ValueError(f"Invalid component {output}")
|
|
307
|
-
return output
|
|
308
|
-
|
|
309
287
|
def __add__(self, other: "BuildGrain") -> "BuildGrain":
|
|
310
288
|
if not other:
|
|
311
289
|
return self
|
|
@@ -324,12 +302,12 @@ class BuildGrain(BaseModel):
|
|
|
324
302
|
# raise NotImplementedError(
|
|
325
303
|
# f"Cannot merge grains with where clauses, self {self.where_clause} other {other.where_clause}"
|
|
326
304
|
# )
|
|
327
|
-
return BuildGrain
|
|
305
|
+
return BuildGrain(
|
|
328
306
|
components=self.components.union(other.components), where_clause=where
|
|
329
307
|
)
|
|
330
308
|
|
|
331
309
|
def __sub__(self, other: "BuildGrain") -> "BuildGrain":
|
|
332
|
-
return BuildGrain
|
|
310
|
+
return BuildGrain(
|
|
333
311
|
components=self.components.difference(other.components),
|
|
334
312
|
where_clause=self.where_clause,
|
|
335
313
|
)
|
|
@@ -401,7 +379,8 @@ class BuildGrain(BaseModel):
|
|
|
401
379
|
return self.__add__(other)
|
|
402
380
|
|
|
403
381
|
|
|
404
|
-
|
|
382
|
+
@dataclass
|
|
383
|
+
class BuildParenthetical(DataTyped, ConstantInlineable, BuildConceptArgs):
|
|
405
384
|
content: "BuildExpr"
|
|
406
385
|
|
|
407
386
|
def __add__(self, other) -> Union["BuildParenthetical", "BuildConditional"]:
|
|
@@ -455,7 +434,8 @@ class BuildParenthetical(DataTyped, ConstantInlineable, BuildConceptArgs, BaseMo
|
|
|
455
434
|
return arg_to_datatype(self.content)
|
|
456
435
|
|
|
457
436
|
|
|
458
|
-
|
|
437
|
+
@dataclass
|
|
438
|
+
class BuildConditional(BuildConceptArgs, ConstantInlineable):
|
|
459
439
|
left: Union[
|
|
460
440
|
int,
|
|
461
441
|
str,
|
|
@@ -583,7 +563,8 @@ class BuildConditional(BuildConceptArgs, ConstantInlineable, BaseModel):
|
|
|
583
563
|
return chunks
|
|
584
564
|
|
|
585
565
|
|
|
586
|
-
|
|
566
|
+
@dataclass
|
|
567
|
+
class BuildWhereClause(BuildConceptArgs):
|
|
587
568
|
conditional: Union[
|
|
588
569
|
BuildSubselectComparison,
|
|
589
570
|
BuildComparison,
|
|
@@ -619,7 +600,8 @@ class BuildHavingClause(BuildWhereClause):
|
|
|
619
600
|
pass
|
|
620
601
|
|
|
621
602
|
|
|
622
|
-
|
|
603
|
+
@dataclass
|
|
604
|
+
class BuildComparison(BuildConceptArgs, ConstantInlineable):
|
|
623
605
|
|
|
624
606
|
left: Union[
|
|
625
607
|
int,
|
|
@@ -749,6 +731,7 @@ class BuildComparison(BuildConceptArgs, ConstantInlineable, BaseModel):
|
|
|
749
731
|
return output
|
|
750
732
|
|
|
751
733
|
|
|
734
|
+
@dataclass
|
|
752
735
|
class BuildSubselectComparison(BuildComparison):
|
|
753
736
|
left: Union[
|
|
754
737
|
int,
|
|
@@ -810,18 +793,18 @@ class BuildSubselectComparison(BuildComparison):
|
|
|
810
793
|
return [tuple(get_concept_arguments(self.right))]
|
|
811
794
|
|
|
812
795
|
|
|
813
|
-
|
|
796
|
+
@dataclass
|
|
797
|
+
class BuildConcept(Addressable, BuildConceptArgs, DataTyped):
|
|
814
798
|
model_config = ConfigDict(extra="forbid")
|
|
815
799
|
name: str
|
|
816
|
-
datatype: DataType | ArrayType | StructType | MapType | NumericType
|
|
800
|
+
datatype: DataType | ArrayType | StructType | MapType | NumericType | TraitDataType
|
|
817
801
|
purpose: Purpose
|
|
818
802
|
build_is_aggregate: bool
|
|
819
803
|
derivation: Derivation = Derivation.ROOT
|
|
820
804
|
granularity: Granularity = Granularity.MULTI_ROW
|
|
821
|
-
namespace: Optional[str] =
|
|
822
|
-
metadata: Metadata =
|
|
805
|
+
namespace: Optional[str] = field(default=DEFAULT_NAMESPACE)
|
|
806
|
+
metadata: Metadata = field(
|
|
823
807
|
default_factory=lambda: Metadata(description=None, line_number=None),
|
|
824
|
-
validate_default=True,
|
|
825
808
|
)
|
|
826
809
|
lineage: Optional[
|
|
827
810
|
Union[
|
|
@@ -835,22 +818,23 @@ class BuildConcept(Addressable, BuildConceptArgs, DataTyped, BaseModel):
|
|
|
835
818
|
] = None
|
|
836
819
|
|
|
837
820
|
keys: Optional[set[str]] = None
|
|
838
|
-
grain: BuildGrain =
|
|
839
|
-
modifiers: List[Modifier] =
|
|
840
|
-
pseudonyms: set[str] =
|
|
821
|
+
grain: BuildGrain = field(default=None) # type: ignore
|
|
822
|
+
modifiers: List[Modifier] = field(default_factory=list) # type: ignore
|
|
823
|
+
pseudonyms: set[str] = field(default_factory=set)
|
|
841
824
|
|
|
842
825
|
@property
|
|
843
826
|
def is_aggregate(self) -> bool:
|
|
844
827
|
return self.build_is_aggregate
|
|
845
828
|
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
def __hash__(self):
|
|
829
|
+
@cached_property
|
|
830
|
+
def hash(self) -> int:
|
|
850
831
|
return hash(
|
|
851
832
|
f"{self.name}+{self.datatype}+ {self.purpose} + {str(self.lineage)} + {self.namespace} + {str(self.grain)} + {str(self.keys)}"
|
|
852
833
|
)
|
|
853
834
|
|
|
835
|
+
def __hash__(self):
|
|
836
|
+
return self.hash
|
|
837
|
+
|
|
854
838
|
def __repr__(self):
|
|
855
839
|
base = f"{self.address}@{self.grain}"
|
|
856
840
|
return base
|
|
@@ -903,7 +887,7 @@ class BuildConcept(Addressable, BuildConceptArgs, DataTyped, BaseModel):
|
|
|
903
887
|
]
|
|
904
888
|
)
|
|
905
889
|
)
|
|
906
|
-
return self.__class__
|
|
890
|
+
return self.__class__(
|
|
907
891
|
name=self.name,
|
|
908
892
|
datatype=self.datatype,
|
|
909
893
|
purpose=self.purpose,
|
|
@@ -945,7 +929,7 @@ class BuildConcept(Addressable, BuildConceptArgs, DataTyped, BaseModel):
|
|
|
945
929
|
grain = self.grain
|
|
946
930
|
else:
|
|
947
931
|
grain = self.grain # type: ignore
|
|
948
|
-
return self.__class__
|
|
932
|
+
return self.__class__(
|
|
949
933
|
name=self.name,
|
|
950
934
|
datatype=self.datatype,
|
|
951
935
|
purpose=self.purpose,
|
|
@@ -1001,7 +985,8 @@ class BuildConcept(Addressable, BuildConceptArgs, DataTyped, BaseModel):
|
|
|
1001
985
|
return self.lineage.concept_arguments if self.lineage else []
|
|
1002
986
|
|
|
1003
987
|
|
|
1004
|
-
|
|
988
|
+
@dataclass
|
|
989
|
+
class BuildOrderItem(DataTyped, BuildConceptArgs):
|
|
1005
990
|
expr: BuildExpr
|
|
1006
991
|
order: Ordering
|
|
1007
992
|
|
|
@@ -1032,11 +1017,12 @@ class BuildOrderItem(DataTyped, BuildConceptArgs, BaseModel):
|
|
|
1032
1017
|
return arg_to_datatype(self.expr)
|
|
1033
1018
|
|
|
1034
1019
|
|
|
1035
|
-
|
|
1020
|
+
@dataclass
|
|
1021
|
+
class BuildWindowItem(DataTyped, BuildConceptArgs):
|
|
1036
1022
|
type: WindowType
|
|
1037
1023
|
content: BuildConcept
|
|
1038
1024
|
order_by: List[BuildOrderItem]
|
|
1039
|
-
over: List["BuildConcept"] =
|
|
1025
|
+
over: List["BuildConcept"] = field(default_factory=list)
|
|
1040
1026
|
index: Optional[int] = None
|
|
1041
1027
|
|
|
1042
1028
|
def __repr__(self) -> str:
|
|
@@ -1069,7 +1055,8 @@ class BuildWindowItem(DataTyped, BuildConceptArgs, BaseModel):
|
|
|
1069
1055
|
return Purpose.PROPERTY
|
|
1070
1056
|
|
|
1071
1057
|
|
|
1072
|
-
|
|
1058
|
+
@dataclass
|
|
1059
|
+
class BuildCaseWhen(BuildConceptArgs):
|
|
1073
1060
|
comparison: BuildConditional | BuildSubselectComparison | BuildComparison
|
|
1074
1061
|
expr: "BuildExpr"
|
|
1075
1062
|
|
|
@@ -1090,30 +1077,18 @@ class BuildCaseWhen(BuildConceptArgs, BaseModel):
|
|
|
1090
1077
|
)
|
|
1091
1078
|
|
|
1092
1079
|
|
|
1093
|
-
|
|
1080
|
+
@dataclass
|
|
1081
|
+
class BuildCaseElse(BuildConceptArgs):
|
|
1094
1082
|
expr: "BuildExpr"
|
|
1095
|
-
# this ensures that it's easily differentiable from CaseWhen
|
|
1096
|
-
discriminant: ComparisonOperator = ComparisonOperator.ELSE
|
|
1097
1083
|
|
|
1098
1084
|
@property
|
|
1099
1085
|
def concept_arguments(self):
|
|
1100
1086
|
return get_concept_arguments(self.expr)
|
|
1101
1087
|
|
|
1102
1088
|
|
|
1103
|
-
|
|
1104
|
-
|
|
1089
|
+
@dataclass
|
|
1090
|
+
class BuildFunction(DataTyped, BuildConceptArgs):
|
|
1105
1091
|
operator: FunctionType
|
|
1106
|
-
arg_count: int = Field(default=1)
|
|
1107
|
-
output_datatype: (
|
|
1108
|
-
DataType | ArrayType | StructType | MapType | NumericType | TraitDataType
|
|
1109
|
-
)
|
|
1110
|
-
output_purpose: Purpose
|
|
1111
|
-
valid_inputs: Optional[
|
|
1112
|
-
Union[
|
|
1113
|
-
Set[DataType],
|
|
1114
|
-
List[Set[DataType]],
|
|
1115
|
-
]
|
|
1116
|
-
] = None
|
|
1117
1092
|
arguments: Sequence[
|
|
1118
1093
|
Union[
|
|
1119
1094
|
int,
|
|
@@ -1139,6 +1114,17 @@ class BuildFunction(DataTyped, BuildConceptArgs, BaseModel):
|
|
|
1139
1114
|
ListWrapper[Any],
|
|
1140
1115
|
]
|
|
1141
1116
|
]
|
|
1117
|
+
output_data_type: (
|
|
1118
|
+
DataType | ArrayType | StructType | MapType | NumericType | TraitDataType
|
|
1119
|
+
)
|
|
1120
|
+
output_purpose: Purpose = field(default=Purpose.KEY)
|
|
1121
|
+
arg_count: int = field(default=1)
|
|
1122
|
+
valid_inputs: Optional[
|
|
1123
|
+
Union[
|
|
1124
|
+
Set[DataType],
|
|
1125
|
+
List[Set[DataType]],
|
|
1126
|
+
]
|
|
1127
|
+
] = None
|
|
1142
1128
|
|
|
1143
1129
|
def __repr__(self):
|
|
1144
1130
|
return f'{self.operator.value}({",".join([str(a) for a in self.arguments])})'
|
|
@@ -1148,7 +1134,11 @@ class BuildFunction(DataTyped, BuildConceptArgs, BaseModel):
|
|
|
1148
1134
|
|
|
1149
1135
|
@property
|
|
1150
1136
|
def datatype(self):
|
|
1151
|
-
return self.
|
|
1137
|
+
return self.output_data_type
|
|
1138
|
+
|
|
1139
|
+
@property
|
|
1140
|
+
def output_datatype(self):
|
|
1141
|
+
return self.output_data_type
|
|
1152
1142
|
|
|
1153
1143
|
@property
|
|
1154
1144
|
def concept_arguments(self) -> List[BuildConcept]:
|
|
@@ -1161,17 +1151,18 @@ class BuildFunction(DataTyped, BuildConceptArgs, BaseModel):
|
|
|
1161
1151
|
def output_grain(self):
|
|
1162
1152
|
# aggregates have an abstract grain
|
|
1163
1153
|
if self.operator in FunctionClass.AGGREGATE_FUNCTIONS.value:
|
|
1164
|
-
return BuildGrain
|
|
1154
|
+
return BuildGrain(components=[])
|
|
1165
1155
|
# scalars have implicit grain of all arguments
|
|
1166
1156
|
args = set()
|
|
1167
1157
|
for input in self.concept_arguments:
|
|
1168
1158
|
args += input.grain.components
|
|
1169
|
-
return BuildGrain
|
|
1159
|
+
return BuildGrain(components=args)
|
|
1170
1160
|
|
|
1171
1161
|
|
|
1172
|
-
|
|
1162
|
+
@dataclass
|
|
1163
|
+
class BuildAggregateWrapper(BuildConceptArgs, DataTyped):
|
|
1173
1164
|
function: BuildFunction
|
|
1174
|
-
by: List[BuildConcept] =
|
|
1165
|
+
by: List[BuildConcept] = field(default_factory=list)
|
|
1175
1166
|
|
|
1176
1167
|
def __str__(self):
|
|
1177
1168
|
grain_str = [str(c) for c in self.by] if self.by else "abstract"
|
|
@@ -1194,7 +1185,8 @@ class BuildAggregateWrapper(BuildConceptArgs, DataTyped, BaseModel):
|
|
|
1194
1185
|
return self.function.output_purpose
|
|
1195
1186
|
|
|
1196
1187
|
|
|
1197
|
-
|
|
1188
|
+
@dataclass
|
|
1189
|
+
class BuildFilterItem(BuildConceptArgs):
|
|
1198
1190
|
content: "BuildExpr"
|
|
1199
1191
|
where: BuildWhereClause
|
|
1200
1192
|
|
|
@@ -1226,13 +1218,15 @@ class BuildFilterItem(BuildConceptArgs, BaseModel):
|
|
|
1226
1218
|
return self.where.concept_arguments
|
|
1227
1219
|
|
|
1228
1220
|
|
|
1229
|
-
|
|
1221
|
+
@dataclass
|
|
1222
|
+
class BuildRowsetLineage(BuildConceptArgs):
|
|
1230
1223
|
name: str
|
|
1231
1224
|
derived_concepts: List[str]
|
|
1232
1225
|
select: SelectLineage | MultiSelectLineage
|
|
1233
1226
|
|
|
1234
1227
|
|
|
1235
|
-
|
|
1228
|
+
@dataclass
|
|
1229
|
+
class BuildRowsetItem(DataTyped, BuildConceptArgs):
|
|
1236
1230
|
content: BuildConcept
|
|
1237
1231
|
rowset: BuildRowsetLineage
|
|
1238
1232
|
|
|
@@ -1259,7 +1253,8 @@ class BuildRowsetItem(DataTyped, BuildConceptArgs, BaseModel):
|
|
|
1259
1253
|
return [self.content]
|
|
1260
1254
|
|
|
1261
1255
|
|
|
1262
|
-
|
|
1256
|
+
@dataclass
|
|
1257
|
+
class BuildOrderBy:
|
|
1263
1258
|
items: List[BuildOrderItem]
|
|
1264
1259
|
|
|
1265
1260
|
@property
|
|
@@ -1267,39 +1262,42 @@ class BuildOrderBy(BaseModel):
|
|
|
1267
1262
|
return [x.expr for x in self.items]
|
|
1268
1263
|
|
|
1269
1264
|
|
|
1270
|
-
|
|
1265
|
+
@dataclass
|
|
1266
|
+
class BuildAlignClause:
|
|
1271
1267
|
items: List[BuildAlignItem]
|
|
1272
1268
|
|
|
1273
1269
|
|
|
1274
|
-
|
|
1270
|
+
@dataclass
|
|
1271
|
+
class BuildSelectLineage:
|
|
1275
1272
|
selection: List[BuildConcept]
|
|
1276
1273
|
hidden_components: set[str]
|
|
1277
1274
|
local_concepts: dict[str, BuildConcept]
|
|
1278
1275
|
order_by: Optional[BuildOrderBy] = None
|
|
1279
1276
|
limit: Optional[int] = None
|
|
1280
|
-
meta: Metadata =
|
|
1281
|
-
grain: BuildGrain =
|
|
1282
|
-
where_clause: BuildWhereClause | None =
|
|
1283
|
-
having_clause: BuildHavingClause | None =
|
|
1277
|
+
meta: Metadata = field(default_factory=lambda: Metadata())
|
|
1278
|
+
grain: BuildGrain = field(default_factory=BuildGrain)
|
|
1279
|
+
where_clause: BuildWhereClause | None = field(default=None)
|
|
1280
|
+
having_clause: BuildHavingClause | None = field(default=None)
|
|
1284
1281
|
|
|
1285
1282
|
@property
|
|
1286
1283
|
def output_components(self) -> List[BuildConcept]:
|
|
1287
1284
|
return self.selection
|
|
1288
1285
|
|
|
1289
1286
|
|
|
1290
|
-
|
|
1287
|
+
@dataclass
|
|
1288
|
+
class BuildMultiSelectLineage(BuildConceptArgs):
|
|
1291
1289
|
selects: List[SelectLineage]
|
|
1292
1290
|
grain: BuildGrain
|
|
1293
1291
|
align: BuildAlignClause
|
|
1294
1292
|
namespace: str
|
|
1295
|
-
order_by: Optional[BuildOrderBy] = None
|
|
1296
|
-
limit: Optional[int] = None
|
|
1297
|
-
where_clause: Union["BuildWhereClause", None] = Field(default=None)
|
|
1298
|
-
having_clause: Union["BuildHavingClause", None] = Field(default=None)
|
|
1299
1293
|
local_concepts: dict[str, BuildConcept]
|
|
1300
1294
|
build_concept_arguments: list[BuildConcept]
|
|
1301
1295
|
build_output_components: list[BuildConcept]
|
|
1302
1296
|
hidden_components: set[str]
|
|
1297
|
+
order_by: Optional[BuildOrderBy] = None
|
|
1298
|
+
limit: Optional[int] = None
|
|
1299
|
+
where_clause: Union["BuildWhereClause", None] = field(default=None)
|
|
1300
|
+
having_clause: Union["BuildHavingClause", None] = field(default=None)
|
|
1303
1301
|
|
|
1304
1302
|
@property
|
|
1305
1303
|
def derived_concepts(self) -> set[str]:
|
|
@@ -1341,12 +1339,12 @@ class BuildMultiSelectLineage(BuildConceptArgs, BaseModel):
|
|
|
1341
1339
|
)
|
|
1342
1340
|
|
|
1343
1341
|
|
|
1344
|
-
|
|
1342
|
+
@dataclass
|
|
1343
|
+
class BuildAlignItem:
|
|
1345
1344
|
alias: str
|
|
1346
1345
|
concepts: List[BuildConcept]
|
|
1347
|
-
namespace: str =
|
|
1346
|
+
namespace: str = field(default=DEFAULT_NAMESPACE)
|
|
1348
1347
|
|
|
1349
|
-
@computed_field # type: ignore
|
|
1350
1348
|
@cached_property
|
|
1351
1349
|
def concepts_lcl(self) -> LooseBuildConceptList:
|
|
1352
1350
|
return LooseBuildConceptList(concepts=self.concepts)
|
|
@@ -1356,10 +1354,11 @@ class BuildAlignItem(BaseModel):
|
|
|
1356
1354
|
return f"{self.namespace}.{self.alias}"
|
|
1357
1355
|
|
|
1358
1356
|
|
|
1359
|
-
|
|
1360
|
-
|
|
1357
|
+
@dataclass
|
|
1358
|
+
class BuildColumnAssignment:
|
|
1359
|
+
alias: str | RawColumnExpr | BuildFunction | BuildAggregateWrapper
|
|
1361
1360
|
concept: BuildConcept
|
|
1362
|
-
modifiers: List[Modifier] =
|
|
1361
|
+
modifiers: List[Modifier] = field(default_factory=list)
|
|
1363
1362
|
|
|
1364
1363
|
@property
|
|
1365
1364
|
def is_complete(self) -> bool:
|
|
@@ -1370,15 +1369,16 @@ class BuildColumnAssignment(BaseModel):
|
|
|
1370
1369
|
return Modifier.NULLABLE in self.modifiers
|
|
1371
1370
|
|
|
1372
1371
|
|
|
1373
|
-
|
|
1372
|
+
@dataclass
|
|
1373
|
+
class BuildDatasource:
|
|
1374
1374
|
name: str
|
|
1375
1375
|
columns: List[BuildColumnAssignment]
|
|
1376
1376
|
address: Union[Address, str]
|
|
1377
|
-
grain: BuildGrain =
|
|
1378
|
-
default_factory=lambda: BuildGrain(components=set()),
|
|
1377
|
+
grain: BuildGrain = field(
|
|
1378
|
+
default_factory=lambda: BuildGrain(components=set()),
|
|
1379
1379
|
)
|
|
1380
|
-
namespace: Optional[str] =
|
|
1381
|
-
metadata: DatasourceMetadata =
|
|
1380
|
+
namespace: Optional[str] = field(default=DEFAULT_NAMESPACE)
|
|
1381
|
+
metadata: DatasourceMetadata = field(
|
|
1382
1382
|
default_factory=lambda: DatasourceMetadata(freshness_concept=None)
|
|
1383
1383
|
)
|
|
1384
1384
|
where: Optional[BuildWhereClause] = None
|
|
@@ -1447,7 +1447,7 @@ class BuildDatasource(BaseModel):
|
|
|
1447
1447
|
concept: BuildConcept,
|
|
1448
1448
|
use_raw_name: bool = True,
|
|
1449
1449
|
force_alias: bool = False,
|
|
1450
|
-
) -> Optional[str | RawColumnExpr] | BuildFunction:
|
|
1450
|
+
) -> Optional[str | RawColumnExpr] | BuildFunction | BuildAggregateWrapper:
|
|
1451
1451
|
# 2022-01-22
|
|
1452
1452
|
# this logic needs to be refined.
|
|
1453
1453
|
# if concept.lineage:
|
|
@@ -1491,8 +1491,6 @@ BuildExpr = (
|
|
|
1491
1491
|
| list
|
|
1492
1492
|
)
|
|
1493
1493
|
|
|
1494
|
-
BuildConcept.model_rebuild()
|
|
1495
|
-
|
|
1496
1494
|
|
|
1497
1495
|
def get_canonical_pseudonyms(environment: Environment) -> dict[str, set[str]]:
|
|
1498
1496
|
roots: dict[str, set[str]] = defaultdict(set)
|
|
@@ -1655,22 +1653,22 @@ class Factory:
|
|
|
1655
1653
|
)
|
|
1656
1654
|
)
|
|
1657
1655
|
|
|
1658
|
-
return BuildFunction
|
|
1656
|
+
return BuildFunction(
|
|
1659
1657
|
operator=base.operator,
|
|
1660
1658
|
arguments=[
|
|
1661
1659
|
rval,
|
|
1662
1660
|
*[self.handle_constant(self.build(c)) for c in raw_args[1:]],
|
|
1663
1661
|
],
|
|
1664
|
-
|
|
1662
|
+
output_data_type=base.output_datatype,
|
|
1665
1663
|
output_purpose=base.output_purpose,
|
|
1666
1664
|
valid_inputs=base.valid_inputs,
|
|
1667
1665
|
arg_count=base.arg_count,
|
|
1668
1666
|
)
|
|
1669
1667
|
|
|
1670
|
-
new = BuildFunction
|
|
1668
|
+
new = BuildFunction(
|
|
1671
1669
|
operator=base.operator,
|
|
1672
1670
|
arguments=[self.handle_constant(self.build(c)) for c in raw_args],
|
|
1673
|
-
|
|
1671
|
+
output_data_type=base.output_datatype,
|
|
1674
1672
|
output_purpose=base.output_purpose,
|
|
1675
1673
|
valid_inputs=base.valid_inputs,
|
|
1676
1674
|
arg_count=base.arg_count,
|
|
@@ -1702,7 +1700,7 @@ class Factory:
|
|
|
1702
1700
|
validation = requires_concept_nesting(expr)
|
|
1703
1701
|
if validation:
|
|
1704
1702
|
expr, _ = self.instantiate_concept(validation)
|
|
1705
|
-
return BuildCaseWhen
|
|
1703
|
+
return BuildCaseWhen(
|
|
1706
1704
|
comparison=self.build(comparison),
|
|
1707
1705
|
expr=self.build(expr),
|
|
1708
1706
|
)
|
|
@@ -1716,7 +1714,7 @@ class Factory:
|
|
|
1716
1714
|
validation = requires_concept_nesting(expr)
|
|
1717
1715
|
if validation:
|
|
1718
1716
|
expr, _ = self.instantiate_concept(validation)
|
|
1719
|
-
return BuildCaseElse
|
|
1717
|
+
return BuildCaseElse(expr=self.build(expr))
|
|
1720
1718
|
|
|
1721
1719
|
@build.register
|
|
1722
1720
|
def _(self, base: Concept) -> BuildConcept:
|
|
@@ -1751,7 +1749,7 @@ class Factory:
|
|
|
1751
1749
|
for x in self.pseudonym_map.get(base.address, set())
|
|
1752
1750
|
if x != base.address
|
|
1753
1751
|
}
|
|
1754
|
-
rval = BuildConcept
|
|
1752
|
+
rval = BuildConcept(
|
|
1755
1753
|
name=base.name,
|
|
1756
1754
|
datatype=base.datatype,
|
|
1757
1755
|
purpose=base.purpose,
|
|
@@ -1777,13 +1775,14 @@ class Factory:
|
|
|
1777
1775
|
def _build_aggregate_wrapper(self, base: AggregateWrapper) -> BuildAggregateWrapper:
|
|
1778
1776
|
if not base.by:
|
|
1779
1777
|
by = [
|
|
1780
|
-
self.
|
|
1778
|
+
self._build_concept(self.environment.concepts[c])
|
|
1779
|
+
for c in self.grain.components
|
|
1781
1780
|
]
|
|
1782
1781
|
else:
|
|
1783
1782
|
by = [self.build(x) for x in base.by]
|
|
1784
1783
|
|
|
1785
|
-
parent = self.
|
|
1786
|
-
return BuildAggregateWrapper
|
|
1784
|
+
parent: BuildFunction = self._build_function(base.function) # type: ignore
|
|
1785
|
+
return BuildAggregateWrapper(function=parent, by=by)
|
|
1787
1786
|
|
|
1788
1787
|
@build.register
|
|
1789
1788
|
def _(self, base: ColumnAssignment) -> BuildColumnAssignment:
|
|
@@ -1801,7 +1800,7 @@ class Factory:
|
|
|
1801
1800
|
)
|
|
1802
1801
|
)
|
|
1803
1802
|
|
|
1804
|
-
return BuildColumnAssignment
|
|
1803
|
+
return BuildColumnAssignment(
|
|
1805
1804
|
alias=(
|
|
1806
1805
|
self._build_function(base.alias)
|
|
1807
1806
|
if isinstance(base.alias, Function)
|
|
@@ -1816,7 +1815,7 @@ class Factory:
|
|
|
1816
1815
|
return self._build_order_by(base)
|
|
1817
1816
|
|
|
1818
1817
|
def _build_order_by(self, base: OrderBy) -> BuildOrderBy:
|
|
1819
|
-
return BuildOrderBy
|
|
1818
|
+
return BuildOrderBy(items=[self._build_order_item(x) for x in base.items])
|
|
1820
1819
|
|
|
1821
1820
|
@build.register
|
|
1822
1821
|
def _(self, base: FunctionCallWrapper) -> BuildExpr:
|
|
@@ -1838,7 +1837,7 @@ class Factory:
|
|
|
1838
1837
|
bexpr, _ = self.instantiate_concept(validation)
|
|
1839
1838
|
else:
|
|
1840
1839
|
bexpr = base.expr
|
|
1841
|
-
return BuildOrderItem
|
|
1840
|
+
return BuildOrderItem(
|
|
1842
1841
|
expr=(self.build(bexpr)),
|
|
1843
1842
|
order=base.order,
|
|
1844
1843
|
)
|
|
@@ -1848,18 +1847,14 @@ class Factory:
|
|
|
1848
1847
|
return self._build_where_clause(base)
|
|
1849
1848
|
|
|
1850
1849
|
def _build_where_clause(self, base: WhereClause) -> BuildWhereClause:
|
|
1851
|
-
return BuildWhereClause.
|
|
1852
|
-
conditional=self.build(base.conditional)
|
|
1853
|
-
)
|
|
1850
|
+
return BuildWhereClause(conditional=self.build(base.conditional))
|
|
1854
1851
|
|
|
1855
1852
|
@build.register
|
|
1856
1853
|
def _(self, base: HavingClause) -> BuildHavingClause:
|
|
1857
1854
|
return self._build_having_clause(base)
|
|
1858
1855
|
|
|
1859
1856
|
def _build_having_clause(self, base: HavingClause) -> BuildHavingClause:
|
|
1860
|
-
return BuildHavingClause.
|
|
1861
|
-
conditional=self.build(base.conditional)
|
|
1862
|
-
)
|
|
1857
|
+
return BuildHavingClause(conditional=self.build(base.conditional))
|
|
1863
1858
|
|
|
1864
1859
|
@build.register
|
|
1865
1860
|
def _(self, base: WindowItem) -> BuildWindowItem:
|
|
@@ -1879,11 +1874,11 @@ class Factory:
|
|
|
1879
1874
|
):
|
|
1880
1875
|
x.expr.by = [content]
|
|
1881
1876
|
final_by.append(x)
|
|
1882
|
-
return BuildWindowItem
|
|
1877
|
+
return BuildWindowItem(
|
|
1883
1878
|
type=base.type,
|
|
1884
1879
|
content=self.build(content),
|
|
1885
1880
|
order_by=[self.build(x) for x in final_by],
|
|
1886
|
-
over=[self.
|
|
1881
|
+
over=[self._build_concept_ref(x) for x in base.over],
|
|
1887
1882
|
index=base.index,
|
|
1888
1883
|
)
|
|
1889
1884
|
|
|
@@ -1892,7 +1887,7 @@ class Factory:
|
|
|
1892
1887
|
return self._build_conditional(base)
|
|
1893
1888
|
|
|
1894
1889
|
def _build_conditional(self, base: Conditional) -> BuildConditional:
|
|
1895
|
-
return BuildConditional
|
|
1890
|
+
return BuildConditional(
|
|
1896
1891
|
left=self.handle_constant(self.build(base.left)),
|
|
1897
1892
|
right=self.handle_constant(self.build(base.right)),
|
|
1898
1893
|
operator=base.operator,
|
|
@@ -1910,7 +1905,7 @@ class Factory:
|
|
|
1910
1905
|
if isinstance(base.right, (AggregateWrapper, WindowItem, FilterItem, Function)):
|
|
1911
1906
|
right_c, _ = self.instantiate_concept(base.right)
|
|
1912
1907
|
right = right_c
|
|
1913
|
-
return BuildSubselectComparison
|
|
1908
|
+
return BuildSubselectComparison(
|
|
1914
1909
|
left=self.handle_constant(self.build(base.left)),
|
|
1915
1910
|
right=self.handle_constant(self.build(right)),
|
|
1916
1911
|
operator=base.operator,
|
|
@@ -1931,7 +1926,7 @@ class Factory:
|
|
|
1931
1926
|
if validation:
|
|
1932
1927
|
right_c, _ = self.instantiate_concept(validation)
|
|
1933
1928
|
right = right_c # type: ignore
|
|
1934
|
-
return BuildComparison
|
|
1929
|
+
return BuildComparison(
|
|
1935
1930
|
left=self.handle_constant(self.build(left)),
|
|
1936
1931
|
right=self.handle_constant(self.build(right)),
|
|
1937
1932
|
operator=base.operator,
|
|
@@ -1942,9 +1937,9 @@ class Factory:
|
|
|
1942
1937
|
return self._build_align_item(base)
|
|
1943
1938
|
|
|
1944
1939
|
def _build_align_item(self, base: AlignItem) -> BuildAlignItem:
|
|
1945
|
-
return BuildAlignItem
|
|
1940
|
+
return BuildAlignItem(
|
|
1946
1941
|
alias=base.alias,
|
|
1947
|
-
concepts=[self.
|
|
1942
|
+
concepts=[self._build_concept_ref(x) for x in base.concepts],
|
|
1948
1943
|
namespace=base.namespace,
|
|
1949
1944
|
)
|
|
1950
1945
|
|
|
@@ -1953,9 +1948,7 @@ class Factory:
|
|
|
1953
1948
|
return self._build_align_clause(base)
|
|
1954
1949
|
|
|
1955
1950
|
def _build_align_clause(self, base: AlignClause) -> BuildAlignClause:
|
|
1956
|
-
return BuildAlignClause.
|
|
1957
|
-
items=[self.build(x) for x in base.items]
|
|
1958
|
-
)
|
|
1951
|
+
return BuildAlignClause(items=[self._build_align_item(x) for x in base.items])
|
|
1959
1952
|
|
|
1960
1953
|
@build.register
|
|
1961
1954
|
def _(self, base: RowsetItem) -> BuildRowsetItem:
|
|
@@ -1994,12 +1987,10 @@ class Factory:
|
|
|
1994
1987
|
factory = Factory(
|
|
1995
1988
|
environment=self.environment, pseudonym_map=self.pseudonym_map
|
|
1996
1989
|
)
|
|
1997
|
-
where = factory.
|
|
1990
|
+
where = factory._build_where_clause(base.where_clause)
|
|
1998
1991
|
else:
|
|
1999
1992
|
where = None
|
|
2000
|
-
return BuildGrain.
|
|
2001
|
-
components=base.components, where_clause=where
|
|
2002
|
-
)
|
|
1993
|
+
return BuildGrain(components=base.components, where_clause=where)
|
|
2003
1994
|
|
|
2004
1995
|
@build.register
|
|
2005
1996
|
def _(self, base: TupleWrapper) -> TupleWrapper:
|
|
@@ -2017,10 +2008,8 @@ class Factory:
|
|
|
2017
2008
|
base.content, (Function, AggregateWrapper, WindowItem, FilterItem)
|
|
2018
2009
|
):
|
|
2019
2010
|
_, built = self.instantiate_concept(base.content)
|
|
2020
|
-
return BuildFilterItem.
|
|
2021
|
-
|
|
2022
|
-
)
|
|
2023
|
-
return BuildFilterItem.model_construct(
|
|
2011
|
+
return BuildFilterItem(content=built, where=self.build(base.where))
|
|
2012
|
+
return BuildFilterItem(
|
|
2024
2013
|
content=self.build(base.content), where=self.build(base.where)
|
|
2025
2014
|
)
|
|
2026
2015
|
|
|
@@ -2029,7 +2018,7 @@ class Factory:
|
|
|
2029
2018
|
return self._build_parenthetical(base)
|
|
2030
2019
|
|
|
2031
2020
|
def _build_parenthetical(self, base: Parenthetical) -> BuildParenthetical:
|
|
2032
|
-
return BuildParenthetical
|
|
2021
|
+
return BuildParenthetical(content=(self.build(base.content)))
|
|
2033
2022
|
|
|
2034
2023
|
@build.register
|
|
2035
2024
|
def _(self, base: SelectLineage) -> BuildSelectLineage:
|
|
@@ -2117,7 +2106,7 @@ class Factory:
|
|
|
2117
2106
|
derived_base = []
|
|
2118
2107
|
for k in base.derived_concepts:
|
|
2119
2108
|
base_concept = self.environment.concepts[k]
|
|
2120
|
-
x = BuildConcept
|
|
2109
|
+
x = BuildConcept(
|
|
2121
2110
|
name=base_concept.name,
|
|
2122
2111
|
datatype=base_concept.datatype,
|
|
2123
2112
|
purpose=base_concept.purpose,
|
|
@@ -2145,7 +2134,7 @@ class Factory:
|
|
|
2145
2134
|
where_factory = Factory(
|
|
2146
2135
|
environment=self.environment, pseudonym_map=self.pseudonym_map
|
|
2147
2136
|
)
|
|
2148
|
-
lineage = BuildMultiSelectLineage
|
|
2137
|
+
lineage = BuildMultiSelectLineage(
|
|
2149
2138
|
# we don't build selects here; they'll be built automatically in query discovery
|
|
2150
2139
|
selects=base.selects,
|
|
2151
2140
|
grain=final_grain,
|
|
@@ -2253,7 +2242,7 @@ class Factory:
|
|
|
2253
2242
|
local_concepts=local_cache,
|
|
2254
2243
|
pseudonym_map=self.pseudonym_map,
|
|
2255
2244
|
)
|
|
2256
|
-
return BuildDatasource
|
|
2245
|
+
return BuildDatasource(
|
|
2257
2246
|
name=base.name,
|
|
2258
2247
|
columns=[factory._build_column_assignment(c) for c in base.columns],
|
|
2259
2248
|
address=base.address,
|