pytrilogy 0.0.3.51__py3-none-any.whl → 0.0.3.52__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.51.dist-info → pytrilogy-0.0.3.52.dist-info}/METADATA +1 -1
- {pytrilogy-0.0.3.51.dist-info → pytrilogy-0.0.3.52.dist-info}/RECORD +13 -13
- trilogy/__init__.py +1 -1
- trilogy/core/functions.py +5 -2
- trilogy/core/models/author.py +6 -7
- trilogy/core/models/build.py +3 -9
- trilogy/core/models/execute.py +25 -11
- trilogy/parsing/common.py +3 -3
- trilogy/parsing/parse_engine.py +10 -5
- {pytrilogy-0.0.3.51.dist-info → pytrilogy-0.0.3.52.dist-info}/WHEEL +0 -0
- {pytrilogy-0.0.3.51.dist-info → pytrilogy-0.0.3.52.dist-info}/entry_points.txt +0 -0
- {pytrilogy-0.0.3.51.dist-info → pytrilogy-0.0.3.52.dist-info}/licenses/LICENSE.md +0 -0
- {pytrilogy-0.0.3.51.dist-info → pytrilogy-0.0.3.52.dist-info}/top_level.txt +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
pytrilogy-0.0.3.
|
|
2
|
-
trilogy/__init__.py,sha256=
|
|
1
|
+
pytrilogy-0.0.3.52.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
|
|
2
|
+
trilogy/__init__.py,sha256=3lpAbpHzxQ6c0SUaZfiuOcDzIS6IZ5DyK1fl8FmZ3hE,303
|
|
3
3
|
trilogy/compiler.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
trilogy/constants.py,sha256=5eQxk1A0pv-TQk3CCvgZCFA9_K-6nxrOm7E5Lxd7KIY,1652
|
|
5
5
|
trilogy/engine.py,sha256=OK2RuqCIUId6yZ5hfF8J1nxGP0AJqHRZiafcowmW0xc,1728
|
|
@@ -16,19 +16,19 @@ trilogy/core/env_processor.py,sha256=pFsxnluKIusGKx1z7tTnfsd_xZcPy9pZDungkjkyvI0
|
|
|
16
16
|
trilogy/core/environment_helpers.py,sha256=VvPIiFemqaLLpIpLIqprfu63K7muZ1YzNg7UZIUph8w,8267
|
|
17
17
|
trilogy/core/ergonomics.py,sha256=e-7gE29vPLFdg0_A1smQ7eOrUwKl5VYdxRSTddHweRA,1631
|
|
18
18
|
trilogy/core/exceptions.py,sha256=JPYyBcit3T_pRtlHdtKSeVJkIyWUTozW2aaut25A2xI,673
|
|
19
|
-
trilogy/core/functions.py,sha256=
|
|
19
|
+
trilogy/core/functions.py,sha256=OIcaftda-afXrHMSvPksLbRTwPUwQHAIpy9l78EBZVU,28643
|
|
20
20
|
trilogy/core/graph_models.py,sha256=z17EoO8oky2QOuO6E2aMWoVNKEVJFhLdsQZOhC4fNLU,2079
|
|
21
21
|
trilogy/core/internal.py,sha256=iicDBlC6nM8d7e7jqzf_ZOmpUsW8yrr2AA8AqEiLx-s,1577
|
|
22
22
|
trilogy/core/optimization.py,sha256=O7ag0IVQlJyWdAXBi_hHeU3Df5DRyd75Vlz6pks2J10,8197
|
|
23
23
|
trilogy/core/query_processor.py,sha256=NNzYPKN5HzivQFXugSbJC_MaupkwOYii7A_vnXuBIK4,20063
|
|
24
24
|
trilogy/core/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
|
-
trilogy/core/models/author.py,sha256=
|
|
26
|
-
trilogy/core/models/build.py,sha256=
|
|
25
|
+
trilogy/core/models/author.py,sha256=KKW_3A1hdwq7D2dFwI6xZanukPuCQQ23R4GzE5VRJ6c,77206
|
|
26
|
+
trilogy/core/models/build.py,sha256=yBiOQ4Bhjz09pSD1jSGhhf9QFFQuplrvZ0JQB5-iXHk,63104
|
|
27
27
|
trilogy/core/models/build_environment.py,sha256=s_C9xAHuD3yZ26T15pWVBvoqvlp2LdZ8yjsv2_HdXLk,5363
|
|
28
28
|
trilogy/core/models/core.py,sha256=wx6hJcFECMG-Ij972ADNkr-3nFXkYESr82ObPiC46_U,10875
|
|
29
29
|
trilogy/core/models/datasource.py,sha256=6RjJUd2u4nYmEwFBpJlM9LbHVYDv8iHJxqiBMZqUrwI,9422
|
|
30
30
|
trilogy/core/models/environment.py,sha256=AVSrvjNcNX535GhCPtYhCRY2Lp_Hj0tdY3VVt_kZb9Q,27260
|
|
31
|
-
trilogy/core/models/execute.py,sha256=
|
|
31
|
+
trilogy/core/models/execute.py,sha256=ucxMwsu5OMoP0E4pVKtkCNU0nogElJKQAqfu3arE4Jo,34879
|
|
32
32
|
trilogy/core/optimizations/__init__.py,sha256=YH2-mGXZnVDnBcWVi8vTbrdw7Qs5TivG4h38rH3js_I,290
|
|
33
33
|
trilogy/core/optimizations/base_optimization.py,sha256=gzDOKImoFn36k7XBD3ysEYDnbnb6vdVIztUfFQZsGnM,513
|
|
34
34
|
trilogy/core/optimizations/inline_datasource.py,sha256=AHuTGh2x0GQ8usOe0NiFncfTFQ_KogdgDl4uucmhIbI,4241
|
|
@@ -86,11 +86,11 @@ trilogy/hooks/graph_hook.py,sha256=c-vC-IXoJ_jDmKQjxQyIxyXPOuUcLIURB573gCsAfzQ,2
|
|
|
86
86
|
trilogy/hooks/query_debugger.py,sha256=1npRjww94sPV5RRBBlLqMJRaFkH9vhEY6o828MeoEcw,5583
|
|
87
87
|
trilogy/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
88
88
|
trilogy/parsing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
89
|
-
trilogy/parsing/common.py,sha256=
|
|
89
|
+
trilogy/parsing/common.py,sha256=g1RmQF4fS_OgkcC6j4hnKIcn_ap0fFa_kzNUlH5D0nA,29760
|
|
90
90
|
trilogy/parsing/config.py,sha256=Z-DaefdKhPDmSXLgg5V4pebhSB0h590vI0_VtHnlukI,111
|
|
91
91
|
trilogy/parsing/exceptions.py,sha256=Xwwsv2C9kSNv2q-HrrKC1f60JNHShXcCMzstTSEbiCw,154
|
|
92
92
|
trilogy/parsing/helpers.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
93
|
-
trilogy/parsing/parse_engine.py,sha256=
|
|
93
|
+
trilogy/parsing/parse_engine.py,sha256=p2YnE-YV-Dt0FlC6rP7Rq8phNxzk_O4ukNzVIDyHyu4,70054
|
|
94
94
|
trilogy/parsing/render.py,sha256=hI4y-xjXrEXvHslY2l2TQ8ic0zAOpN41ADH37J2_FZY,19047
|
|
95
95
|
trilogy/parsing/trilogy.lark,sha256=ijY6220e2hV21F1XFsvpYRimSrpNGIdjP7b0TVz7caI,13814
|
|
96
96
|
trilogy/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -101,8 +101,8 @@ trilogy/std/display.preql,sha256=2BbhvqR4rcltyAbOXAUo7SZ_yGFYZgFnurglHMbjW2g,40
|
|
|
101
101
|
trilogy/std/geography.preql,sha256=-fqAGnBL6tR-UtT8DbSek3iMFg66ECR_B_41pODxv-k,504
|
|
102
102
|
trilogy/std/money.preql,sha256=ZHW-csTX-kYbOLmKSO-TcGGgQ-_DMrUXy0BjfuJSFxM,80
|
|
103
103
|
trilogy/std/report.preql,sha256=LbV-XlHdfw0jgnQ8pV7acG95xrd1-p65fVpiIc-S7W4,202
|
|
104
|
-
pytrilogy-0.0.3.
|
|
105
|
-
pytrilogy-0.0.3.
|
|
106
|
-
pytrilogy-0.0.3.
|
|
107
|
-
pytrilogy-0.0.3.
|
|
108
|
-
pytrilogy-0.0.3.
|
|
104
|
+
pytrilogy-0.0.3.52.dist-info/METADATA,sha256=TIB3nLBjPqlhtsB-ZgL61mCM8MPkXdJkhB-nAIuhdcA,9095
|
|
105
|
+
pytrilogy-0.0.3.52.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
|
|
106
|
+
pytrilogy-0.0.3.52.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
|
|
107
|
+
pytrilogy-0.0.3.52.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
|
|
108
|
+
pytrilogy-0.0.3.52.dist-info/RECORD,,
|
trilogy/__init__.py
CHANGED
trilogy/core/functions.py
CHANGED
|
@@ -809,13 +809,14 @@ def create_function_derived_concept(
|
|
|
809
809
|
namespace: str,
|
|
810
810
|
operator: FunctionType,
|
|
811
811
|
arguments: list[Concept],
|
|
812
|
+
environment: Environment,
|
|
812
813
|
output_type: Optional[
|
|
813
814
|
DataType | ListType | StructType | MapType | NumericType | TraitDataType
|
|
814
815
|
] = None,
|
|
815
816
|
output_purpose: Optional[Purpose] = None,
|
|
816
817
|
) -> Concept:
|
|
817
818
|
purpose = (
|
|
818
|
-
function_args_to_output_purpose(arguments)
|
|
819
|
+
function_args_to_output_purpose(arguments, environment=environment)
|
|
819
820
|
if output_purpose is None
|
|
820
821
|
else output_purpose
|
|
821
822
|
)
|
|
@@ -868,13 +869,15 @@ def argument_to_purpose(arg) -> Purpose:
|
|
|
868
869
|
raise ValueError(f"Cannot parse arg purpose for {arg} of type {type(arg)}")
|
|
869
870
|
|
|
870
871
|
|
|
871
|
-
def function_args_to_output_purpose(args) -> Purpose:
|
|
872
|
+
def function_args_to_output_purpose(args, environment: Environment) -> Purpose:
|
|
872
873
|
has_metric = False
|
|
873
874
|
has_non_constant = False
|
|
874
875
|
has_non_single_row_constant = False
|
|
875
876
|
if not args:
|
|
876
877
|
return Purpose.CONSTANT
|
|
877
878
|
for arg in args:
|
|
879
|
+
if isinstance(arg, ConceptRef):
|
|
880
|
+
arg = environment.concepts[arg.address]
|
|
878
881
|
purpose = argument_to_purpose(arg)
|
|
879
882
|
if purpose == Purpose.METRIC:
|
|
880
883
|
has_metric = True
|
trilogy/core/models/author.py
CHANGED
|
@@ -25,6 +25,7 @@ from pydantic import (
|
|
|
25
25
|
ValidationInfo,
|
|
26
26
|
computed_field,
|
|
27
27
|
field_validator,
|
|
28
|
+
model_validator,
|
|
28
29
|
)
|
|
29
30
|
|
|
30
31
|
from trilogy.constants import DEFAULT_NAMESPACE, MagicConstants
|
|
@@ -621,8 +622,8 @@ class Comparison(ConceptArgs, Mergeable, DataTyped, Namespaced, BaseModel):
|
|
|
621
622
|
return v.reference
|
|
622
623
|
return v
|
|
623
624
|
|
|
624
|
-
|
|
625
|
-
|
|
625
|
+
@model_validator(mode="after")
|
|
626
|
+
def validate_comparison(self):
|
|
626
627
|
if self.operator in (ComparisonOperator.IS, ComparisonOperator.IS_NOT):
|
|
627
628
|
if self.right != MagicConstants.NULL and DataType.BOOL != arg_to_datatype(
|
|
628
629
|
self.right
|
|
@@ -632,7 +633,6 @@ class Comparison(ConceptArgs, Mergeable, DataTyped, Namespaced, BaseModel):
|
|
|
632
633
|
)
|
|
633
634
|
elif self.operator in (ComparisonOperator.IN, ComparisonOperator.NOT_IN):
|
|
634
635
|
right_type = arg_to_datatype(self.right)
|
|
635
|
-
|
|
636
636
|
if isinstance(right_type, ListType) and not is_compatible_datatype(
|
|
637
637
|
arg_to_datatype(self.left), right_type.value_data_type
|
|
638
638
|
):
|
|
@@ -653,6 +653,8 @@ class Comparison(ConceptArgs, Mergeable, DataTyped, Namespaced, BaseModel):
|
|
|
653
653
|
f"Cannot compare {arg_to_datatype(self.left)} and {arg_to_datatype(self.right)} of different types with operator {self.operator} in {str(self)}"
|
|
654
654
|
)
|
|
655
655
|
|
|
656
|
+
return self
|
|
657
|
+
|
|
656
658
|
def __add__(self, other):
|
|
657
659
|
if other is None:
|
|
658
660
|
return self
|
|
@@ -1022,7 +1024,7 @@ class Concept(Addressable, DataTyped, ConceptArgs, Mergeable, Namespaced, BaseMo
|
|
|
1022
1024
|
keys = self.keys
|
|
1023
1025
|
|
|
1024
1026
|
if self.is_aggregate and isinstance(new_lineage, Function) and grain.components:
|
|
1025
|
-
grain_components = [
|
|
1027
|
+
grain_components: list[ConceptRef | Concept] = [
|
|
1026
1028
|
environment.concepts[c].reference for c in grain.components
|
|
1027
1029
|
]
|
|
1028
1030
|
new_lineage = AggregateWrapper(function=new_lineage, by=grain_components)
|
|
@@ -1847,9 +1849,6 @@ class AggregateWrapper(Mergeable, DataTyped, ConceptArgs, Namespaced, BaseModel)
|
|
|
1847
1849
|
function: Function
|
|
1848
1850
|
by: List[ConceptRef | Concept] = Field(default_factory=list)
|
|
1849
1851
|
|
|
1850
|
-
def __init__(self, **kwargs):
|
|
1851
|
-
super().__init__(**kwargs)
|
|
1852
|
-
|
|
1853
1852
|
@field_validator("by", mode="before")
|
|
1854
1853
|
@classmethod
|
|
1855
1854
|
def enforce_concept_ref(cls, v):
|
trilogy/core/models/build.py
CHANGED
|
@@ -262,11 +262,8 @@ class BuildGrain(BaseModel):
|
|
|
262
262
|
components: set[str] = Field(default_factory=set)
|
|
263
263
|
where_clause: Optional[BuildWhereClause] = None
|
|
264
264
|
|
|
265
|
-
def __init__(self, **kwargs):
|
|
266
|
-
super().__init__(**kwargs)
|
|
267
|
-
|
|
268
265
|
def without_condition(self):
|
|
269
|
-
return BuildGrain(components=self.components)
|
|
266
|
+
return BuildGrain.model_construct(components=self.components)
|
|
270
267
|
|
|
271
268
|
@classmethod
|
|
272
269
|
def from_concepts(
|
|
@@ -321,12 +318,12 @@ class BuildGrain(BaseModel):
|
|
|
321
318
|
# raise NotImplementedError(
|
|
322
319
|
# f"Cannot merge grains with where clauses, self {self.where_clause} other {other.where_clause}"
|
|
323
320
|
# )
|
|
324
|
-
return BuildGrain(
|
|
321
|
+
return BuildGrain.model_construct(
|
|
325
322
|
components=self.components.union(other.components), where_clause=where
|
|
326
323
|
)
|
|
327
324
|
|
|
328
325
|
def __sub__(self, other: "BuildGrain") -> "BuildGrain":
|
|
329
|
-
return BuildGrain(
|
|
326
|
+
return BuildGrain.model_construct(
|
|
330
327
|
components=self.components.difference(other.components),
|
|
331
328
|
where_clause=self.where_clause,
|
|
332
329
|
)
|
|
@@ -637,9 +634,6 @@ class BuildComparison(BuildConceptArgs, ConstantInlineable, BaseModel):
|
|
|
637
634
|
]
|
|
638
635
|
operator: ComparisonOperator
|
|
639
636
|
|
|
640
|
-
def __init__(self, *args, **kwargs) -> None:
|
|
641
|
-
super().__init__(*args, **kwargs)
|
|
642
|
-
|
|
643
637
|
def __add__(self, other):
|
|
644
638
|
if other is None:
|
|
645
639
|
return self
|
trilogy/core/models/execute.py
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from collections import defaultdict
|
|
4
|
-
from typing import
|
|
5
|
-
|
|
6
|
-
from pydantic import
|
|
4
|
+
from typing import Dict, List, Optional, Set, Union
|
|
5
|
+
|
|
6
|
+
from pydantic import (
|
|
7
|
+
BaseModel,
|
|
8
|
+
Field,
|
|
9
|
+
ValidationInfo,
|
|
10
|
+
computed_field,
|
|
11
|
+
field_validator,
|
|
12
|
+
model_validator,
|
|
13
|
+
)
|
|
7
14
|
|
|
8
15
|
from trilogy.constants import CONFIG, logger
|
|
9
16
|
from trilogy.core.constants import CONSTANT_DATASET
|
|
@@ -473,8 +480,8 @@ class BaseJoin(BaseModel):
|
|
|
473
480
|
left_datasource: Optional[Union[BuildDatasource, "QueryDatasource"]] = None
|
|
474
481
|
concept_pairs: list[ConceptPair] | None = None
|
|
475
482
|
|
|
476
|
-
|
|
477
|
-
|
|
483
|
+
@model_validator(mode="after")
|
|
484
|
+
def validate_join(self) -> "BaseJoin":
|
|
478
485
|
if (
|
|
479
486
|
self.left_datasource
|
|
480
487
|
and self.left_datasource.identifier == self.right_datasource.identifier
|
|
@@ -483,14 +490,18 @@ class BaseJoin(BaseModel):
|
|
|
483
490
|
f"Cannot join a dataself to itself, joining {self.left_datasource} and"
|
|
484
491
|
f" {self.right_datasource}"
|
|
485
492
|
)
|
|
486
|
-
final_concepts = []
|
|
487
493
|
|
|
488
|
-
#
|
|
494
|
+
# Early returns maintained as in original code
|
|
489
495
|
if self.concept_pairs:
|
|
490
|
-
return
|
|
496
|
+
return self
|
|
497
|
+
|
|
491
498
|
if self.concepts == []:
|
|
492
|
-
return
|
|
499
|
+
return self
|
|
500
|
+
|
|
501
|
+
# Validation logic
|
|
502
|
+
final_concepts = []
|
|
493
503
|
assert self.left_datasource and self.right_datasource
|
|
504
|
+
|
|
494
505
|
for concept in self.concepts or []:
|
|
495
506
|
include = True
|
|
496
507
|
for ds in [self.left_datasource, self.right_datasource]:
|
|
@@ -507,6 +518,7 @@ class BaseJoin(BaseModel):
|
|
|
507
518
|
)
|
|
508
519
|
if include:
|
|
509
520
|
final_concepts.append(concept)
|
|
521
|
+
|
|
510
522
|
if not final_concepts and self.concepts:
|
|
511
523
|
# if one datasource only has constants
|
|
512
524
|
# we can join on 1=1
|
|
@@ -519,11 +531,11 @@ class BaseJoin(BaseModel):
|
|
|
519
531
|
]
|
|
520
532
|
):
|
|
521
533
|
self.concepts = []
|
|
522
|
-
return
|
|
534
|
+
return self
|
|
523
535
|
# if everything is at abstract grain, we can skip joins
|
|
524
536
|
if all([c.grain.abstract for c in ds.output_concepts]):
|
|
525
537
|
self.concepts = []
|
|
526
|
-
return
|
|
538
|
+
return self
|
|
527
539
|
|
|
528
540
|
left_keys = [c.address for c in self.left_datasource.output_concepts]
|
|
529
541
|
right_keys = [c.address for c in self.right_datasource.output_concepts]
|
|
@@ -535,7 +547,9 @@ class BaseJoin(BaseModel):
|
|
|
535
547
|
f" right_keys {right_keys},"
|
|
536
548
|
f" provided join concepts {match_concepts}"
|
|
537
549
|
)
|
|
550
|
+
|
|
538
551
|
self.concepts = final_concepts
|
|
552
|
+
return self
|
|
539
553
|
|
|
540
554
|
@property
|
|
541
555
|
def unique_id(self) -> str:
|
trilogy/parsing/common.py
CHANGED
|
@@ -62,7 +62,7 @@ def process_function_arg(
|
|
|
62
62
|
operator=FunctionType.PARENTHETICAL,
|
|
63
63
|
arguments=processed,
|
|
64
64
|
output_datatype=arg_to_datatype(processed[0]),
|
|
65
|
-
output_purpose=function_args_to_output_purpose(processed),
|
|
65
|
+
output_purpose=function_args_to_output_purpose(processed, environment),
|
|
66
66
|
)
|
|
67
67
|
elif isinstance(arg, Function):
|
|
68
68
|
# if it's not an aggregate function, we can skip the virtual concepts
|
|
@@ -140,7 +140,7 @@ def get_purpose_and_keys(
|
|
|
140
140
|
args: Tuple[ConceptRef | Concept, ...] | None,
|
|
141
141
|
environment: Environment,
|
|
142
142
|
) -> Tuple[Purpose, set[str] | None]:
|
|
143
|
-
local_purpose = purpose or function_args_to_output_purpose(args)
|
|
143
|
+
local_purpose = purpose or function_args_to_output_purpose(args, environment)
|
|
144
144
|
if local_purpose in (Purpose.PROPERTY, Purpose.METRIC) and args:
|
|
145
145
|
keys = concept_list_to_keys(args, environment)
|
|
146
146
|
else:
|
|
@@ -548,7 +548,7 @@ def filter_item_to_concept(
|
|
|
548
548
|
|
|
549
549
|
else:
|
|
550
550
|
raise NotImplementedError(
|
|
551
|
-
f"Filter item with non ref content {parent.content} not yet supported"
|
|
551
|
+
f"Filter item with non ref content {parent.content} ({type(parent.content)}) not yet supported"
|
|
552
552
|
)
|
|
553
553
|
modifiers = get_upstream_modifiers(
|
|
554
554
|
cparent.concept_arguments, environment=environment
|
trilogy/parsing/parse_engine.py
CHANGED
|
@@ -1257,16 +1257,21 @@ class ParseToObjects(Transformer):
|
|
|
1257
1257
|
intersection = base.locally_derived.intersection(pre_keys)
|
|
1258
1258
|
if intersection:
|
|
1259
1259
|
for x in intersection:
|
|
1260
|
-
if (
|
|
1261
|
-
|
|
1262
|
-
== self.environment.concepts[x].derivation
|
|
1260
|
+
if str(base.local_concepts[x].lineage) == str(
|
|
1261
|
+
self.environment.concepts[x].lineage
|
|
1263
1262
|
):
|
|
1263
|
+
local = base.local_concepts[x]
|
|
1264
|
+
friendly_name = (
|
|
1265
|
+
local.name
|
|
1266
|
+
if local.namespace == DEFAULT_NAMESPACE
|
|
1267
|
+
else local.namespace
|
|
1268
|
+
)
|
|
1264
1269
|
raise NameShadowError(
|
|
1265
|
-
f"Select statement {base}
|
|
1270
|
+
f"Select statement {base} creates a new concept '{friendly_name}' with identical definition as the existing concept '{friendly_name}'. Replace {base.local_concepts[x].lineage} with a direct reference to {friendly_name}."
|
|
1266
1271
|
)
|
|
1267
1272
|
else:
|
|
1268
1273
|
raise NameShadowError(
|
|
1269
|
-
f"Select statement {base} creates new
|
|
1274
|
+
f"Select statement {base} creates new named concepts from calculations {list(intersection)} with identical name(s) to existing concept(s). Use new unique names for these."
|
|
1270
1275
|
)
|
|
1271
1276
|
return base
|
|
1272
1277
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|