@@ -299,17 +299,32 @@ def test_section_markdown_includes_formula(self):
299299
300300 # --- path rendering ----------------------------------------------------- #
301301
302- def test_paths_rendered_relative_when_under_notebook_dir (self ):
302+ def test_paths_kept_absolute_and_wrapped_in_resolve_path (self ):
303+ """Absolute paths survive into the paths-dict cell and each is wrapped
304+ in ``_resolve_path(...)`` so they're rebased through
305+ ``arc.common.globalize_path`` at notebook execution time. This makes
306+ the notebook robust to the user moving the project directory or
307+ running on a different machine — paths under ``<project>/calcs/Species/``
308+ or ``<project>/calcs/TSs/`` get auto-rebased to the new project root."""
303309 write_composite_notebook (** self .kwargs )
304310 paths_cell = next (c for c in self ._cells ()
305311 if c .cell_type == "code" and "paths = " in c .source
306312 and "parse_e_elect" not in c .source )
307- # Relative paths should start with './' and not have the tmp absolute prefix.
308- self .assertNotIn (self .tmp , paths_cell .source )
309- self .assertIn ("./base.out" , paths_cell .source )
310-
311- def test_paths_rendered_absolute_when_outside (self ):
312- # A path outside the notebook dir must appear as absolute.
313+ # Each path value must be wrapped in _resolve_path(...).
314+ self .assertIn ("_resolve_path(" , paths_cell .source )
315+ # Paths are stored as absolute strings so globalize_path can recognise
316+ # the project-directory prefix and rewrite it. The rewrite is a no-op
317+ # if the project hasn't moved.
318+ self .assertIn (self .base_path , paths_cell .source )
319+ self .assertIn (self .hi_path , paths_cell .source )
320+ self .assertIn (self .lo_path , paths_cell .source )
321+
322+ def test_paths_outside_project_survive_resolve_unchanged (self ):
323+ """Paths that don't match the ``/calcs/Species|TSs/`` pattern flow
324+ through ``globalize_path`` unchanged (it only rebases project-tree
325+ QM-output paths). They must still appear as absolutes wrapped in
326+ ``_resolve_path(...)`` — the notebook can't pre-judge what's
327+ inside vs outside the project."""
313328 outside_dir = tempfile .mkdtemp ()
314329 outside_path = os .path .join (outside_dir , "far.out" )
315330 _write_gaussian_fixture (outside_path , - 1.0 )
@@ -325,10 +340,26 @@ def test_paths_rendered_absolute_when_outside(self):
325340 if c .cell_type == "code" and "paths = " in c .source
326341 and "parse_e_elect" not in c .source )
327342 self .assertIn (outside_path , paths_cell .source )
343+ self .assertIn ("_resolve_path(" , paths_cell .source )
328344 finally :
329345 os .unlink (outside_path )
330346 os .rmdir (outside_dir )
331347
348+ def test_setup_cell_defines_resolve_path_and_imports_arc_common (self ):
349+ """The setup cell must define ``_resolve_path`` and import
350+ ``arc.common`` so the per-section paths-dict cells can call
351+ ``_resolve_path(...)`` on each absolute path."""
352+ write_composite_notebook (** self .kwargs )
353+ # Setup cell is the first code cell after the title/banner markdown.
354+ setup_cells = [c for c in self ._cells ()
355+ if c .cell_type == "code" and "_resolve_path" in c .source ]
356+ self .assertGreaterEqual (len (setup_cells ), 1 ,
357+ "Expected at least one code cell defining _resolve_path." )
358+ setup_src = setup_cells [0 ].source
359+ self .assertIn ("arc.common" , setup_src )
360+ self .assertIn ("globalize_path" , setup_src )
361+ self .assertIn ("def _resolve_path" , setup_src )
362+
332363 # --- determinism -------------------------------------------------------- #
333364
334365 def test_deterministic_byte_identical_across_runs (self ):
0 commit comments