py/objgenerator: Implement __name__ with normal fun attr accessor code.
With the recent change b488a4a848, 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__.
This commit is contained in:
@@ -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
|
#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) {
|
if (dest[0] != MP_OBJ_NULL) {
|
||||||
// not load attribute
|
// not load attribute
|
||||||
return;
|
return;
|
||||||
@@ -358,7 +358,7 @@ const mp_obj_type_t mp_type_fun_bc = {
|
|||||||
.call = fun_bc_call,
|
.call = fun_bc_call,
|
||||||
.unary_op = mp_generic_unary_op,
|
.unary_op = mp_generic_unary_op,
|
||||||
#if MICROPY_PY_FUNCTION_ATTRS
|
#if MICROPY_PY_FUNCTION_ATTRS
|
||||||
.attr = fun_bc_attr,
|
.attr = mp_obj_fun_bc_attr,
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -41,4 +41,6 @@ typedef struct _mp_obj_fun_bc_t {
|
|||||||
mp_obj_t extra_args[];
|
mp_obj_t extra_args[];
|
||||||
} mp_obj_fun_bc_t;
|
} 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
|
#endif // MICROPY_INCLUDED_PY_OBJFUN_H
|
||||||
|
|||||||
@@ -68,6 +68,9 @@ const mp_obj_type_t mp_type_gen_wrap = {
|
|||||||
.name = MP_QSTR_generator,
|
.name = MP_QSTR_generator,
|
||||||
.call = gen_wrap_call,
|
.call = gen_wrap_call,
|
||||||
.unary_op = mp_generic_unary_op,
|
.unary_op = mp_generic_unary_op,
|
||||||
|
#if MICROPY_PY_FUNCTION_ATTRS
|
||||||
|
.attr = mp_obj_fun_bc_attr,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|||||||
16
tests/basics/generator_name.py
Normal file
16
tests/basics/generator_name.py
Normal file
@@ -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
|
||||||
@@ -336,7 +336,7 @@ def run_tests(pyb, tests, args, base_path="."):
|
|||||||
# Some tests are known to fail with native emitter
|
# Some tests are known to fail with native emitter
|
||||||
# Remove them from the below when they work
|
# Remove them from the below when they work
|
||||||
if args.emit == 'native':
|
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/%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/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
|
skip_tests.update({'basics/%s.py' % t for t in 'try_reraise try_reraise2'.split()}) # require raise_varargs
|
||||||
|
|||||||
Reference in New Issue
Block a user