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