Skip to content

Commit 50c8984

Browse files
committed
feat: enhance _find_spec function and add nested module support
1 parent cf20ac9 commit 50c8984

File tree

8 files changed

+22
-23
lines changed

8 files changed

+22
-23
lines changed

src/awepatch/_module.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,11 @@ def find_spec(
9999

100100

101101
def _find_spec(name: str) -> ModuleSpec | None:
102-
"""Find a module's spec."""
102+
"""Find a module's spec without importing it.
103+
104+
For nested modules like 'a.b.c', we need to find the parent's spec first
105+
to get the search path, but we don't import the parent.
106+
"""
103107
if name in sys.modules:
104108
# The module is already imported, so we can skip the finders and just
105109
# return the spec from sys.modules.
@@ -111,13 +115,22 @@ def _find_spec(name: str) -> ModuleSpec | None:
111115

112116
warnings.warn("sys.meta_path is empty", ImportWarning, stacklevel=2)
113117

118+
# For nested modules, we need to find the parent spec first
119+
path = None
120+
parent_name = name.rpartition(".")[0]
121+
if parent_name:
122+
parent_spec = _find_spec(parent_name)
123+
if parent_spec is None:
124+
return None
125+
path = parent_spec.submodule_search_locations
126+
114127
for finder in meta_path:
115128
try:
116129
find_spec = finder.find_spec
117130
except AttributeError:
118131
continue
119132
else:
120-
spec = find_spec(name, None)
133+
spec = find_spec(name, path)
121134
if spec is not None:
122135
return spec
123136
else:

tests/__init__.py

Whitespace-only changes.

tests/test_function/__init__.py

Whitespace-only changes.

tests/test_module/__init__.py

Whitespace-only changes.

tests/test_module/nested/__init__.py

Whitespace-only changes.
File renamed without changes.

tests/test_module/test_module_patcher.py

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,9 @@
66

77

88
def test_module_patch_dataclass() -> None:
9-
from tests.test_module import module_for_test
10-
11-
importlib.reload(module_for_test)
12-
13-
user = module_for_test.User(name="Alice", age=230)
14-
assert user.name == "Alice"
15-
assert user.age == 230
16-
assert not hasattr(user, "gender")
17-
189
patcher = ModulePatcher()
1910
patcher.add_patch(
20-
"tests.test_module.module_for_test",
11+
"tests.test_module.nested.module_for_test",
2112
target="class User:",
2213
content="""
2314
@dataclass
@@ -29,7 +20,7 @@ class User:
2920
mode="replace",
3021
)
3122
patcher.add_patch(
32-
"tests.test_module.module_for_test",
23+
"tests.test_module.nested.module_for_test",
3324
target="def greet(user: User) -> str:",
3425
content="""
3526
def greet(user: User) -> str:
@@ -38,6 +29,8 @@ def greet(user: User) -> str:
3829
mode="replace",
3930
)
4031
patcher.apply()
32+
from tests.test_module.nested import module_for_test
33+
4134
importlib.reload(module_for_test)
4235
try:
4336
patched_user = module_for_test.User(name="Bob", age=25)
@@ -54,25 +47,18 @@ def greet(user: User) -> str:
5447

5548

5649
def test_module_patch_field() -> None:
57-
from tests.test_module import module_for_test
58-
59-
importlib.reload(module_for_test)
60-
61-
user = module_for_test.User(name="Alice", age=230)
62-
assert user.name == "Alice"
63-
assert user.age == 230
64-
assert not hasattr(user, "gender")
65-
6650
patcher = ModulePatcher()
6751
patcher.add_patch(
68-
"tests.test_module.module_for_test",
52+
"tests.test_module.nested.module_for_test",
6953
target=("class User:", "age: int"),
7054
content="""
7155
gender: str = "unspecified"
7256
""",
7357
mode="after",
7458
)
7559
patcher.apply()
60+
from tests.test_module.nested import module_for_test
61+
7662
importlib.reload(module_for_test)
7763
try:
7864
importlib.reload(module_for_test)

tests/test_utils/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)