-
Notifications
You must be signed in to change notification settings - Fork 6
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
Example tags #8
Comments
We could also have one that removes indentation from a triple-quoted string, like from textwrap import dd
def main():
code = dd"""
def f(x, y):
print(x, x+y)
"""
eval(code) instead of having to place the text flush left (breaking the visual indentation) or call |
This could be especially helpful when you have multi-line text you inserting. Here's an example with complex regular expressions: VERSION = textwrap.dedent(r'''
(?:
( \d+ ) # <major>
\.
( \d+ ) # <minor>
(?:
\.
( \d+ ) # <micro>
)?
(
( a | b | c | rc | f ) # <level>
( \d+ ) # <serial>
)?
)
'''
DATE = textwrap.dedent(r'''
(?:
( \d{4} ) # <year>
-
( \d\d ) # <month>
-
( \d\d ) # <day>
)
'''
REGEX = re.compile(rf'''
^
(?:
(?:
( v )? # <prefix>
{VERSION}
)
|
(?:
{DATE}
)
)
$
''', re.VERBOSE) I've had to deal with this in a number of projects. Without any extra effort, the resulting patterns are harder to read, which matters a lot when you are trying to debug a regex. A Another interesting variation would be a similar tag in the re module, for verbose patterns like the ones above. |
There's potential utility for a built-in This is the nature of having metacharacters - we have to distinguish them from the code that's using them (whether Python, regex minilanguage, or |
@gvanrossum See https://github.com/jimbaker/tagstr/blob/main/examples/code.py, which implements a fairly minimal Python code templating tag,
(Note that It does do the autodedent, plus supporting interpolation. Interestingly it can do stuff like this, where we have code inserted into code. I think it's sufficiently white-space aware, although clearly Python is not a Lisp with lots of parentheses.
It feels like there's something potentially useful here for templating code. I would like to cover examples like the ones seen in |
Okay, so the weird thing is that you have to write I wouldn't get too tied to dataclasses here, they're stdlib magic and we're more concerned about performance there than about readability of the implementation. :-) |
@ericsnowcurrently It would be interesting to implement a minimal
as we can see with the zeroth implementation of
which results in something like the following:
In particular, we can ignore |
Yes, that sounds like a very good nice simplification in usage! Most tags will have a natural string representation and corresponding usage. (Additional methods for the rest.) Note that I had a workaround for this in the shell example, where I used the fact
Hah. Now arguably there might a suitable |
Maybe there could be a built-in ‘re’ tag that compiles a regex. Somewhere
could do `re”a.*z”.search(line)`. (Hm, that might look like line noise to
some. Then again that is in regex’s nature. :-)
…--
--Guido (mobile)
|
One that could be interesting would be a tag that parses an RST or Markdown string and produces a tree of |
This makes sense to me - basically if we have a DSL that would benefit from interpolation and/or recursive construction, it seems like the tag string support is actually quite nice. Let's work through an example!
So far I don't think we have any tags that would be candidates for the stdlib. I was initially thinking we might need |
I updated the example
|
I implemented the It's possible this might actually be useful! Although calling it |
The catch with a tag for regular expressions is that the exiting "r" prefix is usually important for regular expressions. |
If it's correct to |
That's why the current proposal always passes the "raw mode" string to the tag function, i.e. |
Maybe a some_dir = "dir1"
list_of_dirs = ["dir3", "dir4"]
something = "special.txt"
assert (
path"/{some_dir}/dir2/{list_of_dirs}/this_is_{something}.txt"
== Path("/", some_dir, "dir2", *list_of_dirs, f"this_is_{something}.txt")
) |
That example is only somewhat compelling because pathlib's Path("/") / some_dir / "dir2" / Path(*list_of_dirs) / f"this_is_{something}.txt" It's longer but such complicated paths are uncommon. Though maybe the example would be more compelling if it referred to a real use case? Spam and ham aside, abstract examples don't speak to the reader as much as examples that look like something you'd actually use? E.g. an example using a |
I added an example So given
it does the following:
This particular tag would need more work for real usage, but it seems possibly useful. |
Cool. It looks like it would have to have complete knowledge of SQL grammar to be able to decide how to do the quoting, right? I am a little hesitant about How would you do a "prepare" style command? I guess you wouldn't. |
I think the only way you'd want to use this is to build a parameterized query. For example, I can't imagine wanting to allow x = 'e t'
sql'creat{x}able {table_name} (name, first_appeared)' Most if not all database engines cache parameterized queries, so I'm not sure how useful "prepare" is any more. |
I don't believe so. See for example @ericvsmith 's example:
results in this syntactically invalid SQL:
which raises this error, Arguably this is a correct interpolation.
For sure. This tag really gives access to all of SQL. So there's no need for a standard Bobby Tables SQL injection attack, this tag is directly enabling:
and having the A real tag built around this should make it clear what is being enabled, and where any specific interpolations can happen. I'm pretty sure the placeholder rewrite is safe because it uses the SQL
For this example tag, it might make more sense to have it support
This concern certainly does not apply to SQLite. I'm not certain about any other SQL dialects at this point (I would agree with @ericvsmith in general on this, other than to think that SQL is so varied in its implementations). |
I updated the example
I also identified some additional changes that can be done, such as supporting recursive construction of the statement. |
One rather cool thing is being able to see this, given the support for the
|
I completely revamped the So this looks like the following:
This was motivated in part because if one looks at the sqlite3 reference manual, it becomes apparent that there is no easy way to identify where a placeholder vs an identifier could go, without writing a parser for the SQL dialect. While there are a few SQL parsers on PyPI that potentially be used here, with suitable interpolation points being placed to work with them, I didn't want to rely on them for the PEP. I also removed the support for |
Closing this out. We have written some interesting examples. Future work can look at internationalization, Latex, etc, in separate issues. |
Some example tags we can implement. Let's update this list over time with linked issues and any new tags that might be useful.
html
- tutorial - I am working in a branch #1 - updated in https://github.com/jimbaker/tagstr/blob/main/examples/htmlbuilder.pyhtml
- tutorial - subset of https://viewdom.readthedocs.io/en/latest/ or similar package - Codegen function from a tag string to support ReactPy's virtual DOM #9template
- calling a template with**kwargs
- Using templates defined in another scope #2fl
- lambda-wrapped expressions - support lazy f-strings -fl
tag - Supporting lazy version of f-strings #6sh
- another example of interpolating expressions, this time for shell usage - https://github.com/jimbaker/tagstr/blob/main/examples/shell.pysql
- interpolates SQL statements, with support for qmarks/named params, identifier quoting, and subqueries (target sqlite3, but applicable to other SQL dialects) - https://github.com/jimbaker/tagstr/blob/main/examples/sql.pynumexpr
- expression rewriting with lexical scope - so something like the numexpr library with lambda lifting - Rewriting expressions, using their lexical scope #10code
- code templating tag, as discussed directly in this issuelatex
- raw string - \LaTeX generation, such as tables, arrays, or other fragments that would benefit from having tag supporti18n
or_
- get the source text string, including the formatspeci
- PEP 501 interpolation template - some significant subset of functionality should be supportable, although the log records is a can of apparent worms - Comparison to PEP 501 #7The text was updated successfully, but these errors were encountered: