From 3cc17c69ffd64dca55fe613f6e931585d8893c0d Mon Sep 17 00:00:00 2001 From: stijn Date: Sat, 14 Feb 2015 18:44:31 +0100 Subject: [PATCH] py: Allow retrieving a function's __name__. Disabled by default. Enabled on unix and stmhal ports. --- py/bc.c | 2 +- py/mpconfig.h | 5 +++++ py/obj.h | 4 ++-- py/objboundmeth.c | 12 ++++++++++++ py/objfun.c | 19 +++++++++++++++---- py/objgenerator.c | 2 +- stmhal/mpconfigport.h | 1 + tests/basics/fun_name.py | 16 ++++++++++++++++ unix/mpconfigport.h | 1 + 9 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 tests/basics/fun_name.py diff --git a/py/bc.c b/py/bc.c index 9498b4f18..3a8dc5e04 100644 --- a/py/bc.c +++ b/py/bc.c @@ -62,7 +62,7 @@ STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, mp_uint_t expecte #elif MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "%s() takes %d positional arguments but %d were given", - mp_obj_fun_get_name(f), expected, given)); + qstr_str(mp_obj_fun_get_name(f)), expected, given)); #endif } diff --git a/py/mpconfig.h b/py/mpconfig.h index e8f7cc890..094d8d78a 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -359,6 +359,11 @@ typedef double mp_float_t; /*****************************************************************************/ /* Fine control over Python builtins, classes, modules, etc */ +// Whether to implement attributes on functions +#ifndef MICROPY_PY_FUNCTION_ATTRS +#define MICROPY_PY_FUNCTION_ATTRS (0) +#endif + // Whether str object is proper unicode #ifndef MICROPY_PY_BUILTINS_STR_UNICODE #define MICROPY_PY_BUILTINS_STR_UNICODE (0) diff --git a/py/obj.h b/py/obj.h index b7f38d1c5..33b764787 100644 --- a/py/obj.h +++ b/py/obj.h @@ -574,8 +574,8 @@ typedef struct _mp_obj_fun_builtin_t { // use this to make const objects that go void *fun; // must be a pointer to a callable function in ROM } mp_obj_fun_builtin_t; -const char *mp_obj_fun_get_name(mp_const_obj_t fun); -const char *mp_obj_code_get_name(const byte *code_info); +qstr mp_obj_fun_get_name(mp_const_obj_t fun); +qstr mp_obj_code_get_name(const byte *code_info); mp_obj_t mp_identity(mp_obj_t self); MP_DECLARE_CONST_FUN_OBJ(mp_identity_obj); diff --git a/py/objboundmeth.c b/py/objboundmeth.c index 7698ed29f..69ae263af 100644 --- a/py/objboundmeth.c +++ b/py/objboundmeth.c @@ -70,6 +70,15 @@ STATIC mp_obj_t bound_meth_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_ } } +#if MICROPY_PY_FUNCTION_ATTRS +STATIC void bound_meth_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { + if(attr == MP_QSTR___name__) { + mp_obj_bound_meth_t *o = self_in; + dest[0] = MP_OBJ_NEW_QSTR(mp_obj_fun_get_name(o->meth)); + } +} +#endif + const mp_obj_type_t bound_meth_type = { { &mp_type_type }, .name = MP_QSTR_bound_method, @@ -77,6 +86,9 @@ const mp_obj_type_t bound_meth_type = { .print = bound_meth_print, #endif .call = bound_meth_call, +#if MICROPY_PY_FUNCTION_ATTRS + .load_attr = bound_meth_load_attr, +#endif }; mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self) { diff --git a/py/objfun.c b/py/objfun.c index dc068d521..d8ea22f39 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -103,12 +103,12 @@ const mp_obj_type_t mp_type_fun_builtin = { /******************************************************************************/ /* byte code functions */ -const char *mp_obj_code_get_name(const byte *code_info) { +qstr mp_obj_code_get_name(const byte *code_info) { mp_decode_uint(&code_info); // skip code_info_size entry - return qstr_str(mp_decode_uint(&code_info)); + return mp_decode_uint(&code_info); } -const char *mp_obj_fun_get_name(mp_const_obj_t fun_in) { +qstr mp_obj_fun_get_name(mp_const_obj_t fun_in) { const mp_obj_fun_bc_t *fun = fun_in; const byte *code_info = fun->bytecode; return mp_obj_code_get_name(code_info); @@ -118,7 +118,7 @@ const char *mp_obj_fun_get_name(mp_const_obj_t fun_in) { STATIC void fun_bc_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_fun_bc_t *o = o_in; - print(env, "", mp_obj_fun_get_name(o), o); + print(env, "", qstr_str(mp_obj_fun_get_name(o)), o); } #endif @@ -246,6 +246,14 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, } } +#if MICROPY_PY_FUNCTION_ATTRS +STATIC void fun_bc_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { + if(attr == MP_QSTR___name__) { + dest[0] = MP_OBJ_NEW_QSTR(mp_obj_fun_get_name(self_in)); + } +} +#endif + const mp_obj_type_t mp_type_fun_bc = { { &mp_type_type }, .name = MP_QSTR_function, @@ -253,6 +261,9 @@ const mp_obj_type_t mp_type_fun_bc = { .print = fun_bc_print, #endif .call = fun_bc_call, +#if MICROPY_PY_FUNCTION_ATTRS + .load_attr = fun_bc_load_attr, +#endif }; mp_obj_t mp_obj_new_fun_bc(mp_uint_t scope_flags, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, mp_obj_t def_args_in, mp_obj_t def_kw_args, const byte *code) { diff --git a/py/objgenerator.c b/py/objgenerator.c index e67824dd7..112becb46 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -97,7 +97,7 @@ mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun) { STATIC void gen_instance_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_gen_instance_t *self = self_in; - print(env, "", mp_obj_code_get_name(self->code_state.code_info), self_in); + print(env, "", qstr_str(mp_obj_code_get_name(self->code_state.code_info)), self_in); } mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) { diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h index 1d3378739..e1d532d1e 100644 --- a/stmhal/mpconfigport.h +++ b/stmhal/mpconfigport.h @@ -55,6 +55,7 @@ #define MICROPY_STREAMS_NON_BLOCK (1) #define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) +#define MICROPY_PY_FUNCTION_ATTRS (1) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_FROZENSET (1) diff --git a/tests/basics/fun_name.py b/tests/basics/fun_name.py new file mode 100644 index 000000000..a7f9c6096 --- /dev/null +++ b/tests/basics/fun_name.py @@ -0,0 +1,16 @@ +def Fun(): + pass + +class A: + def __init__(self): + pass + def Fun(self): + pass + +try: + print(Fun.__name__) + print(A.__init__.__name__) + print(A.Fun.__name__) + print(A().Fun.__name__) +except AttributeError: + print('SKIP') diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h index a7ebf21ed..fd8e52267 100644 --- a/unix/mpconfigport.h +++ b/unix/mpconfigport.h @@ -57,6 +57,7 @@ #define MICROPY_OPT_COMPUTED_GOTO (1) #define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) +#define MICROPY_PY_FUNCTION_ATTRS (1) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_FROZENSET (1)