From e2e22e3d7e29985579b2c91c639c71229422f349 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 10 Jul 2018 16:21:34 +1000 Subject: [PATCH] py/objgenerator: Implement __name__ with normal fun attr accessor code. With the recent change b488a4a8480533a6a3c9468c2f8bd359c94d4d02, a generating function now has the same layout in memory as a normal bytecode function, and so can reuse the latter's attribute accessor code to implement __name__. --- py/objfun.c | 4 ++-- py/objfun.h | 2 ++ py/objgenerator.c | 3 +++ tests/basics/generator_name.py | 16 ++++++++++++++++ tests/run-tests | 2 +- 5 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 tests/basics/generator_name.py diff --git a/py/objfun.c b/py/objfun.c index 8c51d92e06..b8657ec954 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -338,7 +338,7 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const } #if MICROPY_PY_FUNCTION_ATTRS -STATIC void fun_bc_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { +void mp_obj_fun_bc_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { // not load attribute return; @@ -358,7 +358,7 @@ const mp_obj_type_t mp_type_fun_bc = { .call = fun_bc_call, .unary_op = mp_generic_unary_op, #if MICROPY_PY_FUNCTION_ATTRS - .attr = fun_bc_attr, + .attr = mp_obj_fun_bc_attr, #endif }; diff --git a/py/objfun.h b/py/objfun.h index fbb3516261..257b8a65a7 100644 --- a/py/objfun.h +++ b/py/objfun.h @@ -41,4 +41,6 @@ typedef struct _mp_obj_fun_bc_t { mp_obj_t extra_args[]; } mp_obj_fun_bc_t; +void mp_obj_fun_bc_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest); + #endif // MICROPY_INCLUDED_PY_OBJFUN_H diff --git a/py/objgenerator.c b/py/objgenerator.c index 8b898c9374..c45bebacd2 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -68,6 +68,9 @@ const mp_obj_type_t mp_type_gen_wrap = { .name = MP_QSTR_generator, .call = gen_wrap_call, .unary_op = mp_generic_unary_op, + #if MICROPY_PY_FUNCTION_ATTRS + .attr = mp_obj_fun_bc_attr, + #endif }; /******************************************************************************/ diff --git a/tests/basics/generator_name.py b/tests/basics/generator_name.py new file mode 100644 index 0000000000..77259a8218 --- /dev/null +++ b/tests/basics/generator_name.py @@ -0,0 +1,16 @@ +# test __name__ on generator functions + +def Fun(): + yield + +class A: + def Fun(self): + yield + +try: + print(Fun.__name__) + print(A.Fun.__name__) + print(A().Fun.__name__) +except AttributeError: + print('SKIP') + raise SystemExit diff --git a/tests/run-tests b/tests/run-tests index e1b594edfd..e4a0e20ed5 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -336,7 +336,7 @@ def run_tests(pyb, tests, args, base_path="."): # Some tests are known to fail with native emitter # Remove them from the below when they work if args.emit == 'native': - skip_tests.update({'basics/%s.py' % t for t in 'gen_yield_from gen_yield_from_close gen_yield_from_ducktype gen_yield_from_exc gen_yield_from_executing gen_yield_from_iter gen_yield_from_send gen_yield_from_stopped gen_yield_from_throw gen_yield_from_throw2 gen_yield_from_throw3 generator1 generator2 generator_args generator_close generator_closure generator_exc generator_pend_throw generator_return generator_send'.split()}) # require yield + skip_tests.update({'basics/%s.py' % t for t in 'gen_yield_from gen_yield_from_close gen_yield_from_ducktype gen_yield_from_exc gen_yield_from_executing gen_yield_from_iter gen_yield_from_send gen_yield_from_stopped gen_yield_from_throw gen_yield_from_throw2 gen_yield_from_throw3 generator1 generator2 generator_args generator_close generator_closure generator_exc generator_name generator_pend_throw generator_return generator_send'.split()}) # require yield skip_tests.update({'basics/%s.py' % t for t in 'bytes_gen class_store_class globals_del string_join'.split()}) # require yield skip_tests.update({'basics/async_%s.py' % t for t in 'def await await2 for for2 with with2 with_break with_return'.split()}) # require yield skip_tests.update({'basics/%s.py' % t for t in 'try_reraise try_reraise2'.split()}) # require raise_varargs