Skip to content

Commit 589880c

Browse files
committed
tests: add split namespace package tests
Add four tests for MICROPY_MODULE_SPLIT_NAMESPACE_PACKAGES: - import_split_ns_pkg: basic split import across two directories - import_split_ns_pkg_nested: nested sub-namespace packages - import_split_ns_pkg_path: verify __path__ is a list - import_split_ns_pkg_compat: existing packages still work The first three tests SKIP gracefully when the feature is disabled. The compat test passes regardless of feature state. Also update cpydiff documentation to reflect the new feature.
1 parent d034c7c commit 589880c

14 files changed

Lines changed: 103 additions & 4 deletions

tests/cpydiff/core_import_path.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""
22
categories: Core,import
3-
description: __path__ attribute of a package has a different type (single string instead of list of strings) in MicroPython
4-
cause: MicroPython doesn't support namespace packages split across filesystem. Beyond that, MicroPython's import system is highly optimized for minimal memory usage.
3+
description: __path__ attribute of a regular package has a different type (single string instead of list of strings) in MicroPython
4+
cause: MicroPython's import system is highly optimized for minimal memory usage. With MICROPY_MODULE_SPLIT_NAMESPACE_PACKAGES enabled, namespace packages (without __init__.py) get a list __path__, but regular packages still use a string.
55
workaround: Details of import handling is inherently implementation dependent. Don't rely on such details in portable applications.
66
"""
77

tests/cpydiff/core_import_split_ns_pkgs.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
"""
22
categories: Core,import
3-
description: MicroPython doesn't support namespace packages split across filesystem.
3+
description: MicroPython doesn't support namespace packages split across filesystem by default.
44
cause: MicroPython's import system is highly optimized for simplicity, minimal memory usage, and minimal filesystem search overhead.
5-
workaround: Don't install modules belonging to the same namespace package in different directories. For MicroPython, it's recommended to have at most 3-component module search paths: for your current application, per-user (writable), system-wide (non-writable).
5+
workaround: Enable MICROPY_MODULE_SPLIT_NAMESPACE_PACKAGES in the build configuration, or don't install modules belonging to the same namespace package in different directories.
66
"""
77

88
import sys
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Test split namespace packages: sub-modules of the same namespace package
2+
# located in different directories on sys.path.
3+
# Requires MICROPY_MODULE_SPLIT_NAMESPACE_PACKAGES to be enabled.
4+
5+
import sys
6+
7+
_f = __file__.replace("\\", "/")
8+
test_dir = _f[:_f.rfind("/")] if "/" in _f else "."
9+
10+
sys.path.insert(0, test_dir + "/split_ns_dir1")
11+
sys.path.insert(1, test_dir + "/split_ns_dir2")
12+
13+
# Detect feature by checking if __path__ is a list (split ns) vs string.
14+
import nspkg
15+
if not isinstance(nspkg.__path__, list):
16+
print("SKIP")
17+
raise SystemExit
18+
19+
import nspkg.mod_a
20+
import nspkg.mod_b
21+
print("split namespace package OK")
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
mod_a from dir1
2+
mod_b from dir2
3+
split namespace package OK
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Test that split namespace package support does not break existing imports:
2+
# 1. Regular packages (with __init__.py) still work
3+
# 2. Single-directory namespace packages (without __init__.py) still work
4+
# This test must pass regardless of MICROPY_MODULE_SPLIT_NAMESPACE_PACKAGES.
5+
6+
import pkg.mod
7+
print("regular package:", pkg.mod.foo())
8+
9+
import pkg8.mod
10+
print("single-dir ns package OK")
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
regular package: 42
2+
foo
3+
single-dir ns package OK
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Test nested split namespace packages: sub-namespaces of the same package
2+
# split across different directories.
3+
# Requires MICROPY_MODULE_SPLIT_NAMESPACE_PACKAGES to be enabled.
4+
5+
import sys
6+
7+
_f = __file__.replace("\\", "/")
8+
test_dir = _f[:_f.rfind("/")] if "/" in _f else "."
9+
10+
sys.path.insert(0, test_dir + "/split_ns_dir1")
11+
sys.path.insert(1, test_dir + "/split_ns_dir2")
12+
13+
# Detect feature by checking if __path__ is a list (split ns) vs string.
14+
import nspkg
15+
if not isinstance(nspkg.__path__, list):
16+
print("SKIP")
17+
raise SystemExit
18+
19+
import nspkg.sub.mod_x
20+
import nspkg.sub.mod_y
21+
print("nested split namespace package OK")
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
mod_x from dir1/sub
2+
mod_y from dir2/sub
3+
nested split namespace package OK
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Test that __path__ of a split namespace package is a list containing
2+
# all contributing directories.
3+
# Requires MICROPY_MODULE_SPLIT_NAMESPACE_PACKAGES to be enabled.
4+
5+
import sys
6+
7+
_f = __file__.replace("\\", "/")
8+
test_dir = _f[:_f.rfind("/")] if "/" in _f else "."
9+
10+
sys.path.insert(0, test_dir + "/split_ns_dir1")
11+
sys.path.insert(1, test_dir + "/split_ns_dir2")
12+
13+
import nspkg
14+
15+
p = nspkg.__path__
16+
if not isinstance(p, list):
17+
print("SKIP")
18+
raise SystemExit
19+
20+
print("type:", type(p).__name__)
21+
print("len:", len(p))
22+
23+
# Verify both directories are present (check basenames of parent dirs).
24+
dirs = []
25+
for d in p:
26+
d = d.replace("\\", "/")
27+
parent = d[:d.rfind("/")] if "/" in d else d
28+
name = parent[parent.rfind("/") + 1:] if "/" in parent else parent
29+
dirs.append(name)
30+
dirs.sort()
31+
print("dirs:", dirs)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
type: list
2+
len: 2
3+
dirs: ['split_ns_dir1', 'split_ns_dir2']

0 commit comments

Comments
 (0)