Skip to content

Commit f51a9f6

Browse files
committed
py/builtinimport.c: Add support for built-in packages.
Allows a built-in module to add a sub-module as a member of its globals dict, and allow importing it as "import foo.bar" (or any other variation on the import statement). Note: This does give the slightly surprising behavior that "import foo" followed by "foo.bar.x" will also work. +56 bytes on PYBV11.
1 parent b5ebfb8 commit f51a9f6

File tree

1 file changed

+17
-1
lines changed

1 file changed

+17
-1
lines changed

py/builtinimport.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ STATIC void evaluate_relative_import(mp_int_t level, size_t *mod_len, const char
315315

316316
STATIC mp_obj_t process_import_at_level(qstr full_mod_name, qstr level_mod_name, mp_obj_t outer_module_obj, vstr_t *path, bool override_main) {
317317
mp_import_stat_t stat = MP_IMPORT_STAT_NO_EXIST;
318+
bool store_on_parent = true;
318319

319320
// Exact-match built-in (or already-loaded) takes priority.
320321
mp_obj_t module_obj = mp_module_get_loaded_or_builtin(full_mod_name);
@@ -346,6 +347,21 @@ STATIC mp_obj_t process_import_at_level(qstr full_mod_name, qstr level_mod_name,
346347
} else {
347348
DEBUG_printf("Searching for sub-module\n");
348349

350+
if (module_obj == MP_OBJ_NULL) {
351+
// See if the outer module has this module as an attr.
352+
// e.g. built-in modules can add modules to their globals dict
353+
// to provide something that behaves like built-in packages.
354+
mp_obj_t dest[2] = { MP_OBJ_NULL };
355+
mp_type_module.attr(outer_module_obj, level_mod_name, dest);
356+
if (dest[0] != MP_OBJ_NULL) {
357+
// Ensure that it's actually a module.
358+
if (mp_obj_get_type(dest[0]) == &mp_type_module) {
359+
module_obj = dest[0];
360+
store_on_parent = false;
361+
}
362+
}
363+
}
364+
349365
// Add the current part of the module name to the path.
350366
vstr_add_char(path, PATH_SEP_CHAR[0]);
351367
vstr_add_str(path, qstr_str(level_mod_name));
@@ -418,7 +434,7 @@ STATIC mp_obj_t process_import_at_level(qstr full_mod_name, qstr level_mod_name,
418434
}
419435
}
420436

421-
if (outer_module_obj != MP_OBJ_NULL) {
437+
if (store_on_parent && outer_module_obj != MP_OBJ_NULL) {
422438
// If it's a sub-module (not a built-in one), then make it available on
423439
// the parent module.
424440
mp_store_attr(outer_module_obj, level_mod_name, module_obj);

0 commit comments

Comments
 (0)