Skip to content

Commit b5bd968

Browse files
committed
redo of tuple starred assignments; on mismatch exception, no variables are assigned
1 parent 7c087e7 commit b5bd968

File tree

5 files changed

+37
-44
lines changed

5 files changed

+37
-44
lines changed

custom_components/pyscript/eval.py

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -607,35 +607,37 @@ async def recurse_assign(self, lhs, val):
607607
"""Recursive assignment."""
608608
if isinstance(lhs, ast.Tuple):
609609
try:
610-
val_iter = val.__iter__()
611-
except AttributeError:
610+
vals = [*(val.__iter__())]
611+
except Exception: # pylint: disable=broad-except
612612
raise TypeError("cannot unpack non-iterable object")
613-
sentinel = object()
614-
for lhs_idx, lhs_elt in enumerate(lhs.elts):
615-
val_elt = next(val_iter, sentinel)
616-
if val_elt is sentinel:
617-
raise ValueError(
618-
f"too few values to unpack (expected {len(lhs.elts)})"
619-
)
613+
got_star = 0
614+
for lhs_elt in lhs.elts:
620615
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_idx2, lhs_elt in enumerate(lhs.elts[lhs_idx + 1 :]):
629-
await self.recurse_assign(lhs_elt, star_lhs[star_len + lhs_idx2])
630-
await self.recurse_assign(
631-
ast.Name(id=star_name, ctx=ast.Store()), star_lhs[0:star_len]
632-
)
633-
return
634-
await self.recurse_assign(lhs_elt, val_elt)
635-
if next(val_iter, sentinel) is not sentinel:
616+
got_star = 1
617+
break
618+
if len(lhs.elts) > len(vals) + got_star:
619+
if got_star:
620+
err_msg = f"at least {len(lhs.elts) - got_star}"
621+
else:
622+
err_msg = f"{len(lhs.elts)}"
623+
raise ValueError(f"too few values to unpack (expected {err_msg})")
624+
if len(lhs.elts) < len(vals) and got_star == 0:
636625
raise ValueError(
637626
f"too many values to unpack (expected {len(lhs.elts)})"
638627
)
628+
val_idx = 0
629+
for lhs_elt in lhs.elts:
630+
if isinstance(lhs_elt, ast.Starred):
631+
star_len = len(vals) - len(lhs.elts) + 1
632+
star_name = lhs_elt.value.id
633+
await self.recurse_assign(
634+
ast.Name(id=star_name, ctx=ast.Store()),
635+
vals[val_idx : val_idx + star_len],
636+
)
637+
val_idx += star_len
638+
else:
639+
await self.recurse_assign(lhs_elt, vals[val_idx])
640+
val_idx += 1
639641
elif isinstance(lhs, ast.Subscript):
640642
var = await self.aeval(lhs.value)
641643
if isinstance(lhs.slice, ast.Index):

tests/custom_components/pyscript/test_func.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ async def setup_script(hass, notify_q, now, source):
3333
)
3434

3535
with patch(
36-
"homeassistant.loader.async_get_integration",
37-
return_value=integration,
36+
"homeassistant.loader.async_get_integration", return_value=integration,
3837
), patch(
3938
"config.custom_components.pyscript.os.path.isdir", return_value=True
4039
), patch(

tests/custom_components/pyscript/test_init.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ async def setup_script(hass, notify_q, now, source):
3434
)
3535

3636
with patch(
37-
"homeassistant.loader.async_get_integration",
38-
return_value=integration,
37+
"homeassistant.loader.async_get_integration", return_value=integration,
3938
), patch(
4039
"config.custom_components.pyscript.os.path.isdir", return_value=True
4140
), patch(
@@ -87,8 +86,7 @@ async def test_setup_fails_on_no_dir(hass, caplog):
8786
)
8887

8988
with patch(
90-
"homeassistant.loader.async_get_integration",
91-
return_value=integration,
89+
"homeassistant.loader.async_get_integration", return_value=integration,
9290
), patch("config.custom_components.pyscript.os.path.isdir", return_value=False):
9391
res = await async_setup_component(hass, "pyscript", {DOMAIN: {}})
9492

@@ -434,8 +432,7 @@ def func5(var_name=None, value=None):
434432
)
435433

436434
with patch(
437-
"homeassistant.loader.async_get_integration",
438-
return_value=integration,
435+
"homeassistant.loader.async_get_integration", return_value=integration,
439436
), patch(
440437
"config.custom_components.pyscript.os.path.isdir", return_value=True
441438
), patch(

tests/custom_components/pyscript/test_unique.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ async def setup_script(hass, notify_q, now, source):
3232
)
3333

3434
with patch(
35-
"homeassistant.loader.async_get_integration",
36-
return_value=integration,
35+
"homeassistant.loader.async_get_integration", return_value=integration,
3736
), patch(
3837
"config.custom_components.pyscript.os.path.isdir", return_value=True
3938
), patch(

tests/custom_components/pyscript/test_unit_eval.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -658,11 +658,7 @@ def get(self):
658658
async def run_one_test(test_data):
659659
"""Run one interpreter test."""
660660
source, expect = test_data
661-
global_ctx = GlobalContext(
662-
"test",
663-
None,
664-
global_sym_table={},
665-
)
661+
global_ctx = GlobalContext("test", None, global_sym_table={})
666662
ast = AstEval("test", global_ctx=global_ctx)
667663
ast.parse(source)
668664
if ast.get_exception() is not None:
@@ -692,27 +688,27 @@ def test_eval(hass):
692688
["xx", "Exception in test line 1 column 0: name 'xx' is not defined"],
693689
[
694690
"(x, y) = (1, 2, 4)",
695-
"Exception in test line 1 column 4: too many values to unpack (expected 2)",
691+
"Exception in test line 1 column 16: too many values to unpack (expected 2)",
696692
],
697693
[
698694
"(x, y) = iter([1, 2, 4])",
699-
"Exception in test line 1 column 4: too many values to unpack (expected 2)",
695+
"Exception in test line 1 column 21: too many values to unpack (expected 2)",
700696
],
701697
[
702698
"(x, y, z) = (1, 2)",
703-
"Exception in test line 1 column 4: too few values to unpack (expected 3)",
699+
"Exception in test line 1 column 16: too few values to unpack (expected 3)",
704700
],
705701
[
706702
"(x, y, z) = iter([1, 2])",
707-
"Exception in test line 1 column 4: too few values to unpack (expected 3)",
703+
"Exception in test line 1 column 21: too few values to unpack (expected 3)",
708704
],
709705
[
710706
"(x, y) = 1",
711707
"Exception in test line 1 column 9: cannot unpack non-iterable object",
712708
],
713709
[
714710
"a, *y, w, z = range(2)",
715-
"Exception in test line 1 column 0: too few values to unpack (expected at least 3)",
711+
"Exception in test line 1 column 20: too few values to unpack (expected at least 3)",
716712
],
717713
[
718714
"assert 1 == 0, 'this is an error'",

0 commit comments

Comments
 (0)