summaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/builtinimport.c14
-rw-r--r--py/mpconfig.h14
2 files changed, 28 insertions, 0 deletions
diff --git a/py/builtinimport.c b/py/builtinimport.c
index d8127a66f..f6c2f7c34 100644
--- a/py/builtinimport.c
+++ b/py/builtinimport.c
@@ -428,6 +428,20 @@ STATIC mp_obj_t process_import_at_level(qstr full_mod_name, qstr level_mod_name,
} else {
DEBUG_printf("Searching for sub-module\n");
+ #if MICROPY_MODULE_BUILTIN_SUBPACKAGES
+ // If the outer module is a built-in (because its map is in ROM), then
+ // treat it like a package if it contains this submodule in its
+ // globals dict.
+ mp_obj_module_t *mod = MP_OBJ_TO_PTR(outer_module_obj);
+ if (mod->globals->map.is_fixed) {
+ elem = mp_map_lookup(&mod->globals->map, MP_OBJ_NEW_QSTR(level_mod_name), MP_MAP_LOOKUP);
+ // Also verify that the entry in the globals dict is in fact a module.
+ if (elem && mp_obj_is_type(elem->value, &mp_type_module)) {
+ return elem->value;
+ }
+ }
+ #endif
+
// If the outer module is a package, it will have __path__ set.
// We can use that as the path to search inside.
mp_obj_t dest[2];
diff --git a/py/mpconfig.h b/py/mpconfig.h
index f3d5ce557..292fafb52 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -850,6 +850,20 @@ typedef double mp_float_t;
#define MICROPY_MODULE_BUILTIN_INIT (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES)
#endif
+// Whether to allow built-in modules to have sub-packages (by making the
+// sub-package a member of their locals dict). Sub-packages should not be
+// registered with MP_REGISTER_MODULE, instead they should be added as
+// members of the parent's globals dict. To match CPython behavior,
+// their __name__ should be "foo.bar"(i.e. QSTR_foo_dot_bar) which will
+// require an entry in qstrdefs, although it does also work to just call
+// it "bar". Also, because subpackages can be accessed without being
+// imported (e.g. as foo.bar after `import foo`), they should not
+// have __init__ methods. Instead, the top-level package's __init__ should
+// initialise all sub-packages.
+#ifndef MICROPY_MODULE_BUILTIN_SUBPACKAGES
+#define MICROPY_MODULE_BUILTIN_SUBPACKAGES (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING)
+#endif
+
// Whether to support module-level __getattr__ (see PEP 562)
#ifndef MICROPY_MODULE_GETATTR
#define MICROPY_MODULE_GETATTR (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES)