Skip to content

Commit 5c64127

Browse files
committed
Refactor load_python_class and add _import_module_from_classpath for improved module handling; enhance test cases for classpath conflicts
1 parent 84db9bc commit 5c64127

3 files changed

Lines changed: 28 additions & 5 deletions

File tree

src/iop/_persistent_message.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,10 @@ def load_python_class(
299299
except ModuleNotFoundError as exc:
300300
if not python_classpath or not _is_missing_target_module(exc, module_name):
301301
raise
302-
_prepend_sys_path(python_classpath)
303-
module = importlib.import_module(module_name)
302+
module = _import_module_from_classpath(module_name, python_classpath)
303+
else:
304+
if python_classpath and not hasattr(module, class_name):
305+
module = _import_module_from_classpath(module_name, python_classpath)
304306
return getattr(module, class_name)
305307

306308

@@ -529,3 +531,10 @@ def _prepend_sys_path(path: str) -> None:
529531
while normalized_path in sys.path:
530532
sys.path.remove(normalized_path)
531533
sys.path.insert(0, normalized_path)
534+
importlib.invalidate_caches()
535+
536+
537+
def _import_module_from_classpath(module_name: str, python_classpath: str):
538+
_prepend_sys_path(python_classpath)
539+
sys.modules.pop(module_name, None)
540+
return importlib.import_module(module_name)

src/tests/e2e/local/test_persistent_message.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""E2E (local IRIS) tests for PersistentMessage native message bodies."""
2+
23
from unittest.mock import MagicMock
34

45
from iop import Field, PersistentMessage

src/tests/unit/test_persistent_message.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,12 @@ def test_classes_registration_uses_key_as_iris_classname():
7070

7171
assert NativeOrderMessage._classname == "Demo.Msg.NativeOrderMessage"
7272
assert NativeOrderMessage._parameters["IOP_MESSAGE_KIND"] == "PersistentMessage"
73-
assert NativeOrderMessage._parameters["IOP_PYTHON_CLASS"].endswith(".NativeOrderMessage")
74-
assert NativeOrderMessage._parameters["IOP_PYTHON_CLASSPATH"] == get_python_classpath(
75-
NativeOrderMessage
73+
assert NativeOrderMessage._parameters["IOP_PYTHON_CLASS"].endswith(
74+
".NativeOrderMessage"
7675
)
76+
assert NativeOrderMessage._parameters[
77+
"IOP_PYTHON_CLASSPATH"
78+
] == get_python_classpath(NativeOrderMessage)
7779

7880

7981
def test_explicit_meta_classname_conflict_raises():
@@ -182,18 +184,27 @@ def _Id(self):
182184

183185
def test_load_python_class_uses_classpath_on_cold_import(tmp_path):
184186
app_dir = tmp_path / "app"
187+
conflict_dir = tmp_path / "conflict"
185188
app_dir.mkdir()
189+
conflict_dir.mkdir()
186190
module_path = app_dir / "msg.py"
187191
module_path.write_text(
188192
"from iop import Field, PersistentMessage\n"
189193
"class ColdMessage(PersistentMessage):\n"
190194
" Value: str = Field(required=True)\n",
191195
encoding="utf-8",
192196
)
197+
(conflict_dir / "msg.py").write_text(
198+
"class PickleMessage:\n pass\n",
199+
encoding="utf-8",
200+
)
193201

194202
sys.modules.pop("msg", None)
195203
while str(app_dir) in sys.path:
196204
sys.path.remove(str(app_dir))
205+
while str(conflict_dir) in sys.path:
206+
sys.path.remove(str(conflict_dir))
207+
sys.path.insert(0, str(conflict_dir))
197208

198209
try:
199210
msg_cls = load_python_class("msg.ColdMessage", str(app_dir))
@@ -205,6 +216,8 @@ def test_load_python_class_uses_classpath_on_cold_import(tmp_path):
205216
sys.modules.pop("msg", None)
206217
while str(app_dir) in sys.path:
207218
sys.path.remove(str(app_dir))
219+
while str(conflict_dir) in sys.path:
220+
sys.path.remove(str(conflict_dir))
208221

209222

210223
def test_deserializes_iris_originated_message_with_class_parameters(tmp_path):

0 commit comments

Comments
 (0)