summaryrefslogtreecommitdiff
path: root/py/compile.c
diff options
context:
space:
mode:
authorKenny <3454741+WarriorOfWire@users.noreply.github.com>2020-08-05 19:55:40 -0700
committerKenny <3454741+WarriorOfWire@users.noreply.github.com>2020-10-10 15:45:08 -0700
commitbf849ff674a953ea36dbffc856a05158b2350077 (patch)
tree02489fad10981c914515a0edb65e649f83ceaadd /py/compile.c
parent5cadf525bdf27ef4a3fab9b1c7242384f260003e (diff)
async def syntax rigor and __await__ magic method
Some examples of improved compliance with CPython that currently have divergent behavior in CircuitPython are listed below: * yield from is not allowed in async methods ``` >>> async def f(): ... yield from 'abc' ... Traceback (most recent call last): File "<stdin>", line 2, in f SyntaxError: 'yield from' inside async function ``` * await only works on awaitable expressions ``` >>> async def f(): ... await 'not awaitable' ... >>> f().send(None) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in f AttributeError: 'str' object has no attribute '__await__' ``` * only __await__()able expressions are awaitable Okay this one actually does not work in circuitpython at all today. This is how CPython works though and pretending __await__ does not exist will only bite users who write both. ``` >>> class c: ... pass ... >>> def f(self): ... yield ... yield ... return 'f to pay respects' ... >>> c.__await__ = f # could just as easily have put it on the class but this shows how it's wired >>> async def g(): ... awaitable_thing = c() ... partial = await awaitable_thing ... return 'press ' + partial ... >>> q = g() >>> q.send(None) >>> q.send(None) >>> q.send(None) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration: press f to pay respects ```
Diffstat (limited to 'py/compile.c')
-rw-r--r--py/compile.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/py/compile.c b/py/compile.c
index 653aae004..f19430298 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -2632,6 +2632,12 @@ STATIC void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
EMIT_ARG(yield, MP_EMIT_YIELD_VALUE);
} else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_yield_arg_from)) {
pns = (mp_parse_node_struct_t*)pns->nodes[0];
+#if MICROPY_PY_ASYNC_AWAIT
+ if(comp->scope_cur->scope_flags & MP_SCOPE_FLAG_ASYNC) {
+ compile_syntax_error(comp, (mp_parse_node_t)pns, translate("'yield from' inside async function"));
+ return;
+ }
+#endif
compile_node(comp, pns->nodes[0]);
compile_yield_from(comp);
} else {
@@ -2648,7 +2654,8 @@ STATIC void compile_atom_expr_await(compiler_t *comp, mp_parse_node_struct_t *pn
}
compile_require_async_context(comp, pns);
compile_atom_expr_normal(comp, pns);
- compile_yield_from(comp);
+
+ compile_await_object_method(comp, MP_QSTR___await__);
}
#endif