Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions arc/job/env_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,10 @@ def rmg_env_command(py_args: str | list[str],
Resolution order, preserved from the call sites this replaced:
``MAMBA_EXE`` (exported by setup-micromamba in CI) → ``RMG_PYTHON`` from
ARC's settings (needed on conda/mambaforge installs where micromamba's
``conda`` shim is broken) → a launcher found on PATH, hunted for under a
``conda`` shim is broken; this branch invokes the interpreter directly,
so it also re-exports ``PYTHONPATH`` from ``RMG_PATH`` after scrubbing
ARC's leaked activation vars, restoring visibility of a source-tree
RMG-Py/Arkane checkout) → a launcher found on PATH, hunted for under a
login shell so that a conda initialization block in the user's profile is
still honoured.

Expand Down Expand Up @@ -240,11 +243,21 @@ def rmg_env_command(py_args: str | list[str],
])

if rmg_python and os.path.isfile(rmg_python):
return '\n'.join(preamble + [
rmg_path = settings.get('RMG_PATH')
lines = preamble + [
f'unset {" ".join(_ARC_ENV_ACTIVATION_VARS)}',
f'export PATH={shlex.quote(os.path.dirname(rmg_python))}:"$PATH"',
f'{shlex.quote(rmg_python)} {py_args}{suffix}',
])
]
if rmg_path:
# Restore PYTHONPATH to RMG_PATH after scrubbing ARC's leakage above.
# rmg_python is invoked directly (no launcher, no activation hooks), so
# on a source-tree RMG-Py/Arkane checkout reachable only via
# PYTHONPATH -- rather than pip-installed into rmg_env -- unsetting
# PYTHONPATH and stopping there leaves the child unable to import
# rmgpy/arkane at all.
lines.append(f'export PYTHONPATH={shlex.quote(rmg_path)}')
lines.append(f'{shlex.quote(rmg_python)} {py_args}{suffix}')
return '\n'.join(lines)

# No launcher pinned by an env var and no configured interpreter: hunt for a
# launcher on PATH. This runs under ``bash -l`` so the user's profile (where
Expand Down
37 changes: 37 additions & 0 deletions arc/job/env_run_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,5 +384,42 @@ def test_py_args_list_arkane_module_invocation_three_tokens(self):
self.assertIn('python -m arkane input.py', script)


class TestRmgEnvCommandPythonPath(unittest.TestCase):
"""The RMG_PYTHON (direct-interpreter) branch unsets PYTHONPATH along
with the rest of ARC's leaked activation vars, then must re-export it
from RMG_PATH -- otherwise a source-tree RMG-Py/Arkane checkout that is
only reachable via PYTHONPATH (not pip-installed into rmg_env) can never
be imported by the child interpreter."""

def setUp(self):
# Force the RMG_PYTHON branch: no MAMBA_EXE, and RMG_PYTHON resolves
# to a real file (RMG_PATH/RMG_PYTHON come from the patched settings
# dict below; os.path.isfile still needs a real path on disk, so
# point it at this test file itself).
self.env_patch = patch.dict(os.environ, {}, clear=False)
self.env_patch.start()
self.addCleanup(self.env_patch.stop)
os.environ.pop('MAMBA_EXE', None)
self.fake_rmg_python = __file__

def test_pythonpath_reexported_from_rmg_path(self):
settings_overrides = {'RMG_ENV_NAME': 'rmg_env', 'RMG_PYTHON': self.fake_rmg_python,
'RMG_PATH': '/opt/RMG-Py'}
with patch.dict('arc.job.env_run.settings', settings_overrides):
script = rmg_env_command("-c 'pass'")
self.assertIn(f'export PYTHONPATH={shlex.quote("/opt/RMG-Py")}', script)
# The re-export must come after the unset, so it is not clobbered.
unset_idx = script.index('unset ')
export_idx = script.index('export PYTHONPATH=')
self.assertLess(unset_idx, export_idx)

def test_no_pythonpath_export_when_rmg_path_falsy(self):
settings_overrides = {'RMG_ENV_NAME': 'rmg_env', 'RMG_PYTHON': self.fake_rmg_python,
'RMG_PATH': None}
with patch.dict('arc.job.env_run.settings', settings_overrides):
script = rmg_env_command("-c 'pass'")
self.assertNotIn('export PYTHONPATH=', script)


if __name__ == '__main__':
unittest.main()
Loading