pytrilogy 0.0.3.117__py3-none-any.whl → 0.0.3.119__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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytrilogy
3
- Version: 0.0.3.117
3
+ Version: 0.0.3.119
4
4
  Summary: Declarative, typed query language that compiles to SQL.
5
5
  Classifier: Programming Language :: Python
6
6
  Classifier: Programming Language :: Python :: 3
@@ -1,5 +1,5 @@
1
- pytrilogy-0.0.3.117.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
2
- trilogy/__init__.py,sha256=TkCDQL8X9qEaoFjTuzamNRfxRiggkAyy6htNlnHQ6XU,304
1
+ pytrilogy-0.0.3.119.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
2
+ trilogy/__init__.py,sha256=yAEhbbiEzNNNbrfLDM4oizZbA7BwdavMgSpAlAszpbk,304
3
3
  trilogy/constants.py,sha256=_Tm7YGaAZuxH77X5ve0TajU0dQD7RcGV6ECrTHRL3qQ,2678
4
4
  trilogy/engine.py,sha256=v4TpNktM4zZ9OX7jZH2nde4dpX5uAH2U23ELfULTCSg,2280
5
5
  trilogy/executor.py,sha256=uKlCnPp4FHkgsa_dDcQJ4y-ObtvKat2KFx05c-z1mZo,17885
@@ -28,17 +28,17 @@ trilogy/core/env_processor.py,sha256=H-rr2ALj31l5oh3FqeI47Qju6OOfiXBacXNJGNZ92zQ
28
28
  trilogy/core/environment_helpers.py,sha256=TRlqVctqIRBxzfjRBmpQsAVoiCcsEKBhG1B6PUE0l1M,12743
29
29
  trilogy/core/ergonomics.py,sha256=e-7gE29vPLFdg0_A1smQ7eOrUwKl5VYdxRSTddHweRA,1631
30
30
  trilogy/core/exceptions.py,sha256=axkVXYJYQXCCwMHwlyDA232g4tCOwdCZUt7eHeUMDMg,2829
31
- trilogy/core/functions.py,sha256=QidWH7dDjvLjXA0ujCkemUzYjkYmtMD2T78hnvk86K8,34876
31
+ trilogy/core/functions.py,sha256=yvy4t1pZmsdTpcP5gxPIpS2G2ULNotmmF7HZcYDH6bE,35857
32
32
  trilogy/core/graph_models.py,sha256=4EWFTHGfYd72zvS2HYoV6hm7nMC_VEd7vWr6txY-ig0,3400
33
33
  trilogy/core/internal.py,sha256=r9QagDB2GvpqlyD_I7VrsfbVfIk5mnok2znEbv72Aa4,2681
34
34
  trilogy/core/optimization.py,sha256=eKieOaWXUtoNTVQbThGA5tqrI06ZR6SUFOqGe4Jw0k4,9262
35
35
  trilogy/core/query_processor.py,sha256=rMrtLSQxVm7yeyh0nWjDNI9nnu4Xi0NgHvBJ14gvu4I,20384
36
36
  trilogy/core/utility.py,sha256=3VC13uSQWcZNghgt7Ot0ZTeEmNqs__cx122abVq9qhM,410
37
37
  trilogy/core/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
- trilogy/core/models/author.py,sha256=YnBwxanbn9uBAExz5POM0_RFw9GIHmjfLZRVzA10Gws,85862
38
+ trilogy/core/models/author.py,sha256=gsKPOwgnebnAs2HV72ZHdXYfoUzDs8jQNse8vEwtG3k,86081
39
39
  trilogy/core/models/build.py,sha256=zVHD8jo8V8E0aGWtobzXG7hY3VjLChiW4s1QBx9sD5k,72938
40
40
  trilogy/core/models/build_environment.py,sha256=mpx7MKGc60fnZLVdeLi2YSREy7eQbQYycCrP4zF-rHU,5258
41
- trilogy/core/models/core.py,sha256=iT9WdZoiXeglmUHWn6bZyXCTBpkApTGPKtNm_Mhbu_g,12987
41
+ trilogy/core/models/core.py,sha256=mv1QOxf-6uGoWpfwuucNAW3W_ZZGQuxtnPWAXhQsxSI,13290
42
42
  trilogy/core/models/datasource.py,sha256=wogTevZ-9CyUW2a8gjzqMCieircxi-J5lkI7EOAZnck,9596
