Skip to content

Commit 2d0ef4b

Browse files
contextualization mechanism - dedicated unit tests
1 parent 9b2e131 commit 2d0ef4b

File tree

2 files changed

+37
-6
lines changed

2 files changed

+37
-6
lines changed

tests/unit/iql/test_iql_parser.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,44 @@
11
import re
2-
from typing import List
2+
from typing import List, Union
33

44
import pytest
55

6+
from dbally.context import BaseCallerContext
67
from dbally.iql import IQLArgumentParsingError, IQLQuery, IQLUnsupportedSyntaxError, syntax
78
from dbally.iql._exceptions import IQLArgumentValidationError, IQLFunctionNotExists
89
from dbally.iql._processor import IQLProcessor
910
from dbally.views.exposed_functions import ExposedFunction, MethodParamWithTyping
1011

1112

13+
class TestCustomContext(BaseCallerContext):
14+
city: str
15+
16+
17+
class AnotherTestCustomContext(BaseCallerContext):
18+
some_field: str
19+
20+
1221
async def test_iql_parser():
22+
custom_context = TestCustomContext(city="cracow")
23+
custom_context2 = AnotherTestCustomContext(some_field="aaa")
24+
1325
parsed = await IQLQuery.parse(
14-
"not (filter_by_name(['John', 'Anne']) and filter_by_city('cracow') and filter_by_company('deepsense.ai'))",
26+
"not (filter_by_name(['John', 'Anne']) and filter_by_city(BaseCallerContext()) and filter_by_company('deepsense.ai'))",
1527
allowed_functions=[
1628
ExposedFunction(
1729
name="filter_by_name", description="", parameters=[MethodParamWithTyping(name="name", type=List[str])]
1830
),
1931
ExposedFunction(
20-
name="filter_by_city", description="", parameters=[MethodParamWithTyping(name="city", type=str)]
32+
name="filter_by_city",
33+
description="",
34+
parameters=[MethodParamWithTyping(name="city", type=Union[str, TestCustomContext])],
35+
context_class=TestCustomContext,
2136
),
2237
ExposedFunction(
2338
name="filter_by_company", description="", parameters=[MethodParamWithTyping(name="company", type=str)]
2439
),
2540
],
41+
contexts=[custom_context, custom_context2],
2642
)
2743

2844
not_op = parsed.root
@@ -37,7 +53,7 @@ async def test_iql_parser():
3753
assert name_filter.arguments[0] == ["John", "Anne"]
3854

3955
assert isinstance(city_filter, syntax.FunctionCall)
40-
assert city_filter.arguments[0] == "cracow"
56+
assert city_filter.arguments[0] is custom_context
4157

4258
assert isinstance(company_filter, syntax.FunctionCall)
4359
assert company_filter.arguments[0] == "deepsense.ai"

tests/unit/views/test_sqlalchemy_base.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
# pylint: disable=missing-docstring, missing-return-doc, missing-param-doc, disallowed-name
22

33
import re
4+
from typing import Union
45

56
import sqlalchemy
67

8+
from dbally.context import BaseCallerContext
79
from dbally.iql import IQLQuery
810
from dbally.views.decorators import view_filter
911
from dbally.views.sqlalchemy_base import SqlAlchemyBaseView
1012

1113

14+
class SomeTestContext(BaseCallerContext):
15+
age: int
16+
17+
1218
class MockSqlAlchemyView(SqlAlchemyBaseView):
1319
"""
1420
Mock class for testing the SqlAlchemyBaseView
@@ -22,12 +28,20 @@ def method_foo(self, idx: int) -> sqlalchemy.ColumnElement:
2228
"""
2329
Some documentation string
2430
"""
31+
2532
return sqlalchemy.literal(idx)
2633

2734
@view_filter()
2835
async def method_bar(self, city: str, year: int) -> sqlalchemy.ColumnElement:
2936
return sqlalchemy.literal(f"hello {city} in {year}")
3037

38+
@view_filter()
39+
async def method_baz(self, age: Union[int, SomeTestContext]) -> sqlalchemy.ColumnElement:
40+
if isinstance(age, SomeTestContext):
41+
return sqlalchemy.literal(age.age)
42+
43+
return sqlalchemy.literal(age)
44+
3145

3246
def normalize_whitespace(s: str) -> str:
3347
"""
@@ -44,9 +58,10 @@ async def test_filter_sql_generation() -> None:
4458
mock_connection = sqlalchemy.create_mock_engine("postgresql://", executor=None)
4559
mock_view = MockSqlAlchemyView(mock_connection.engine)
4660
query = await IQLQuery.parse(
47-
'method_foo(1) and method_bar("London", 2020)',
61+
'method_foo(1) and method_bar("London", 2020) and method_baz(BaseCallerContext())',
4862
allowed_functions=mock_view.list_filters(),
63+
contexts=[SomeTestContext(age=69)],
4964
)
5065
await mock_view.apply_filters(query)
5166
sql = normalize_whitespace(mock_view.execute(dry_run=True).context["sql"])
52-
assert sql == "SELECT 'test' AS foo WHERE 1 AND 'hello London in 2020'"
67+
assert sql == "SELECT 'test' AS foo WHERE 1 AND 'hello London in 2020' AND 69"

0 commit comments

Comments
 (0)