@@ -71,8 +71,10 @@ def _install_stubs():
7171 """Insert MagicMock modules for all heavy dependencies."""
7272 for name in _MODULES_TO_STUB :
7373 if name not in sys .modules :
74- _stubs_installed [name ] = MagicMock ()
75- sys .modules [name ] = _stubs_installed [name ]
74+ sys .modules [name ] = _stubs_installed .setdefault (name , MagicMock ())
75+ if "." in name :
76+ parent_name , child_name = name .rsplit ("." , 1 )
77+ setattr (sys .modules [parent_name ], child_name , sys .modules [name ])
7678
7779 @dataclass
7880 class DeadlinePacingConfig :
@@ -88,6 +90,21 @@ class RetargetingExecutionConfig:
8890 tsm .RetargetingExecutionConfig = RetargetingExecutionConfig # type: ignore[attr-defined]
8991
9092
93+ def _restore_stubs ():
94+ """Remove stubs installed for this test module from ``sys.modules``."""
95+ for name in reversed (_MODULES_TO_STUB ):
96+ stub = _stubs_installed .get (name )
97+ if stub is None :
98+ continue
99+ if "." in name :
100+ parent_name , child_name = name .rsplit ("." , 1 )
101+ parent = sys .modules .get (parent_name )
102+ if parent is not None and getattr (parent , child_name , None ) is stub :
103+ delattr (parent , child_name )
104+ if sys .modules .get (name ) is stub :
105+ del sys .modules [name ]
106+
107+
91108_install_stubs ()
92109
93110from isaaclab_teleop .isaac_teleop_cfg import ( # noqa: E402
@@ -97,11 +114,21 @@ class RetargetingExecutionConfig:
97114)
98115from isaaclab_teleop .session_lifecycle import TeleopSessionLifecycle # noqa: E402
99116
117+ _restore_stubs ()
118+
100119# ---------------------------------------------------------------------------
101120# Helpers
102121# ---------------------------------------------------------------------------
103122
104123
124+ @pytest .fixture (autouse = True )
125+ def _stub_heavy_dependencies ():
126+ """Keep CloudXR tests isolated from modules collected later in the suite."""
127+ _install_stubs ()
128+ yield
129+ _restore_stubs ()
130+
131+
105132def _make_cfg () -> IsaacTeleopCfg :
106133 """Build a minimal IsaacTeleopCfg with a dummy pipeline_builder."""
107134 return IsaacTeleopCfg (
@@ -123,6 +150,24 @@ def _make_lifecycle(
123150 )
124151
125152
153+ def _make_supported_tsm_module () -> ModuleType :
154+ """Build a fake ``teleop_session_manager`` with the new execution config API."""
155+
156+ @dataclass
157+ class DeadlinePacingConfig :
158+ safety_margin_s : float = 0.025
159+
160+ @dataclass
161+ class RetargetingExecutionConfig :
162+ mode : str = "sync"
163+ pacing : DeadlinePacingConfig | None = None
164+
165+ tsm = ModuleType ("isaacteleop.teleop_session_manager" )
166+ tsm .DeadlinePacingConfig = DeadlinePacingConfig # type: ignore[attr-defined]
167+ tsm .RetargetingExecutionConfig = RetargetingExecutionConfig # type: ignore[attr-defined]
168+ return tsm
169+
170+
126171# ============================================================================
127172# Shipped .env profile paths
128173# ============================================================================
@@ -163,7 +208,13 @@ class TestRetargetingExecutionConfig:
163208
164209 def test_cfg_defaults_to_deadline_paced_pipelined_retargeting (self ):
165210 """Isaac Lab defaults to deadline-paced pipelined retargeting."""
166- cfg = _make_cfg ()
211+ import isaaclab_teleop .isaac_teleop_cfg as cfg_module
212+
213+ with (
214+ patch .object (cfg_module , "_RETARGETING_EXECUTION_SUPPORTED" , True ),
215+ patch .object (cfg_module , "_tsm" , _make_supported_tsm_module ()),
216+ ):
217+ cfg = _make_cfg ()
167218
168219 assert cfg .retargeting_execution .mode == "pipelined"
169220 assert cfg .retargeting_execution .pacing .safety_margin_s == 0.025
@@ -177,8 +228,23 @@ def test_cfg_defaults_to_none_with_legacy_isaacteleop(self):
177228
178229 assert cfg .retargeting_execution is None
179230
231+ def test_retargeting_execution_support_requires_new_config_classes (self ):
232+ """IsaacTeleop must expose both execution config classes to enable the default."""
233+ import isaaclab_teleop .isaac_teleop_cfg as cfg_module
234+
235+ legacy_tsm = ModuleType ("isaacteleop.teleop_session_manager" )
236+ assert not cfg_module ._retargeting_execution_is_supported (legacy_tsm )
237+
238+ legacy_tsm .RetargetingExecutionConfig = object
239+ assert not cfg_module ._retargeting_execution_is_supported (legacy_tsm )
240+
241+ legacy_tsm .DeadlinePacingConfig = object
242+ assert cfg_module ._retargeting_execution_is_supported (legacy_tsm )
243+
180244 def test_session_config_receives_cfg_retargeting_execution (self ):
181245 """The configured IsaacTeleop execution mode is passed into TeleopSession."""
246+ import isaaclab_teleop .session_lifecycle as lifecycle_module
247+
182248 cfg = _make_cfg ()
183249 sentinel_execution = object ()
184250 cfg .retargeting_execution = sentinel_execution
@@ -192,6 +258,7 @@ def test_session_config_receives_cfg_retargeting_execution(self):
192258 fake_tsm_module = sys .modules ["isaacteleop.teleop_session_manager" ]
193259
194260 with (
261+ patch .object (lifecycle_module , "_RETARGETING_EXECUTION_SUPPORTED" , True ),
195262 patch .object (fake_tsm_module , "TeleopSessionConfig" , session_config_cls ),
196263 patch .object (fake_tsm_module , "TeleopSession" , session_cls ),
197264 patch .object (lifecycle , "_ensure_xr_ar_profile_enabled" ),
@@ -235,6 +302,8 @@ def test_session_config_omits_retargeting_execution_for_legacy_isaacteleop(self,
235302
236303 def test_session_config_propagates_typeerror_from_supported_isaacteleop (self ):
237304 """A TypeError from a supported IsaacTeleop must surface, not be swallowed."""
305+ import isaaclab_teleop .session_lifecycle as lifecycle_module
306+
238307 cfg = _make_cfg ()
239308 cfg .retargeting_execution = object ()
240309
@@ -248,6 +317,7 @@ def raising_session_config(**kwargs):
248317 fake_tsm_module = sys .modules ["isaacteleop.teleop_session_manager" ]
249318
250319 with (
320+ patch .object (lifecycle_module , "_RETARGETING_EXECUTION_SUPPORTED" , True ),
251321 patch .object (fake_tsm_module , "TeleopSessionConfig" , raising_session_config ),
252322 patch .object (fake_tsm_module , "TeleopSession" , MagicMock ()),
253323 patch .object (lifecycle , "_ensure_xr_ar_profile_enabled" ),
0 commit comments