mirror of
https://github.com/licsber/micropython.git
synced 2024-09-20 00:50:24 +08:00
py/builtinimport: Allow builtin modules to be packages.
To use this: - Create a built-in module, and add the module object as a member of the parent module's globals dict. - The submodule can set its `__name__` to either `QSTR_foo_dot_bar` or `QSTR_bar`. The former requires using qstrdefs(port).h to make the qstr. Because `bar` is a member of `foo`'s globals, it is possible to write `import foo` and then immediately use `foo.bar` without importing it explicitly. This means that if `bar` has an `__init__`, it will not be called in this situation, and for that reason, sub-modules should not have `__init__` methods. If this is required, then all initalisation for sub-modules should be done by the top-level module's (i.e. `foo`'s) `__init__` method. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
This commit is contained in:
parent
525557738c
commit
ed90f30dd5
@ -428,6 +428,20 @@ STATIC mp_obj_t process_import_at_level(qstr full_mod_name, qstr level_mod_name,
|
|||||||
} else {
|
} else {
|
||||||
DEBUG_printf("Searching for sub-module\n");
|
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.
|
// If the outer module is a package, it will have __path__ set.
|
||||||
// We can use that as the path to search inside.
|
// We can use that as the path to search inside.
|
||||||
mp_obj_t dest[2];
|
mp_obj_t dest[2];
|
||||||
|
@ -850,6 +850,20 @@ typedef double mp_float_t;
|
|||||||
#define MICROPY_MODULE_BUILTIN_INIT (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES)
|
#define MICROPY_MODULE_BUILTIN_INIT (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES)
|
||||||
#endif
|
#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)
|
// Whether to support module-level __getattr__ (see PEP 562)
|
||||||
#ifndef MICROPY_MODULE_GETATTR
|
#ifndef MICROPY_MODULE_GETATTR
|
||||||
#define MICROPY_MODULE_GETATTR (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES)
|
#define MICROPY_MODULE_GETATTR (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES)
|
||||||
|
Loading…
Reference in New Issue
Block a user