From c14a81662c1df812c0c6b4299f97966302f16477 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 12 Oct 2014 11:46:04 +0100 Subject: [PATCH] py: Add module weak link support. With this patch a port can enable module weak link support and provide a dict of qstr->module mapping. This mapping is looked up only if an import fails to find the requested module in the filesystem. This allows to have the builtin module named, eg, usocket, and provide a weak link of "socket" to the same module, but this weak link can be overridden if a file by the name "socket.py" is found in the import path. --- py/builtinimport.c | 24 +++++++++++++++++++++--- py/builtintables.c | 17 +++++++++++++++++ py/builtintables.h | 4 ++++ py/mpconfig.h | 10 ++++++++++ 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/py/builtinimport.c b/py/builtinimport.c index ffdadf0227..1272d59413 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -44,6 +44,7 @@ #include "runtime0.h" #include "runtime.h" #include "builtin.h" +#include "builtintables.h" #if 0 // print debugging info #define DEBUG_PRINT (1) @@ -251,12 +252,29 @@ mp_obj_t mp_builtin___import__(mp_uint_t n_args, mp_obj_t *args) { } DEBUG_printf("Current path: %s\n", vstr_str(&path)); - // fail if we couldn't find the file if (stat == MP_IMPORT_STAT_NO_EXIST) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "No module named '%s'", qstr_str(mod_name))); + #if MICROPY_MODULE_WEAK_LINKS + // check if there is a weak link to this module + if (i == mod_len) { + mp_map_elem_t *el = mp_map_lookup((mp_map_t*)&mp_builtin_module_weak_links_dict_obj.map, MP_OBJ_NEW_QSTR(mod_name), MP_MAP_LOOKUP); + if (el == NULL) { + goto no_exist; + } + // found weak linked module + module_obj = el->value; + } else { + no_exist: + #else + { + #endif + // couldn't find the file, so fail + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "No module named '%s'", qstr_str(mod_name))); + } + } else { + // found the file, so get the module + module_obj = mp_module_get(mod_name); } - module_obj = mp_module_get(mod_name); if (module_obj == MP_OBJ_NULL) { // module not already loaded, so load it! diff --git a/py/builtintables.c b/py/builtintables.c index 1fd60d8177..6d74961384 100644 --- a/py/builtintables.c +++ b/py/builtintables.c @@ -227,3 +227,20 @@ const mp_obj_dict_t mp_builtin_module_dict_obj = { .table = (mp_map_elem_t*)mp_builtin_module_table, }, }; + +#if MICROPY_MODULE_WEAK_LINKS +STATIC const mp_map_elem_t mp_builtin_module_weak_links_table[] = { + MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS +}; + +const mp_obj_dict_t mp_builtin_module_weak_links_dict_obj = { + .base = {&mp_type_dict}, + .map = { + .all_keys_are_qstrs = 1, + .table_is_fixed_array = 1, + .used = MP_ARRAY_SIZE(mp_builtin_module_weak_links_table), + .alloc = MP_ARRAY_SIZE(mp_builtin_module_weak_links_table), + .table = (mp_map_elem_t*)mp_builtin_module_weak_links_table, + }, +}; +#endif diff --git a/py/builtintables.h b/py/builtintables.h index 96fc813aba..5a865a78b4 100644 --- a/py/builtintables.h +++ b/py/builtintables.h @@ -26,3 +26,7 @@ extern const mp_obj_dict_t mp_builtin_object_dict_obj; extern const mp_obj_dict_t mp_builtin_module_dict_obj; + +#if MICROPY_MODULE_WEAK_LINKS +extern const mp_obj_dict_t mp_builtin_module_weak_links_dict_obj; +#endif diff --git a/py/mpconfig.h b/py/mpconfig.h index 92b61d0e12..13ccb9ca98 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -269,6 +269,11 @@ typedef double mp_float_t; #define MICROPY_STREAMS_NON_BLOCK (0) #endif +// Whether module weak links are supported +#ifndef MICROPY_MODULE_WEAK_LINKS +#define MICROPY_MODULE_WEAK_LINKS (0) +#endif + /*****************************************************************************/ /* Fine control over Python builtins, classes, modules, etc */ @@ -411,6 +416,11 @@ typedef double mp_float_t; #define MICROPY_PORT_BUILTIN_MODULES #endif +// Any module weak links - see builtintables.c:mp_builtin_module_weak_links_table. +#ifndef MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS +#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS +#endif + // Additional constant definitions for the compiler - see compile.c:mp_constants_table. #ifndef MICROPY_PORT_CONSTANTS #define MICROPY_PORT_CONSTANTS