43
43
  trilogy/core/models/environment.py,sha256=-r6_imqkJ10iPTbWGrdfeF2Th480UKLsG8ihACyqO8w,28823
44
44
  trilogy/core/models/execute.py,sha256=3fgEdho2e7S0outq91cCzb9jFwz6L1hTbsTrJwGvIFs,42311
@@ -117,9 +117,9 @@ trilogy/parsing/common.py,sha256=GijDRpysULL6vQWpFcjgxVASuTWXUVUi5fILHvjzkbg,355
117
117
  trilogy/parsing/config.py,sha256=Z-DaefdKhPDmSXLgg5V4pebhSB0h590vI0_VtHnlukI,111
118
118
  trilogy/parsing/exceptions.py,sha256=Xwwsv2C9kSNv2q-HrrKC1f60JNHShXcCMzstTSEbiCw,154
119
119
  trilogy/parsing/helpers.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
120
- trilogy/parsing/parse_engine.py,sha256=oCHQz5JaWvOu6u3IkpBWC8FwWCpDt0GNat5fxi9x0Eo,86742
120
+ trilogy/parsing/parse_engine.py,sha256=j0lBbJGObcptw4S7xng2hy-Pv-u5aSfFuxYk6TZvciY,87661
121
121
  trilogy/parsing/render.py,sha256=k7MNp8EBTqVBSVqFlgTHSwIhfSKLyJfSeb2fSbt9dVA,24307
122
- trilogy/parsing/trilogy.lark,sha256=mbwwPlz__xO3ydLXXSum0zZK8k8QyifPTJdyNyMDlSY,17280
122
+ trilogy/parsing/trilogy.lark,sha256=_FW9Hq7Xo6KDrf1JUxD9NBM0Zn9OyoZzWHj97zFqy-M,17449
123
123
  trilogy/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
124
124
  trilogy/scripts/trilogy.py,sha256=1L0XrH4mVHRt1C9T1HnaDv2_kYEfbWTb5_-cBBke79w,3774
125
125
  trilogy/std/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -130,10 +130,11 @@ trilogy/std/geography.preql,sha256=1A9Sq5PPMBnEPPf7f-rPVYxJfsnWpQ8oV_k4Fm3H2dU,6
130
130
  trilogy/std/metric.preql,sha256=DRECGhkMyqfit5Fl4Ut9zbWrJuSMI1iO9HikuyoBpE0,421
131
131
  trilogy/std/money.preql,sha256=XWwvAV3WxBsHX9zfptoYRnBigcfYwrYtBHXTME0xJuQ,2082
132
132
  trilogy/std/net.preql,sha256=WZCuvH87_rZntZiuGJMmBDMVKkdhTtxeHOkrXNwJ1EE,416
133
- trilogy/std/ranking.preql,sha256=LDoZrYyz4g3xsII9XwXfmstZD-_92i1Eox1UqkBIfi8,83
133
+ trilogy/std/ranking.preql,sha256=zDdmHcTerlCjaHDdVyjGTgcc2hAhnlDM_q5tiw0MPGE,108
134
134
  trilogy/std/report.preql,sha256=LbV-XlHdfw0jgnQ8pV7acG95xrd1-p65fVpiIc-S7W4,202
135
- pytrilogy-0.0.3.117.dist-info/METADATA,sha256=abcEvZwmW_1-WWPIeGOqghBy9u2MD3Rh0xCMbxQzA78,12911
136
- pytrilogy-0.0.3.117.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
137
- pytrilogy-0.0.3.117.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
138
- pytrilogy-0.0.3.117.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
139
- pytrilogy-0.0.3.117.dist-info/RECORD,,
135
+ trilogy/std/semantic.preql,sha256=k9_k672nUb5MKjSD1DW5jjn_odoYHl0yNeRPOjFabsE,95
136
+ pytrilogy-0.0.3.119.dist-info/METADATA,sha256=VyzNM-tcKiVnWkJP1MRh61gk61nRWjcIn7I3yRKiSHU,12911
137
+ pytrilogy-0.0.3.119.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
138
+ pytrilogy-0.0.3.119.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
139
+ pytrilogy-0.0.3.119.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
140
+ pytrilogy-0.0.3.119.dist-info/RECORD,,
trilogy/__init__.py CHANGED
@@ -4,6 +4,6 @@ from trilogy.dialect.enums import Dialects
4
4
  from trilogy.executor import Executor
5
5
  from trilogy.parser import parse
6
6
 
