Skip to content

Commit 0cb2e7e

Browse files
committed
added *target tuple assignment
1 parent 99788ec commit 0cb2e7e

File tree

2 files changed

+27
-3
lines changed

2 files changed

+27
-3
lines changed

custom_components/pyscript/eval.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -611,15 +611,31 @@ async def recurse_assign(self, lhs, val):
611611
except AttributeError:
612612
raise TypeError("cannot unpack non-iterable object")
613613
sentinel = object()
614-
for lhs_elt in lhs.elts:
614+
for lhs_idx, lhs_elt in enumerate(lhs.elts):
615615
val_elt = next(val_iter, sentinel)
616616
if val_elt is sentinel:
617-
raise TypeError(
617+
raise ValueError(
618618
f"too few values to unpack (expected {len(lhs.elts)})"
619619
)
620+
if isinstance(lhs_elt, ast.Starred):
621+
star_lhs = [val_elt, *val_iter]
622+
star_len = len(star_lhs) - (len(lhs.elts) - lhs_idx - 1)
623+
if star_len < 0:
624+
raise ValueError(
625+
f"too few values to unpack (expected at least {len(lhs.elts) - 1})"
626+
)
627+
star_name = lhs_elt.value.id
628+
for lhs_idx, lhs_elt in enumerate(lhs.elts[lhs_idx + 1 :]):
629+
await self.recurse_assign(lhs_elt, star_lhs[star_len + lhs_idx])
630+
await self.recurse_assign(
631+
ast.Name(id=star_name, ctx=ast.Store()), star_lhs[0:star_len]
632+
)
633+
return
620634
await self.recurse_assign(lhs_elt, val_elt)
621635
if next(val_iter, sentinel) is not sentinel:
622-
raise TypeError(f"too many values to unpack (expected {len(lhs.elts)})")
636+
raise ValueError(
637+
f"too many values to unpack (expected {len(lhs.elts)})"
638+
)
623639
elif isinstance(lhs, ast.Subscript):
624640
var = await self.aeval(lhs.value)
625641
if isinstance(lhs.slice, ast.Index):

tests/custom_components/pyscript/test_unit_eval.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,10 @@
153153
"tuples = [(1, 2), (3, 4), (5, 6)]; a, b = zip(*tuples); [a, b]",
154154
[(1, 3, 5), (2, 4, 6)],
155155
],
156+
["a, *y, w, z = range(3); [a, y, w, z]", [0, [], 1, 2]],
157+
["a, *y, w, z = range(4); [a, y, w, z]", [0, [1], 2, 3]],
158+
["a, *y, w, z = range(6); [a, y, w, z]", [0, [1, 2, 3], 4, 5]],
159+
["x = [0, 1]; i = 0; i, x[i] = 1, 2; [i, x]", [1, [0, 2]]],
156160
["Foo = type('Foo', (), {'x': 100}); Foo.x = 10; Foo.x", 10],
157161
["Foo = type('Foo', (), {'x': 100}); Foo.x += 10; Foo.x", 110],
158162
["Foo = [type('Foo', (), {'x': 100})]; Foo[0].x = 10; Foo[0].x", 10],
@@ -698,6 +702,10 @@ def test_eval(hass):
698702
"(x, y) = 1",
699703
"Exception in test line 1 column 9: cannot unpack non-iterable object",
700704
],
705+
[
706+
"a, *y, w, z = range(2)",
707+
"Exception in test line 1 column 0: too few values to unpack (expected at least 3)",
708+
],
701709
[
702710
"assert 1 == 0, 'this is an error'",
703711
"Exception in test line 1 column 15: this is an error",

0 commit comments

Comments
 (0)