diff --git a/cmdstanpy/model.py b/cmdstanpy/model.py index d1d96f48..d9f4e9fc 100644 --- a/cmdstanpy/model.py +++ b/cmdstanpy/model.py @@ -2027,7 +2027,14 @@ def diagnose( Gradients are evaluated in the unconstrained space. """ - with temp_single_json(data) as _data, temp_single_json(inits) as _inits: + with ( + temp_single_json(data) as _data, + temp_single_json(inits) as _inits, + # the output is read below and is not needed after this call. + tempfile.TemporaryDirectory( + prefix=self.name, dir=_TMPDIR + ) as output_dir, + ): cmd = [ str(self.exe_file), "diagnose", @@ -2036,14 +2043,12 @@ def diagnose( if epsilon is not None: cmd.append(f"epsilon={epsilon}") if error is not None: - cmd.append(f"epsilon={error}") + cmd.append(f"error={error}") if _data is not None: cmd += ["data", f"file={_data}"] if _inits is not None: cmd.append(f"init={_inits}") - output_dir = tempfile.mkdtemp(prefix=self.name, dir=_TMPDIR) - output = os.path.join(output_dir, "output.csv") cmd += ["output", f"file={output}"] if sig_figs is not None: diff --git a/test/test_model.py b/test/test_model.py index d725eed0..a6af29b5 100644 --- a/test/test_model.py +++ b/test/test_model.py @@ -11,6 +11,7 @@ import numpy as np import pytest +from cmdstanpy import _TMPDIR from cmdstanpy.model import CmdStanModel from cmdstanpy.utils import EXTENSION @@ -472,3 +473,36 @@ def test_diagnose() -> None: require_gradients_ok=False, ) assert np.abs(gradients["error"]).max() > 1e-3 + + +def test_diagnose_error_argument(caplog: pytest.LogCaptureFixture) -> None: + model = CmdStanModel(stan_file=BERN_STAN) + with caplog.at_level(logging.DEBUG, logger="cmdstanpy"): + model.diagnose(data=BERN_DATA, epsilon=1e-5, error=1e-3) + cmds = [r.getMessage() for r in caplog.records if "Cmd:" in r.message] + assert len(cmds) == 1 + assert "'epsilon=1e-05'" in cmds[0] + assert "'error=0.001'" in cmds[0] + assert cmds[0].count("epsilon=") == 1 + + +@pytest.mark.parametrize("fails", [False, True]) +def test_diagnose_removes_output_dir( + fails: bool, caplog: pytest.LogCaptureFixture +) -> None: + model = CmdStanModel(stan_file=BERN_STAN) + cmdstanpy_tmp = set(os.listdir(_TMPDIR)) + + with caplog.at_level(logging.DEBUG, logger="cmdstanpy"): + if fails: + with pytest.raises(RuntimeError, match="may exceed"): + model.diagnose(data=BERN_DATA, epsilon=3) + else: + model.diagnose(data=BERN_DATA) + + assert set(os.listdir(_TMPDIR)) == cmdstanpy_tmp + # the command is logged as a list repr, which escapes Windows separators + output_arg = "file=" + repr(str(_TMPDIR))[1:-1] + cmds = [r.getMessage() for r in caplog.records if "Cmd:" in r.message] + assert len(cmds) == 1 + assert output_arg in cmds[0]