7
- __version__ = "0.0.3.117"
7
+ __version__ = "0.0.3.119"
8
8
 
9
9
  __all__ = ["parse", "Executor", "Dialects", "Environment", "CONFIG"]
trilogy/core/functions.py CHANGED
@@ -19,6 +19,7 @@ from trilogy.core.models.author import (
19
19
  Concept,
20
20
  ConceptRef,
21
21
  Conditional,
22
+ CustomType,
22
23
  Function,
23
24
  Parenthetical,
24
25
  UndefinedConcept,
@@ -40,6 +41,11 @@ from trilogy.core.models.environment import Environment
40
41
  GENERIC_ARGS = Concept | ConceptRef | Function | str | int | float | date | datetime
41
42
 
42
43
 
44
+ CUSTOM_PLACEHOLDER = CustomType(
45
+ name="__placeholder__", type=DataType.UNKNOWN, drop_on=[], add_on=[]
46
+ )
47
+
48
+
43
49
  @dataclass
44
50
  class FunctionConfig:
45
51
  arg_count: int = 1
@@ -99,7 +105,18 @@ def get_attr_datatype(
99
105
 
100
106
  def get_cast_output_type(
101
107
  args: list[Any],
102
- ) -> DataType:
108
+ ) -> DataType | TraitDataType:
109
+ base = arg_to_datatype(args[0])
110
+ if isinstance(base, TraitDataType):
111
+ traits = base.traits
112
+ else:
113
+ traits = []
114
+ if isinstance(args[1], TraitDataType):
115
+ return TraitDataType(
116
+ type=args[1].type, traits=list(set(traits + args[1].traits))
117
+ )
118
+ elif traits:
119
+ return TraitDataType(type=args[1], traits=traits)
103
120
  return args[1]
104
121
 
105
122
 
@@ -995,6 +1012,19 @@ class FunctionFactory:
995
1012
  final_output_type = base_output_type
996
1013
  else:
997
1014
  raise SyntaxError(f"Could not determine output type for {operator}")
1015
+ if isinstance(final_output_type, TraitDataType) and self.environment:
1016
+ final_output_type = TraitDataType(
1017
+ type=final_output_type.type,
1018
+ traits=[
1019
+ x
1020
+ for x in final_output_type.traits
1021
+ if operator
1022
+ not in self.environment.data_types.get(
1023
+ x, CUSTOM_PLACEHOLDER
1024
+ ).drop_on
1025
+ ],
1026
+ )
1027
+
998
1028
  if not output_purpose:
999
1029
  if operator in FunctionClass.AGGREGATE_FUNCTIONS.value:
1000
1030
  output_purpose = Purpose.METRIC
@@ -2598,11 +2598,16 @@ class ArgBinding(Namespaced, DataTyped, BaseModel):
2598
2598
 
2599
2599
  class CustomType(BaseModel):
2600
2600
  name: str
2601
- type: DataType
2601
+ type: DataType | list[DataType]
2602
+ drop_on: list[FunctionType] = Field(default_factory=list)
2603
+ add_on: list[FunctionType] = Field(default_factory=list)
2602
2604
 
2603
2605
  def with_namespace(self, namespace: str) -> "CustomType":
2604
2606
  return CustomType.model_construct(
2605
- name=address_with_namespace(self.name, namespace), type=self.type
2607
+ name=address_with_namespace(self.name, namespace),
2608
+ type=self.type,
2609
+ drop_on=self.drop_on,
2610
+ add_on=self.add_on,
2606
2611
  )
2607
2612
 
2608
2613
 
@@ -99,6 +99,7 @@ class DataType(Enum):
99
99
 
100
100
  # PARSING
101
101
  UNKNOWN = "unknown"
102
+ ANY = "any"
102
103
 
103
104
  @property
104
105
  def data_type(self):
@@ -411,6 +412,12 @@ def merge_datatypes(
411
412
 
412
413
  def is_compatible_datatype(left, right):
413
414
  # for unknown types, we can't make any assumptions
415
+ if isinstance(left, list):
416
+ return any(is_compatible_datatype(ltype, right) for ltype in left)
417
+ if isinstance(right, list):
418
+ return any(is_compatible_datatype(left, rtype) for rtype in right)
419
+ if left == DataType.ANY or right == DataType.ANY:
420
+ return True
414
421
  if all(
415
422
  isinstance(x, NumericType)
416
423
  or x in (DataType.INTEGER, DataType.FLOAT, DataType.NUMERIC)
@@ -171,6 +171,16 @@ class FunctionBindingType:
171
171
  type: DataType | TraitDataType | None = None
172
172
 
173
173
 
174
+ @dataclass
175
+ class DropOn:
176
+ functions: List[FunctionType]
177
+
178
+
179
+ @dataclass
180
+ class AddOn:
181
+ functions: List[FunctionType]
182
+
183
+
174
184
  with open(join(dirname(__file__), "trilogy.lark"), "r") as f:
175
185
  PARSER = Lark(
176
186
  f.read(),
@@ -1512,11 +1522,35 @@ class ParseToObjects(Transformer):
1512
1522
  def function(self, meta: Meta, args) -> Function:
1513
1523
  return args[0]
1514
1524
 
1525
+ @v_args(meta=True)
1526
+ def type_drop_clause(self, meta: Meta, args) -> DropOn:
1527
+ return DropOn([FunctionType(x) for x in args])
1528
+
1529
+ @v_args(meta=True)
1530
+ def type_add_clause(self, meta: Meta, args) -> AddOn:
1531
+ return AddOn([FunctionType(x) for x in args])
1532
+
1515
1533
  @v_args(meta=True)
1516
1534
  def type_declaration(self, meta: Meta, args) -> TypeDeclaration:
1517
1535
  key = args[0]
1518
- datatype = args[1]
1519
- new = CustomType(name=key, type=datatype)
1536
+ datatype: list[DataType] = [x for x in args[1:] if isinstance(x, DataType)]
1537
+ if len(datatype) == 1:
1538
+ final_datatype: list[DataType] | DataType = datatype[0]
1539
+ else:
1540
+ final_datatype = datatype
1541
+ add_on = None
1542
+ drop_on = None
1543
+ for x in args[1:]:
1544
+ if isinstance(x, AddOn):
1545
+ add_on = x
1546
+ elif isinstance(x, DropOn):
1547
+ drop_on = x
1548
+ new = CustomType(
1549
+ name=key,
1550
+ type=final_datatype,
1551
+ drop_on=drop_on.functions if drop_on else [],
1552
+ add_on=add_on.functions if add_on else [],
1553
+ )
1520
1554
  self.environment.data_types[key] = new
1521
1555
  return TypeDeclaration(type=new)
1522
1556
 
@@ -2349,7 +2383,7 @@ def inject_context_maker(pos: int, text: str, span: int = 40) -> str:
2349
2383
  rcap = ""
2350
2384
  # if it goes beyond the end of text, no ...
2351
2385
  # if it terminates on a space, no need for ...
2352
- if not after[-1].isspace() and not (end > len(text)):
2386
+ if after and not after[-1].isspace() and not (end > len(text)):
2353
2387
  rcap = "..."
2354
2388
  lcap = ""
2355
2389
  if start > 0 and not before[0].isspace():
@@ -2444,8 +2478,6 @@ def parse_text(
2444
2478
  else:
2445
2479
  new_pos = pos
2446
2480
  e.interactive_parser.feed_token(Token("IDENTIFIER", e.token.value))
2447
- next(e.interactive_parser.iter_parse())
2448
-
2449
2481
  raise _create_syntax_error(201, new_pos, text)
2450
2482
  except UnexpectedToken:
2451
2483
  pass
@@ -109,7 +109,9 @@
109
109
  raw_function: "def" IDENTIFIER "(" function_binding_list ")" "->" expr
110
110
 
111
111
  // TYPE blocks
112
- type_declaration: "type" IDENTIFIER data_type
112
+ type_drop_clause: "DROP" IDENTIFIER ("|" IDENTIFIER)*
113
+ //type_add_clause: "ADD" IDENTIFIER ("|" IDENTIFIER)* type_add_clause?
114
+ type_declaration: "type" IDENTIFIER data_type ("|" data_type)* type_drop_clause?
113
115
 
114
116
  // user_id where state = Mexico
115
117
  _filter_alt: (IDENTIFIER | literal | "(" expr ")") "?" conditional
trilogy/std/ranking.preql CHANGED
@@ -4,3 +4,4 @@ type score int;
4
4
  type position int;
5
5
  type index int;
6
6
  type grade int;
7
+ type letter_grade string;
@@ -0,0 +1,6 @@
1
+
2
+
3
+ type identifier any;
4
+ type flag any
5
+ drop sum|count|avg|add|subtract|multiply|divide|mod
6
+ ;