-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: handle datetime in nosql_apply_parameters_to_query #299
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
import pyjq | ||
from aiohttp import ClientSession | ||
from jinja2 import Environment, StrictUndefined, Template, meta | ||
from jinja2.nativetypes import NativeEnvironment | ||
from pydantic import Field | ||
from toucan_data_sdk.utils.helpers import slugify | ||
|
||
|
@@ -16,7 +17,6 @@ | |
RE_PARAM = r'%\(([^(%\()]*)\)s' | ||
RE_JINJA = r'{{([^({{)}]*)}}' | ||
|
||
RE_PARAM_ALONE = r'^' + RE_PARAM + '$' | ||
RE_JINJA_ALONE = r'^' + RE_JINJA + '$' | ||
|
||
# Identify jinja params with no quotes around or complex condition | ||
|
@@ -71,26 +71,25 @@ def _render_query(query, parameters): | |
return {key: _render_query(value, parameters) for key, value in deepcopy(query).items()} | ||
elif isinstance(query, list): | ||
return [_render_query(elt, parameters) for elt in deepcopy(query)] | ||
elif type(query) is str: | ||
elif isinstance(query, str): | ||
if not _has_parameters(query): | ||
return query | ||
clean_p = deepcopy(parameters) | ||
|
||
# Replace param templating with jinja templating: | ||
query = re.sub(RE_PARAM, r'{{ \g<1> }}', query) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So easier ^^ By the way, I think we should progressively retire this parameter syntax in favor of Jinja one, which is simpler to read and write. Also, it's complex for users to have two possibilities that does the same thing. |
||
|
||
# Add quotes to string parameters to keep type if not complex | ||
if re.match(RE_PARAM_ALONE, query) or re.match(RE_JINJA_ALONE, query): | ||
clean_p = deepcopy(parameters) | ||
if re.match(RE_JINJA_ALONE, query): | ||
clean_p = _prepare_parameters(clean_p) | ||
|
||
# Render jinja then render parameters `%()s` | ||
res = Template(query).render(clean_p) % clean_p | ||
|
||
# Remove extra quotes with literal_eval | ||
try: | ||
res = ast.literal_eval(res) | ||
if isinstance(res, str): | ||
return res | ||
else: | ||
return _prepare_result(res) | ||
except (SyntaxError, ValueError): | ||
return res | ||
env = NativeEnvironment() | ||
res = env.from_string(query).render(clean_p) | ||
# NativeEnvironment's render() isn't recursive, so we need to | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not instantly clear to me what do you mean by "render is not recursive". (I tried this to test nested arrays, but obtained as expected: >>> env.from_string('{{ [punk, [ipa]] }}').render({'punk': ['pale', 'ale'], 'ipa': 10})
[['pale', 'ale'], [10]] ) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure ! >>> env.from_string('{{ x }}').render({'x': 1}) # we expect 1
1
>>> env.from_string('{{ x }}').render({'x': '1'}) # we expect '1'
1 # <- meh to handle this problem, a solution is to put strings inside quotes, this is what >>> env.from_string('{{ x }}').render({'x': '"1"'}) # we expect '1'
'1' # <- it works ! it also works if x is a list and we get one element from this list : >>> env.from_string('{{ x[0] }}').render({'x': ['"1"', '"2"']}) # we expect '1'
'1' but here's the 2nd problem : >>> env.from_string('{{ x }}').render({'x': ['"1"', '"2"']}) # we expect ['1', '2']
['"1"', '"2"'] # <- meh in this case, since the result is a |
||
# apply recursively the literal_eval by hand for lists and dicts: | ||
if isinstance(res, (list, dict)): | ||
return _prepare_result(res) | ||
return res | ||
else: | ||
return query | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great for checkboxes variables 👍