Open jimbaker opened 11 months ago
I'll file this under "things I would have never thought of." 😉
I don't believe this next point would affect this, but I'll describe anyway, just in case. (And also, I wanted to bring it up.) Other template languages have filters. E.g. {{ items.getBalance() | safe }}
. Two operations in one interpolation.
Not a big deal per se for us, as Python 3.12 and PEP 701 have Python expressions. We don't have to wire in any special parsing as the filter is just a normal Python expression. Except...I don't think that's a valid expression, nor do I think Python has a filter-like syntax. OTOH, I think you've thought about this kind of piping.
Coming back to your point about looping, just want to ensure if you do have some kind of multi-stage "fluent" expressions in the loop, that it doesn't have a consequence.
First, this does work with f-strings, and by extension tag strings:
from typing import Any
from html import escape
class Safe:
def __ror__(self, __value: Any) -> str:
return escape(str(__value))
safe = Safe()
class Account:
def __init__(self, amount):
self.amount = amount
def __str__(self):
return f'${self.amount}'
def get_balance(self):
return self
def test_pipe():
account = Account('<bad>data</bad>')
assert f'Your balance is {account.get_balance() | safe}' == \
'Your balance is $<bad>data</bad>'
Secondly, fluent expressions like that don't have any special impact here. The only possibility is if the tag doesn't fully evaluate its args before returning; and those args depend on cell vars, which are modified by a loop.
So it takes a special tag function to do this (like the fl
example), in a specific context - running in a loop, but not actually evaluating it until later. But in the case of logging
this occurs immediately. A sequence diagram would be helpful here. I will put something together.
Also if you want safe
to work as a function call, simple add __call__
to the Safe
class.
I added a test for using a pipe for filters: https://github.com/pauleveritt/fdom/blob/main/tests/test_pipe.py
Given that all interpolations are lambda wrapped in tag strings, this common issue seen in working with closed over variables - as implemented with cell vars - might be considered to be a potential issue in using tag strings:
https://pylint.readthedocs.io/en/latest/user_guide/messages/warning/cell-var-from-loop.html
It was also recently discussed in this YouTube segment, which popped up as a suggested video for me: https://www.youtube.com/watch?v=fZE6ZWde-Os
Note that a tag function implementation controls the order of evaluation. In most cases, upon the evaluation of a tag string, all interpolations are evaluated with
getvalue
(or not). From outside this function call, it's no different than standard evaluation, and the ordering of evaluation inside the function call is not visible (unless we are working with code that is doing monkeypatching or is threaded, but no different again).However, it is possible for a tag string to defer evaluation, as seen in the
fl
strings example. But in this particular case, the use of the specific logger method (.info
, etc) ensures that the evaluation is fully done by that calling method.Are there other cases to consider?
This consideration should discussed in the PEP.