summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/usercmodule/cexample/examplemodule.c2
-rw-r--r--examples/usercmodule/cexample/micropython.mk7
-rw-r--r--examples/usercmodule/cppexample/examplemodule.c2
-rw-r--r--examples/usercmodule/subpackage/README.md1
-rw-r--r--examples/usercmodule/subpackage/micropython.cmake19
-rw-r--r--examples/usercmodule/subpackage/micropython.mk10
-rw-r--r--examples/usercmodule/subpackage/modexamplepackage.c84
-rw-r--r--examples/usercmodule/subpackage/qstrdefsexamplepackage.h2
-rw-r--r--tests/unix/extra_coverage.py17
-rw-r--r--tests/unix/extra_coverage.py.exp25
10 files changed, 156 insertions, 13 deletions
diff --git a/examples/usercmodule/cexample/examplemodule.c b/examples/usercmodule/cexample/examplemodule.c
index ccce03bcb..9416613ba 100644
--- a/examples/usercmodule/cexample/examplemodule.c
+++ b/examples/usercmodule/cexample/examplemodule.c
@@ -68,7 +68,7 @@ MP_DEFINE_CONST_OBJ_TYPE(
locals_dict, &example_Timer_locals_dict
);
-// Define all properties of the module.
+// Define all attributes of the module.
// Table entries are key/value pairs of the attribute name (a string)
// and the MicroPython object reference.
// All identifiers and strings are written as MP_QSTR_xxx and will be
diff --git a/examples/usercmodule/cexample/micropython.mk b/examples/usercmodule/cexample/micropython.mk
index dbfe3c5cb..d6801dac0 100644
--- a/examples/usercmodule/cexample/micropython.mk
+++ b/examples/usercmodule/cexample/micropython.mk
@@ -1,9 +1,8 @@
-EXAMPLE_MOD_DIR := $(USERMOD_DIR)
+CEXAMPLE_MOD_DIR := $(USERMOD_DIR)
# Add all C files to SRC_USERMOD.
-SRC_USERMOD += $(EXAMPLE_MOD_DIR)/examplemodule.c
+SRC_USERMOD += $(CEXAMPLE_MOD_DIR)/examplemodule.c
# We can add our module folder to include paths if needed
# This is not actually needed in this example.
-CFLAGS_USERMOD += -I$(EXAMPLE_MOD_DIR)
-CEXAMPLE_MOD_DIR := $(USERMOD_DIR)
+CFLAGS_USERMOD += -I$(CEXAMPLE_MOD_DIR)
diff --git a/examples/usercmodule/cppexample/examplemodule.c b/examples/usercmodule/cppexample/examplemodule.c
index 5c84eccd7..96a1a7443 100644
--- a/examples/usercmodule/cppexample/examplemodule.c
+++ b/examples/usercmodule/cppexample/examplemodule.c
@@ -4,7 +4,7 @@
// See example.cpp for the definition.
STATIC MP_DEFINE_CONST_FUN_OBJ_2(cppfunc_obj, cppfunc);
-// Define all properties of the module.
+// Define all attributes of the module.
// Table entries are key/value pairs of the attribute name (a string)
// and the MicroPython object reference.
// All identifiers and strings are written as MP_QSTR_xxx and will be
diff --git a/examples/usercmodule/subpackage/README.md b/examples/usercmodule/subpackage/README.md
new file mode 100644
index 000000000..c7f2ee53a
--- /dev/null
+++ b/examples/usercmodule/subpackage/README.md
@@ -0,0 +1 @@
+This is an example of a user C module that includes subpackages.
diff --git a/examples/usercmodule/subpackage/micropython.cmake b/examples/usercmodule/subpackage/micropython.cmake
new file mode 100644
index 000000000..a51e7a806
--- /dev/null
+++ b/examples/usercmodule/subpackage/micropython.cmake
@@ -0,0 +1,19 @@
+# Create an INTERFACE library for our C module.
+add_library(usermod_subpackage_example INTERFACE)
+
+# Add our source files to the lib
+target_sources(usermod_subpackage_example INTERFACE
+ ${CMAKE_CURRENT_LIST_DIR}/examplemodule.c
+)
+
+# Add the current directory as an include directory.
+target_include_directories(usermod_subpackage_example INTERFACE
+ ${CMAKE_CURRENT_LIST_DIR}
+)
+
+target_compile_definitions(usermod_subpackage_example INTERFACE
+ MICROPY_MODULE_BUILTIN_SUBPACKAGES=1
+)
+
+# Link our INTERFACE library to the usermod target.
+target_link_libraries(usermod INTERFACE usermod_subpackage_example)
diff --git a/examples/usercmodule/subpackage/micropython.mk b/examples/usercmodule/subpackage/micropython.mk
new file mode 100644
index 000000000..99ebf13ec
--- /dev/null
+++ b/examples/usercmodule/subpackage/micropython.mk
@@ -0,0 +1,10 @@
+SUBPACKAGE_EXAMPLE_MOD_DIR := $(USERMOD_DIR)
+
+# Add all C files to SRC_USERMOD.
+SRC_USERMOD += $(SUBPACKAGE_EXAMPLE_MOD_DIR)/modexamplepackage.c
+
+# We can add our module folder to include paths if needed
+# This is not actually needed in this example.
+CFLAGS_USERMOD += -I$(SUBPACKAGE_EXAMPLE_MOD_DIR) -DMICROPY_MODULE_BUILTIN_SUBPACKAGES=1
+
+QSTR_DEFS += $(SUBPACKAGE_EXAMPLE_MOD_DIR)/qstrdefsexamplepackage.h
diff --git a/examples/usercmodule/subpackage/modexamplepackage.c b/examples/usercmodule/subpackage/modexamplepackage.c
new file mode 100644
index 000000000..70e1e4005
--- /dev/null
+++ b/examples/usercmodule/subpackage/modexamplepackage.c
@@ -0,0 +1,84 @@
+// Include MicroPython API.
+#include "py/runtime.h"
+
+// Define example_package.foo.bar.f()
+STATIC mp_obj_t example_package_foo_bar_f(void) {
+ mp_printf(&mp_plat_print, "example_package.foo.bar.f\n");
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(example_package_foo_bar_f_obj, example_package_foo_bar_f);
+
+// Define all attributes of the second-level sub-package (example_package.foo.bar).
+STATIC const mp_rom_map_elem_t example_package_foo_bar_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example_package_dot_foo_dot_bar) },
+ { MP_ROM_QSTR(MP_QSTR_f), MP_ROM_PTR(&example_package_foo_bar_f_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(example_package_foo_bar_globals, example_package_foo_bar_globals_table);
+
+// Define example_package.foo.bar module object.
+const mp_obj_module_t example_package_foo_bar_user_cmodule = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&example_package_foo_bar_globals,
+};
+
+// Define example_package.foo.f()
+STATIC mp_obj_t example_package_foo_f(void) {
+ mp_printf(&mp_plat_print, "example_package.foo.f\n");
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(example_package_foo_f_obj, example_package_foo_f);
+
+// Define all attributes of the first-level sub-package (example_package.foo).
+STATIC const mp_rom_map_elem_t example_package_foo_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example_package_dot_foo) },
+ { MP_ROM_QSTR(MP_QSTR_bar), MP_ROM_PTR(&example_package_foo_bar_user_cmodule) },
+ { MP_ROM_QSTR(MP_QSTR_f), MP_ROM_PTR(&example_package_foo_f_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(example_package_foo_globals, example_package_foo_globals_table);
+
+// Define example_package.foo module object.
+const mp_obj_module_t example_package_foo_user_cmodule = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&example_package_foo_globals,
+};
+
+// Define example_package.f()
+STATIC mp_obj_t example_package_f(void) {
+ mp_printf(&mp_plat_print, "example_package.f\n");
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(example_package_f_obj, example_package_f);
+
+STATIC mp_obj_t example_package___init__(void) {
+ if (!MP_STATE_VM(example_package_initialised)) {
+ // __init__ for builtins is called each time the module is imported,
+ // so ensure that initialisation only happens once.
+ MP_STATE_VM(example_package_initialised) = true;
+ mp_printf(&mp_plat_print, "example_package.__init__\n");
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(example_package___init___obj, example_package___init__);
+
+// The "initialised" state is stored on mp_state so that it is cleared on soft
+// reset.
+MP_REGISTER_ROOT_POINTER(int example_package_initialised);
+
+// Define all attributes of the top-level package (example_package).
+STATIC const mp_rom_map_elem_t example_package_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example_package) },
+ { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&example_package___init___obj) },
+ { MP_ROM_QSTR(MP_QSTR_foo), MP_ROM_PTR(&example_package_foo_user_cmodule) },
+ { MP_ROM_QSTR(MP_QSTR_f), MP_ROM_PTR(&example_package_f_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(example_package_globals, example_package_globals_table);
+
+// Define module object.
+const mp_obj_module_t example_package_user_cmodule = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&example_package_globals,
+};
+
+// Register the module to make it available in Python.
+// Note: subpackages should not be registered with MP_REGISTER_MODULE.
+MP_REGISTER_MODULE(MP_QSTR_example_package, example_package_user_cmodule);
diff --git a/examples/usercmodule/subpackage/qstrdefsexamplepackage.h b/examples/usercmodule/subpackage/qstrdefsexamplepackage.h
new file mode 100644
index 000000000..057ec5279
--- /dev/null
+++ b/examples/usercmodule/subpackage/qstrdefsexamplepackage.h
@@ -0,0 +1,2 @@
+Q(example_package.foo)
+Q(example_package.foo.bar)
diff --git a/tests/unix/extra_coverage.py b/tests/unix/extra_coverage.py
index a51b5b856..3c12b2692 100644
--- a/tests/unix/extra_coverage.py
+++ b/tests/unix/extra_coverage.py
@@ -96,3 +96,20 @@ print(returns_NULL())
import frozentest
print(frozentest.__file__)
+
+# test for builtin sub-packages
+from example_package.foo import bar
+
+print(bar)
+bar.f()
+import example_package
+
+print(example_package, example_package.foo, example_package.foo.bar)
+example_package.f()
+example_package.foo.f()
+example_package.foo.bar.f()
+print(bar == example_package.foo.bar)
+from example_package.foo import f as foo_f
+
+foo_f()
+print(foo_f == example_package.foo.f)
diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp
index ab6d49772..7ea2599c9 100644
--- a/tests/unix/extra_coverage.py.exp
+++ b/tests/unix/extra_coverage.py.exp
@@ -52,13 +52,14 @@ mport
builtins micropython _thread _uasyncio
btree cexample cmath cppexample
-ffi framebuf gc math
-termios uarray ubinascii ucollections
-ucryptolib uctypes uerrno uhashlib
-uheapq uio ujson umachine
-uos urandom ure uselect
-usocket ussl ustruct usys
-utime utimeq uwebsocket uzlib
+example_package ffi framebuf
+gc math termios uarray
+ubinascii ucollections ucryptolib uctypes
+uerrno uhashlib uheapq uio
+ujson umachine uos urandom
+ure uselect usocket ussl
+ustruct usys utime utimeq
+uwebsocket uzlib
ime
utime utimeq
@@ -211,3 +212,13 @@ b'bytes 1234\x01'
2
3
frozentest.py
+example_package.__init__
+<module 'example_package.foo.bar'>
+example_package.foo.bar.f
+<module 'example_package'> <module 'example_package.foo'> <module 'example_package.foo.bar'>
+example_package.f
+example_package.foo.f
+example_package.foo.bar.f
+True
+example_package.foo.f
+True