pytrilogy 0.0.3.89__py3-none-any.whl → 0.0.3.91__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.89.dist-info → pytrilogy-0.0.3.91.dist-info}/METADATA +1 -1
- {pytrilogy-0.0.3.89.dist-info → pytrilogy-0.0.3.91.dist-info}/RECORD +14 -14
- trilogy/__init__.py +1 -1
- trilogy/core/models/author.py +9 -3
- trilogy/core/models/core.py +14 -8
- trilogy/core/processing/node_generators/filter_node.py +9 -3
- trilogy/dialect/base.py +1 -1
- trilogy/dialect/bigquery.py +1 -1
- trilogy/executor.py +12 -4
- trilogy/parsing/parse_engine.py +9 -0
- {pytrilogy-0.0.3.89.dist-info → pytrilogy-0.0.3.91.dist-info}/WHEEL +0 -0
- {pytrilogy-0.0.3.89.dist-info → pytrilogy-0.0.3.91.dist-info}/entry_points.txt +0 -0
- {pytrilogy-0.0.3.89.dist-info → pytrilogy-0.0.3.91.dist-info}/licenses/LICENSE.md +0 -0
- {pytrilogy-0.0.3.89.dist-info → pytrilogy-0.0.3.91.dist-info}/top_level.txt +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
pytrilogy-0.0.3.
|
|
2
|
-
trilogy/__init__.py,sha256=
|
|
1
|
+
pytrilogy-0.0.3.91.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
|
|
2
|
+
trilogy/__init__.py,sha256=LDWJhBs1R3AQp5R7V_F0oNbHt99WNfQUp0xPRujT930,303
|
|
3
3
|
trilogy/compiler.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
trilogy/constants.py,sha256=eKb_EJvSqjN9tGbdVEViwdtwwh8fZ3-jpOEDqL71y70,1691
|
|
5
5
|
trilogy/engine.py,sha256=OK2RuqCIUId6yZ5hfF8J1nxGP0AJqHRZiafcowmW0xc,1728
|
|
6
|
-
trilogy/executor.py,sha256=
|
|
6
|
+
trilogy/executor.py,sha256=tcowEz8I7zbwLnuTr7BlGJ5wnt1JKBNffXbm5ywkNv8,17032
|
|
7
7
|
trilogy/parser.py,sha256=o4cfk3j3yhUFoiDKq9ZX_GjBF3dKhDjXEwb63rcBkBM,293
|
|
8
8
|
trilogy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
9
|
trilogy/render.py,sha256=qQWwduymauOlB517UtM-VGbVe8Cswa4UJub5aGbSO6c,1512
|
|
@@ -23,10 +23,10 @@ trilogy/core/optimization.py,sha256=ojpn-p79lr03SSVQbbw74iPCyoYpDYBmj1dbZ3oXCjI,
|
|
|
23
23
|
trilogy/core/query_processor.py,sha256=5aFgv-2LVM1Uku9cR_tFuTRDwyLnxc95bCMAHeFy2AY,20332
|
|
24
24
|
trilogy/core/utility.py,sha256=3VC13uSQWcZNghgt7Ot0ZTeEmNqs__cx122abVq9qhM,410
|
|
25
25
|
trilogy/core/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
|
-
trilogy/core/models/author.py,sha256=
|
|
26
|
+
trilogy/core/models/author.py,sha256=wiKmEIouIVuzaYSM30PGon_FA9nowtDgnyLO-x5znBI,80180
|
|
27
27
|
trilogy/core/models/build.py,sha256=CyrSo4xgU-uDKW3xUVYs5cTk3Z3Z2BMWdGQNHnHZOqU,66127
|
|
28
28
|
trilogy/core/models/build_environment.py,sha256=s_C9xAHuD3yZ26T15pWVBvoqvlp2LdZ8yjsv2_HdXLk,5363
|
|
29
|
-
trilogy/core/models/core.py,sha256=
|
|
29
|
+
trilogy/core/models/core.py,sha256=NOvonI4Ip4thpz5WoJZWbbBa44PFfpd2hXGx2Cbi4CE,12521
|
|
30
30
|
trilogy/core/models/datasource.py,sha256=wogTevZ-9CyUW2a8gjzqMCieircxi-J5lkI7EOAZnck,9596
|
|
31
31
|
trilogy/core/models/environment.py,sha256=0IHSCFf5e5b4LPQN3vmjumtfM1iD1tN4WMoUr0UqxZI,27855
|
|
32
32
|
trilogy/core/models/execute.py,sha256=sVWhjwWull-T6pUJizhrYVGCWHY3eZivVN6KNlhcHig,41839
|
|
@@ -46,7 +46,7 @@ trilogy/core/processing/node_generators/__init__.py,sha256=iVJ-crowPxYeut-hFjyEj
|
|
|
46
46
|
trilogy/core/processing/node_generators/basic_node.py,sha256=TLZCv4WS196a-0g5xgKuJGthnGP8Ugm46iz85_3NIY4,5626
|
|
47
47
|
trilogy/core/processing/node_generators/common.py,sha256=PdysdroW9DUADP7f5Wv_GKPUyCTROZV1g3L45fawxi8,9443
|
|
48
48
|
trilogy/core/processing/node_generators/constant_node.py,sha256=LfpDq2WrBRZ3tGsLxw77LuigKfhbteWWh9L8BGdMGwk,1146
|
|
49
|
-
trilogy/core/processing/node_generators/filter_node.py,sha256=
|
|
49
|
+
trilogy/core/processing/node_generators/filter_node.py,sha256=ArBsQJl-4fWBJWCE28CRQ7UT7ErnFfbcseoQQZrBodY,11220
|
|
50
50
|
trilogy/core/processing/node_generators/group_node.py,sha256=1QJhRxsTklJ5xq8wHlAURZaN9gL9FPpeCa1OJ7IwXnY,6769
|
|
51
51
|
trilogy/core/processing/node_generators/group_to_node.py,sha256=jKcNCDOY6fNblrdZwaRU0sbUSr9H0moQbAxrGgX6iGA,3832
|
|
52
52
|
trilogy/core/processing/node_generators/multiselect_node.py,sha256=GWV5yLmKTe1yyPhN60RG1Rnrn4ktfn9lYYXi_FVU4UI,7061
|
|
@@ -77,8 +77,8 @@ trilogy/core/statements/build.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
|
|
|
77
77
|
trilogy/core/statements/common.py,sha256=KxEmz2ySySyZ6CTPzn0fJl5NX2KOk1RPyuUSwWhnK1g,759
|
|
78
78
|
trilogy/core/statements/execute.py,sha256=pfr1CZ_Cx1qQ-7LDyRI0JUfvtxBr_GGv-VeqiAjr43g,1406
|
|
79
79
|
trilogy/dialect/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
80
|
-
trilogy/dialect/base.py,sha256=
|
|
81
|
-
trilogy/dialect/bigquery.py,sha256=
|
|
80
|
+
trilogy/dialect/base.py,sha256=_L5wHBHz8v4Us3tu4QIupKuaObmyhWhyDuroT95wUbo,48228
|
|
81
|
+
trilogy/dialect/bigquery.py,sha256=XS3hpybeowgfrOrkycAigAF3NX2YUzTzfgE6f__2fT4,4316
|
|
82
82
|
trilogy/dialect/common.py,sha256=tSthIZOXXRPQ4KeMKnDDsH7KlTmf2EVqigVtLyoc4zc,6071
|
|
83
83
|
trilogy/dialect/config.py,sha256=olnyeVU5W5T6b9-dMeNAnvxuPlyc2uefb7FRME094Ec,3834
|
|
84
84
|
trilogy/dialect/dataframe.py,sha256=RUbNgReEa9g3pL6H7fP9lPTrAij5pkqedpZ99D8_5AE,1522
|
|
@@ -98,7 +98,7 @@ trilogy/parsing/common.py,sha256=yV1AckK0h8u1OFeGQBTMu-wuW5m63c5CcZuPicsTH_w,306
|
|
|
98
98
|
trilogy/parsing/config.py,sha256=Z-DaefdKhPDmSXLgg5V4pebhSB0h590vI0_VtHnlukI,111
|
|
99
99
|
trilogy/parsing/exceptions.py,sha256=Xwwsv2C9kSNv2q-HrrKC1f60JNHShXcCMzstTSEbiCw,154
|
|
100
100
|
trilogy/parsing/helpers.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
101
|
-
trilogy/parsing/parse_engine.py,sha256=
|
|
101
|
+
trilogy/parsing/parse_engine.py,sha256=fgqCtV6sf9HrkViEjf6XXdRpPf4hJ1gSyzLXZ9sLBHs,80148
|
|
102
102
|
trilogy/parsing/render.py,sha256=HSNntD82GiiwHT-TWPLXAaIMWLYVV5B5zQEsgwrHIBE,19605
|
|
103
103
|
trilogy/parsing/trilogy.lark,sha256=ySzMMLxyPjn74MjFHZxXPTW-jHW68KLPJpiszPvZaO0,15780
|
|
104
104
|
trilogy/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -111,8 +111,8 @@ trilogy/std/money.preql,sha256=XWwvAV3WxBsHX9zfptoYRnBigcfYwrYtBHXTME0xJuQ,2082
|
|
|
111
111
|
trilogy/std/net.preql,sha256=WZCuvH87_rZntZiuGJMmBDMVKkdhTtxeHOkrXNwJ1EE,416
|
|
112
112
|
trilogy/std/ranking.preql,sha256=LDoZrYyz4g3xsII9XwXfmstZD-_92i1Eox1UqkBIfi8,83
|
|
113
113
|
trilogy/std/report.preql,sha256=LbV-XlHdfw0jgnQ8pV7acG95xrd1-p65fVpiIc-S7W4,202
|
|
114
|
-
pytrilogy-0.0.3.
|
|
115
|
-
pytrilogy-0.0.3.
|
|
116
|
-
pytrilogy-0.0.3.
|
|
117
|
-
pytrilogy-0.0.3.
|
|
118
|
-
pytrilogy-0.0.3.
|
|
114
|
+
pytrilogy-0.0.3.91.dist-info/METADATA,sha256=_W2oS79HhEjdCvg8ZApmI5siy5k513pXXCO541NVziQ,9589
|
|
115
|
+
pytrilogy-0.0.3.91.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
116
|
+
pytrilogy-0.0.3.91.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
|
|
117
|
+
pytrilogy-0.0.3.91.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
|
|
118
|
+
pytrilogy-0.0.3.91.dist-info/RECORD,,
|
trilogy/__init__.py
CHANGED
trilogy/core/models/author.py
CHANGED
|
@@ -659,6 +659,12 @@ class Comparison(ConceptArgs, Mergeable, DataTyped, Namespaced, BaseModel):
|
|
|
659
659
|
def validate_comparison(self):
|
|
660
660
|
left_type = arg_to_datatype(self.left)
|
|
661
661
|
right_type = arg_to_datatype(self.right)
|
|
662
|
+
left_name = (
|
|
663
|
+
left_type.name if isinstance(left_type, DataType) else str(left_type)
|
|
664
|
+
)
|
|
665
|
+
right_name = (
|
|
666
|
+
right_type.name if isinstance(right_type, DataType) else str(right_type)
|
|
667
|
+
)
|
|
662
668
|
if self.operator in (ComparisonOperator.IS, ComparisonOperator.IS_NOT):
|
|
663
669
|
if self.right != MagicConstants.NULL and DataType.BOOL != right_type:
|
|
664
670
|
raise SyntaxError(
|
|
@@ -676,12 +682,12 @@ class Comparison(ConceptArgs, Mergeable, DataTyped, Namespaced, BaseModel):
|
|
|
676
682
|
left_type, right_type
|
|
677
683
|
):
|
|
678
684
|
raise SyntaxError(
|
|
679
|
-
f"Cannot compare {
|
|
685
|
+
f"Cannot compare {left_name} and {right_name} with operator {self.operator} in {str(self)}"
|
|
680
686
|
)
|
|
681
687
|
else:
|
|
682
688
|
if not is_compatible_datatype(left_type, right_type):
|
|
683
689
|
raise SyntaxError(
|
|
684
|
-
f"Cannot compare {
|
|
690
|
+
f"Cannot compare {left_name} ({self.left}) and {right_name} ({self.right}) of different types with operator {self.operator.value} in {str(self)}"
|
|
685
691
|
)
|
|
686
692
|
|
|
687
693
|
return self
|
|
@@ -1660,7 +1666,6 @@ class Function(DataTyped, ConceptArgs, Mergeable, Namespaced, BaseModel):
|
|
|
1660
1666
|
def parse_output_datatype(cls, v, info: ValidationInfo):
|
|
1661
1667
|
values = info.data
|
|
1662
1668
|
if values.get("operator") == FunctionType.ATTR_ACCESS:
|
|
1663
|
-
print(v)
|
|
1664
1669
|
if isinstance(v, StructType):
|
|
1665
1670
|
raise SyntaxError
|
|
1666
1671
|
return v
|
|
@@ -2470,6 +2475,7 @@ FuncArgs = (
|
|
|
2470
2475
|
| CaseElse
|
|
2471
2476
|
| WindowItem
|
|
2472
2477
|
| FilterItem
|
|
2478
|
+
| bool
|
|
2473
2479
|
| int
|
|
2474
2480
|
| float
|
|
2475
2481
|
| DatePart
|
trilogy/core/models/core.py
CHANGED
|
@@ -264,9 +264,10 @@ class StructType(BaseModel):
|
|
|
264
264
|
class ListWrapper(Generic[VT], UserList):
|
|
265
265
|
"""Used to distinguish parsed list objects from other lists"""
|
|
266
266
|
|
|
267
|
-
def __init__(self, *args, type: DataType, **kwargs):
|
|
267
|
+
def __init__(self, *args, type: DataType, nullable: bool = False, **kwargs):
|
|
268
268
|
super().__init__(*args, **kwargs)
|
|
269
269
|
self.type = type
|
|
270
|
+
self.nullable = nullable
|
|
270
271
|
|
|
271
272
|
@classmethod
|
|
272
273
|
def __get_pydantic_core_schema__(
|
|
@@ -315,10 +316,11 @@ class MapWrapper(Generic[KT, VT], UserDict):
|
|
|
315
316
|
class TupleWrapper(Generic[VT], tuple):
|
|
316
317
|
"""Used to distinguish parsed tuple objects from other tuples"""
|
|
317
318
|
|
|
318
|
-
def __init__(self, val, type: DataType, **kwargs):
|
|
319
|
+
def __init__(self, val, type: DataType, nullable: bool = False, **kwargs):
|
|
319
320
|
super().__init__()
|
|
320
321
|
self.type = type
|
|
321
322
|
self.val = val
|
|
323
|
+
self.nullable = nullable
|
|
322
324
|
|
|
323
325
|
def __getnewargs__(self):
|
|
324
326
|
return (self.val, self.type)
|
|
@@ -344,15 +346,19 @@ class TupleWrapper(Generic[VT], tuple):
|
|
|
344
346
|
|
|
345
347
|
|
|
346
348
|
def list_to_wrapper(args):
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
349
|
+
rtypes = [arg_to_datatype(arg) for arg in args]
|
|
350
|
+
types = [arg for arg in rtypes if arg != DataType.NULL]
|
|
351
|
+
if not len(set(types)) == 1:
|
|
352
|
+
raise SyntaxError(f"Cannot create a list with this set of types: {set(types)}")
|
|
353
|
+
return ListWrapper(args, type=types[0], nullable=DataType.NULL in rtypes)
|
|
350
354
|
|
|
351
355
|
|
|
352
356
|
def tuple_to_wrapper(args):
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
357
|
+
rtypes = [arg_to_datatype(arg) for arg in args]
|
|
358
|
+
types = [arg for arg in rtypes if arg != DataType.NULL]
|
|
359
|
+
if not len(set(types)) == 1:
|
|
360
|
+
raise SyntaxError(f"Cannot create a tuple with this set of types: {set(types)}")
|
|
361
|
+
return TupleWrapper(args, type=types[0], nullable=DataType.NULL in rtypes)
|
|
356
362
|
|
|
357
363
|
|
|
358
364
|
def dict_to_map_wrapper(arg):
|
|
@@ -77,11 +77,17 @@ def build_parent_concepts(
|
|
|
77
77
|
True if (conditions and conditions == filter_where) else False
|
|
78
78
|
)
|
|
79
79
|
|
|
80
|
+
exact_partial_matches = True
|
|
80
81
|
for x in local_optional:
|
|
81
82
|
if isinstance(x.lineage, FILTER_TYPES):
|
|
82
|
-
if
|
|
83
|
+
if set([x.address for x in x.lineage.where.concept_arguments]) == set(
|
|
84
|
+
[x.address for x in filter_where.concept_arguments]
|
|
85
|
+
):
|
|
86
|
+
exact_partial_matches = (
|
|
87
|
+
exact_partial_matches and x.lineage.where == filter_where
|
|
88
|
+
)
|
|
83
89
|
logger.info(
|
|
84
|
-
f"{padding(depth)}{LOGGER_PREFIX} fetching parents for peer {x}
|
|
90
|
+
f"{padding(depth)}{LOGGER_PREFIX} fetching parents for peer {x.address} (of {concept.address})"
|
|
85
91
|
)
|
|
86
92
|
|
|
87
93
|
for arg in x.lineage.content_concept_arguments:
|
|
@@ -100,7 +106,7 @@ def build_parent_concepts(
|
|
|
100
106
|
if x.address in same_filter_optional:
|
|
101
107
|
continue
|
|
102
108
|
extra_row_level_optional.append(x)
|
|
103
|
-
is_optimized_pushdown = pushdown_filter_to_parent(
|
|
109
|
+
is_optimized_pushdown = exact_partial_matches and pushdown_filter_to_parent(
|
|
104
110
|
local_optional, conditions, filter_where, same_filter_optional, depth
|
|
105
111
|
)
|
|
106
112
|
if not is_optimized_pushdown:
|
trilogy/dialect/base.py
CHANGED
|
@@ -174,7 +174,7 @@ FUNCTION_MAP = {
|
|
|
174
174
|
FunctionType.CAST: lambda x: f"cast({x[0]} as {x[1]})",
|
|
175
175
|
FunctionType.CASE: lambda x: render_case(x),
|
|
176
176
|
FunctionType.SPLIT: lambda x: f"split({x[0]}, {x[1]})",
|
|
177
|
-
FunctionType.IS_NULL: lambda x: f"
|
|
177
|
+
FunctionType.IS_NULL: lambda x: f"{x[0]} is null",
|
|
178
178
|
FunctionType.BOOL: lambda x: f"CASE WHEN {x[0]} THEN TRUE ELSE FALSE END",
|
|
179
179
|
FunctionType.PARENTHETICAL: lambda x: f"({x[0]})",
|
|
180
180
|
# Complex
|
trilogy/dialect/bigquery.py
CHANGED
|
@@ -24,7 +24,7 @@ FUNCTION_MAP = {
|
|
|
24
24
|
FunctionType.LIKE: lambda x: (
|
|
25
25
|
f" CASE WHEN {x[0]} like {x[1]} THEN True ELSE False END"
|
|
26
26
|
),
|
|
27
|
-
FunctionType.IS_NULL: lambda x: f"
|
|
27
|
+
FunctionType.IS_NULL: lambda x: f"{x[0]} IS NULL",
|
|
28
28
|
FunctionType.MINUTE: lambda x: f"EXTRACT(MINUTE from {x[0]})",
|
|
29
29
|
FunctionType.SECOND: lambda x: f"EXTRACT(SECOND from {x[0]})",
|
|
30
30
|
FunctionType.HOUR: lambda x: f"EXTRACT(HOUR from {x[0]})",
|
trilogy/executor.py
CHANGED
|
@@ -6,7 +6,7 @@ from typing import Any, Generator, List, Optional, Protocol
|
|
|
6
6
|
from sqlalchemy import text
|
|
7
7
|
from sqlalchemy.engine import CursorResult
|
|
8
8
|
|
|
9
|
-
from trilogy.constants import Rendering, logger
|
|
9
|
+
from trilogy.constants import MagicConstants, Rendering, logger
|
|
10
10
|
from trilogy.core.enums import FunctionType, Granularity, IOType
|
|
11
11
|
from trilogy.core.models.author import Concept, ConceptRef, Function
|
|
12
12
|
from trilogy.core.models.build import BuildFunction
|
|
@@ -388,6 +388,11 @@ class Executor(object):
|
|
|
388
388
|
if persist and isinstance(x, ProcessedQueryPersist):
|
|
389
389
|
self.environment.add_datasource(x.datasource)
|
|
390
390
|
|
|
391
|
+
def _atom_to_value(self, val: Any) -> Any:
|
|
392
|
+
if val == MagicConstants.NULL:
|
|
393
|
+
return None
|
|
394
|
+
return val
|
|
395
|
+
|
|
391
396
|
def _concept_to_value(
|
|
392
397
|
self,
|
|
393
398
|
concept: Concept,
|
|
@@ -402,12 +407,15 @@ class Executor(object):
|
|
|
402
407
|
):
|
|
403
408
|
rval = concept.lineage.arguments[0]
|
|
404
409
|
if isinstance(rval, ListWrapper):
|
|
405
|
-
return [x for x in rval]
|
|
410
|
+
return [self._atom_to_value(x) for x in rval]
|
|
406
411
|
if isinstance(rval, MapWrapper):
|
|
407
412
|
# duckdb expects maps in this format as variables
|
|
408
413
|
if self.dialect == Dialects.DUCK_DB:
|
|
409
|
-
return {
|
|
410
|
-
|
|
414
|
+
return {
|
|
415
|
+
"key": [self._atom_to_value(x) for x in rval],
|
|
416
|
+
"value": [self._atom_to_value(rval[x]) for x in rval],
|
|
417
|
+
}
|
|
418
|
+
return {k: self._atom_to_value(v) for k, v in rval.items()}
|
|
411
419
|
# if isinstance(rval, ConceptRef):
|
|
412
420
|
# return self._concept_to_value(self.environment.concepts[rval.address], local_concepts=local_concepts)
|
|
413
421
|
return rval
|
trilogy/parsing/parse_engine.py
CHANGED
|
@@ -2040,6 +2040,15 @@ class ParseToObjects(Transformer):
|
|
|
2040
2040
|
|
|
2041
2041
|
@v_args(meta=True)
|
|
2042
2042
|
def fnot(self, meta, args):
|
|
2043
|
+
if arg_to_datatype(args[0]) == DataType.BOOL:
|
|
2044
|
+
return Comparison(
|
|
2045
|
+
left=self.function_factory.create_function(
|
|
2046
|
+
[args[0], False], FunctionType.COALESCE, meta
|
|
2047
|
+
),
|
|
2048
|
+
operator=ComparisonOperator.EQ,
|
|
2049
|
+
right=False,
|
|
2050
|
+
meta=meta,
|
|
2051
|
+
)
|
|
2043
2052
|
return self.function_factory.create_function(args, FunctionType.IS_NULL, meta)
|
|
2044
2053
|
|
|
2045
2054
|
@v_args(meta=True)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|