pytrilogy 0.0.3.24__tar.gz → 0.0.3.25__tar.gz

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.

Files changed (133) hide show
  1. {pytrilogy-0.0.3.24/pytrilogy.egg-info → pytrilogy-0.0.3.25}/PKG-INFO +1 -1
  2. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25/pytrilogy.egg-info}/PKG-INFO +1 -1
  3. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_parsing.py +4 -1
  4. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/__init__.py +1 -1
  5. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/models/author.py +13 -3
  6. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/models/core.py +13 -1
  7. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/dialect/base.py +1 -1
  8. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/parsing/parse_engine.py +31 -14
  9. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/LICENSE.md +0 -0
  10. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/README.md +0 -0
  11. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/pyproject.toml +0 -0
  12. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/pytrilogy.egg-info/SOURCES.txt +0 -0
  13. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/pytrilogy.egg-info/dependency_links.txt +0 -0
  14. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/pytrilogy.egg-info/entry_points.txt +0 -0
  15. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/pytrilogy.egg-info/requires.txt +0 -0
  16. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/pytrilogy.egg-info/top_level.txt +0 -0
  17. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/setup.cfg +0 -0
  18. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/setup.py +0 -0
  19. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_datatypes.py +0 -0
  20. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_declarations.py +0 -0
  21. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_derived_concepts.py +0 -0
  22. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_discovery_nodes.py +0 -0
  23. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_enums.py +0 -0
  24. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_environment.py +0 -0
  25. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_executor.py +0 -0
  26. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_functions.py +0 -0
  27. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_imports.py +0 -0
  28. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_metadata.py +0 -0
  29. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_models.py +0 -0
  30. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_multi_join_assignments.py +0 -0
  31. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_parse_engine.py +0 -0
  32. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_partial_handling.py +0 -0
  33. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_query_processing.py +0 -0
  34. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_query_render.py +0 -0
  35. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_select.py +0 -0
  36. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_show.py +0 -0
  37. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_statements.py +0 -0
  38. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_typing.py +0 -0
  39. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_undefined_concept.py +0 -0
  40. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_user_functions.py +0 -0
  41. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/tests/test_where_clause.py +0 -0
  42. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/authoring/__init__.py +0 -0
  43. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/compiler.py +0 -0
  44. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/constants.py +0 -0
  45. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/__init__.py +0 -0
  46. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/constants.py +0 -0
  47. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/enums.py +0 -0
  48. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/env_processor.py +0 -0
  49. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/environment_helpers.py +0 -0
  50. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/ergonomics.py +0 -0
  51. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/exceptions.py +0 -0
  52. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/functions.py +0 -0
  53. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/graph_models.py +0 -0
  54. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/internal.py +0 -0
  55. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/models/__init__.py +0 -0
  56. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/models/build.py +0 -0
  57. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/models/build_environment.py +0 -0
  58. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/models/datasource.py +0 -0
  59. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/models/environment.py +0 -0
  60. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/models/execute.py +0 -0
  61. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/optimization.py +0 -0
  62. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/optimizations/__init__.py +0 -0
  63. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/optimizations/base_optimization.py +0 -0
  64. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/optimizations/inline_constant.py +0 -0
  65. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/optimizations/inline_datasource.py +0 -0
  66. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/optimizations/predicate_pushdown.py +0 -0
  67. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/__init__.py +0 -0
  68. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/concept_strategies_v3.py +0 -0
  69. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/graph_utils.py +0 -0
  70. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/node_generators/__init__.py +0 -0
  71. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/node_generators/basic_node.py +0 -0
  72. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/node_generators/common.py +0 -0
  73. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/node_generators/filter_node.py +0 -0
  74. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/node_generators/group_node.py +0 -0
  75. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/node_generators/group_to_node.py +0 -0
  76. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/node_generators/multiselect_node.py +0 -0
  77. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/node_generators/node_merge_node.py +0 -0
  78. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/node_generators/rowset_node.py +0 -0
  79. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/node_generators/select_helpers/__init__.py +0 -0
  80. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/node_generators/select_helpers/datasource_injection.py +0 -0
  81. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/node_generators/select_merge_node.py +0 -0
  82. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/node_generators/select_node.py +0 -0
  83. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/node_generators/synonym_node.py +0 -0
  84. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/node_generators/union_node.py +0 -0
  85. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/node_generators/unnest_node.py +0 -0
  86. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/node_generators/window_node.py +0 -0
  87. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/nodes/__init__.py +0 -0
  88. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/nodes/base_node.py +0 -0
  89. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/nodes/filter_node.py +0 -0
  90. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/nodes/group_node.py +0 -0
  91. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/nodes/merge_node.py +0 -0
  92. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/nodes/select_node_v2.py +0 -0
  93. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/nodes/union_node.py +0 -0
  94. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/nodes/unnest_node.py +0 -0
  95. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/nodes/window_node.py +0 -0
  96. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/processing/utility.py +0 -0
  97. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/query_processor.py +0 -0
  98. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/statements/__init__.py +0 -0
  99. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/statements/author.py +0 -0
  100. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/statements/build.py +0 -0
  101. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/statements/common.py +0 -0
  102. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/core/statements/execute.py +0 -0
  103. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/dialect/__init__.py +0 -0
  104. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/dialect/bigquery.py +0 -0
  105. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/dialect/common.py +0 -0
  106. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/dialect/config.py +0 -0
  107. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/dialect/dataframe.py +0 -0
  108. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/dialect/duckdb.py +0 -0
  109. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/dialect/enums.py +0 -0
  110. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/dialect/postgres.py +0 -0
  111. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/dialect/presto.py +0 -0
  112. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/dialect/snowflake.py +0 -0
  113. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/dialect/sql_server.py +0 -0
  114. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/engine.py +0 -0
  115. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/executor.py +0 -0
  116. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/hooks/__init__.py +0 -0
  117. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/hooks/base_hook.py +0 -0
  118. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/hooks/graph_hook.py +0 -0
  119. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/hooks/query_debugger.py +0 -0
  120. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/metadata/__init__.py +0 -0
  121. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/parser.py +0 -0
  122. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/parsing/__init__.py +0 -0
  123. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/parsing/common.py +0 -0
  124. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/parsing/config.py +0 -0
  125. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/parsing/exceptions.py +0 -0
  126. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/parsing/helpers.py +0 -0
  127. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/parsing/render.py +0 -0
  128. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/parsing/trilogy.lark +0 -0
  129. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/py.typed +0 -0
  130. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/render.py +0 -0
  131. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/scripts/__init__.py +0 -0
  132. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/scripts/trilogy.py +0 -0
  133. {pytrilogy-0.0.3.24 → pytrilogy-0.0.3.25}/trilogy/utility.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytrilogy
3
- Version: 0.0.3.24
3
+ Version: 0.0.3.25
4
4
  Summary: Declarative, typed query language that compiles to SQL.
5
5
  Home-page:
6
6
  Author:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytrilogy
3
- Version: 0.0.3.24
3
+ Version: 0.0.3.25
4
4
  Summary: Declarative, typed query language that compiles to SQL.
5
5
  Home-page:
6
6
  Author:
@@ -657,7 +657,10 @@ key x int;
657
657
  assert isinstance(env.config.import_resolver, DictImportResolver)
658
658
  env.parse(
659
659
  """
660
- import test;
660
+ import std.geography;
661
+ import test;
662
+
663
+ key fun_lat float::latitude;
661
664
 
662
665
  select x % 10 -> x_mod_10;
663
666
 
@@ -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.24"
7
+ __version__ = "0.0.3.25"
8
8
 
9
9
  __all__ = ["parse", "Executor", "Dialects", "Environment", "CONFIG"]
@@ -255,7 +255,7 @@ class Parenthetical(
255
255
  return arg_to_datatype(self.content)
256
256
 
257
257
 
258
- class Conditional(Mergeable, ConceptArgs, Namespaced, BaseModel):
258
+ class Conditional(Mergeable, ConceptArgs, Namespaced, DataTyped, BaseModel):
259
259
  left: Expr
260
260
  right: Expr
261
261
  operator: BooleanOperator
@@ -357,6 +357,11 @@ class Conditional(Mergeable, ConceptArgs, Namespaced, BaseModel):
357
357
  output += self.right.existence_arguments
358
358
  return output
359
359
 
360
+ @property
361
+ def output_datatype(self):
362
+ # a conditional is always a boolean
363
+ return DataType.BOOL
364
+
360
365
  def decompose(self):
361
366
  chunks = []
362
367
  if self.operator == BooleanOperator.AND:
@@ -545,7 +550,7 @@ class Grain(Namespaced, BaseModel):
545
550
  return self.__add__(other)
546
551
 
547
552
 
548
- class Comparison(ConceptArgs, Mergeable, Namespaced, BaseModel):
553
+ class Comparison(ConceptArgs, Mergeable, DataTyped, Namespaced, BaseModel):
549
554
  left: Union[
550
555
  int,
551
556
  str,
@@ -745,6 +750,11 @@ class Comparison(ConceptArgs, Mergeable, Namespaced, BaseModel):
745
750
  output += self.right.existence_arguments
746
751
  return output
747
752
 
753
+ @property
754
+ def output_datatype(self):
755
+ # a conditional is always a boolean
756
+ return DataType.BOOL
757
+
748
758
 
749
759
  class SubselectComparison(Comparison):
750
760
  def __eq__(self, other):
@@ -1401,7 +1411,7 @@ def get_basic_type(
1401
1411
  if isinstance(type, NumericType):
1402
1412
  return DataType.NUMERIC
1403
1413
  if isinstance(type, TraitDataType):
1404
- return type.type
1414
+ return get_basic_type(type.type)
1405
1415
  return type
1406
1416
 
1407
1417
 
@@ -105,7 +105,7 @@ class DataType(Enum):
105
105
 
106
106
 
107
107
  class TraitDataType(BaseModel):
108
- type: DataType
108
+ type: DataType | NumericType | StructType | ListType | MapType
109
109
  traits: list[str]
110
110
 
111
111
  def __hash__(self):
@@ -134,6 +134,9 @@ class NumericType(BaseModel):
134
134
  precision: int = 20
135
135
  scale: int = 5
136
136
 
137
+ def __str__(self) -> str:
138
+ return f"Numeric({self.precision},{self.scale})"
139
+
137
140
  @property
138
141
  def data_type(self):
139
142
  return DataType.NUMERIC
@@ -356,12 +359,21 @@ def merge_datatypes(
356
359
 
357
360
  def is_compatible_datatype(left, right):
358
361
  # for unknown types, we can't make any assumptions
362
+ if all(
363
+ isinstance(x, NumericType)
364
+ or x in (DataType.INTEGER, DataType.FLOAT, DataType.NUMERIC)
365
+ for x in (left, right)
366
+ ):
367
+ return True
368
+ elif isinstance(left, NumericType) or isinstance(right, NumericType):
369
+ return False
359
370
  if right == DataType.UNKNOWN or left == DataType.UNKNOWN:
360
371
  return True
361
372
  if left == right:
362
373
  return True
363
374
  if {left, right} == {DataType.NUMERIC, DataType.FLOAT}:
364
375
  return True
376
+
365
377
  if {left, right} == {DataType.NUMERIC, DataType.INTEGER}:
366
378
  return True
367
379
  if {left, right} == {DataType.FLOAT, DataType.INTEGER}:
@@ -680,7 +680,7 @@ class BaseDialect:
680
680
  elif isinstance(e, datetime):
681
681
  return self.FUNCTION_MAP[FunctionType.DATETIME_LITERAL](e)
682
682
  elif isinstance(e, TraitDataType):
683
- return self.DATATYPE_MAP.get(e.type, e.type.value)
683
+ return self.render_expr(e.type, cte=cte, cte_map=cte_map)
684
684
  else:
685
685
  raise ValueError(f"Unable to render type {type(e)} {e}")
686
686
 
@@ -91,6 +91,7 @@ from trilogy.core.models.core import (
91
91
  TupleWrapper,
92
92
  arg_to_datatype,
93
93
  dict_to_map_wrapper,
94
+ is_compatible_datatype,
94
95
  list_to_wrapper,
95
96
  tuple_to_wrapper,
96
97
  )
@@ -146,6 +147,8 @@ SELF_LABEL = "root"
146
147
 
147
148
  MAX_PARSE_DEPTH = 10
148
149
 
150
+ STDLIB_ROOT = Path(__file__).parent.parent
151
+
149
152
 
150
153
  @dataclass
151
154
  class WholeGrainWrapper:
@@ -449,20 +452,27 @@ class ParseToObjects(Transformer):
449
452
  ) -> DataType | TraitDataType | ListType | StructType | MapType | NumericType:
450
453
  resolved = args[0]
451
454
  traits = args[2:]
455
+ base: DataType | TraitDataType | ListType | StructType | MapType | NumericType
452
456
  if isinstance(resolved, StructType):
453
- return resolved
457
+ base = resolved
454
458
  elif isinstance(resolved, ListType):
455
- return resolved
459
+ base = resolved
456
460
  elif isinstance(resolved, NumericType):
457
- return resolved
461
+ base = resolved
458
462
  elif isinstance(resolved, MapType):
459
- return resolved
460
- base = DataType(args[0].lower())
463
+ base = resolved
464
+ else:
465
+ base = DataType(args[0].lower())
461
466
  if traits:
462
467
  for trait in traits:
463
468
  if trait not in self.environment.data_types:
464
469
  raise ParseError(
465
- f"Invalid type trait {trait} for {base}, line {meta.line}"
470
+ f"Invalid trait (type) {trait} for {base}, line {meta.line}."
471
+ )
472
+ matched = self.environment.data_types[trait]
473
+ if not is_compatible_datatype(matched.type, base):
474
+ raise ParseError(
475
+ f"Invalid trait (type) {trait} for {base}, line {meta.line}. Trait expects type {matched.type}, has {base}"
466
476
  )
467
477
  return TraitDataType(type=base, traits=traits)
468
478
 
@@ -936,9 +946,12 @@ class ParseToObjects(Transformer):
936
946
  select=args[-1],
937
947
  )
938
948
 
939
- def resolve_import_address(self, address) -> str:
940
- if isinstance(
941
- self.environment.config.import_resolver, FileSystemImportResolver
949
+ def resolve_import_address(self, address, is_stdlib: bool = False) -> str:
950
+ if (
951
+ isinstance(
952
+ self.environment.config.import_resolver, FileSystemImportResolver
953
+ )
954
+ or is_stdlib
942
955
  ):
943
956
  with open(address, "r", encoding="utf-8") as f:
944
957
  text = f.read()
@@ -946,7 +959,7 @@ class ParseToObjects(Transformer):
946
959
  lookup = address
947
960
  if lookup not in self.environment.config.import_resolver.content:
948
961
  raise ImportError(
949
- f"Unable to import file {lookup}, not found in import resolver"
962
+ f"Unable to import file {lookup}, not found in imsport resolver"
950
963
  )
951
964
  text = self.environment.config.import_resolver.content[lookup]
952
965
  else:
@@ -964,13 +977,17 @@ class ParseToObjects(Transformer):
964
977
  cache_key = args[0]
965
978
  input_path = args[0]
966
979
  path = input_path.split(".")
967
-
968
- if isinstance(
980
+ is_stdlib = False
981
+ if path[0] == "std":
982
+ is_stdlib = True
983
+ target = join(STDLIB_ROOT, *path) + ".preql"
984
+ token_lookup: Path | str = Path(target)
985
+ elif isinstance(
969
986
  self.environment.config.import_resolver, FileSystemImportResolver
970
987
  ):
971
988
  target = join(self.environment.working_path, *path) + ".preql"
972
989
  # tokens + text are cached by path
973
- token_lookup: Path | str = Path(target)
990
+ token_lookup = Path(target)
974
991
  elif isinstance(self.environment.config.import_resolver, DictImportResolver):
975
992
  target = ".".join(path)
976
993
  token_lookup = target
@@ -991,7 +1008,7 @@ class ParseToObjects(Transformer):
991
1008
  raw_tokens = self.tokens[token_lookup]
992
1009
  text = self.text_lookup[token_lookup]
993
1010
  else:
994
- text = self.resolve_import_address(target)
1011
+ text = self.resolve_import_address(target, is_stdlib)
995
1012
  self.text_lookup[token_lookup] = text
996
1013
 
997
1014
  try:
File without changes
File without changes
File without changes
File without changes