diff options
author | Matt Trescott <mtc@melexis.com> | 2022-11-10 10:30:21 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-11-15 09:07:35 -0500 |
commit | 2c0f1e7df0fe7a9b0687143a4f442994081430c6 (patch) | |
tree | 14651d18b345834467c27b20e73fda65a397600d | |
parent | 0c4e737ff7d2a586c42f848441fef1386f2900e0 (diff) | |
download | mako-2c0f1e7df0fe7a9b0687143a4f442994081430c6.tar.gz |
Support nested tuple unpacking in for loops
Fixed issue where unpacking nested tuples in a for loop using would raise a
"couldn't apply loop context" error if the loop context was used. The regex
used to match the for loop expression now allows the list of loop variables
to contain parenthesized sub-tuples. Pull request courtesy Matt Trescott.
For example:
~~~
for (key1, val1), (key2, val2) in itertools.pairwise(dict.items()):
...
~~~
This is really just "kicking the can down the road" so to speak, because
it doesn't allow an infinite number of layers of tuples, but
it helps somewhat.
Closes: #368
Pull-request: https://github.com/sqlalchemy/mako/pull/368
Pull-request-sha: 3f15a87266a36306826d460cddc7699dd62a9c43
Change-Id: I52915acb8904daf7071d8c92e1de352f200131ec
-rw-r--r-- | doc/build/unreleased/368.rst | 9 | ||||
-rw-r--r-- | mako/codegen.py | 9 | ||||
-rw-r--r-- | test/test_loop.py | 10 |
3 files changed, 26 insertions, 2 deletions
diff --git a/doc/build/unreleased/368.rst b/doc/build/unreleased/368.rst new file mode 100644 index 0000000..73d4bcb --- /dev/null +++ b/doc/build/unreleased/368.rst @@ -0,0 +1,9 @@ +.. change:: + :tags: bug, codegen + :tickets: 368 + + Fixed issue where unpacking nested tuples in a for loop using would raise a + "couldn't apply loop context" error if the loop context was used. The regex + used to match the for loop expression now allows the list of loop variables + to contain parenthesized sub-tuples. Pull request courtesy Matt Trescott. + diff --git a/mako/codegen.py b/mako/codegen.py index a9dbcb6..d1d2c20 100644 --- a/mako/codegen.py +++ b/mako/codegen.py @@ -1251,8 +1251,13 @@ class _Identifiers: _FOR_LOOP = re.compile( - r"^for\s+((?:\(?)\s*[A-Za-z_][A-Za-z_0-9]*" - r"(?:\s*,\s*(?:[A-Za-z_][A-Za-z0-9_]*),??)*\s*(?:\)?))\s+in\s+(.*):" + r"^for\s+((?:\(?)\s*" + r"(?:\(?)\s*[A-Za-z_][A-Za-z_0-9]*" + r"(?:\s*,\s*(?:[A-Za-z_][A-Za-z_0-9]*),??)*\s*(?:\)?)" + r"(?:\s*,\s*(?:" + r"(?:\(?)\s*[A-Za-z_][A-Za-z_0-9]*" + r"(?:\s*,\s*(?:[A-Za-z_][A-Za-z_0-9]*),??)*\s*(?:\)?)" + r"),??)*\s*(?:\)?))\s+in\s+(.*):" ) diff --git a/test/test_loop.py b/test/test_loop.py index d048ed0..2c11000 100644 --- a/test/test_loop.py +++ b/test/test_loop.py @@ -31,6 +31,16 @@ class TestLoop(unittest.TestCase): "x", "[y+1 for y in [1, 2, 3]]", ), + ( + "for ((key1, val1), (key2, val2)) in pairwise(dict.items()):", + "((key1, val1), (key2, val2))", + "pairwise(dict.items())", + ), + ( + "for (key1, val1), (key2, val2) in pairwise(dict.items()):", + "(key1, val1), (key2, val2)", + "pairwise(dict.items())", + ), ): match = _FOR_LOOP.match(statement) assert match and match.groups() == (target_list, expression_list) |