diff --git a/NEWS b/NEWS index d449e632d..ef5abfd32 100644 --- a/NEWS +++ b/NEWS @@ -127,6 +127,10 @@ New in spot 2.0.3a (not yet released) with spins, and dynamically load them. This is akin to the %%dve magic that was already supported. + * The %%dve and %%pml magics honor the SPOT_TMPDIR and + TMPDIR environment variables. This especially helps + when the current directory is read-only. + Documentation: * A new example page shows how to test the equivalence of diff --git a/python/spot/aux.py b/python/spot/aux.py index 9990df882..caf117653 100644 --- a/python/spot/aux.py +++ b/python/spot/aux.py @@ -26,6 +26,7 @@ import subprocess import sys import os import errno +import contextlib def extend(*classes): """ @@ -80,3 +81,13 @@ def rm_f(filename): except OSError as e: if e.errno != errno.ENOENT: raise + +@contextlib.contextmanager +def tmpdir(): + cwd = os.getcwd() + tmpdir = os.environ.get('SPOT_TMPDIR') or os.environ.get('TMPDIR') or '.' + try: + os.chdir(tmpdir) + yield + finally: + os.chdir(cwd) diff --git a/python/spot/ltsmin.i b/python/spot/ltsmin.i index 70f7dbf8b..2a8f110dd 100644 --- a/python/spot/ltsmin.i +++ b/python/spot/ltsmin.i @@ -149,28 +149,27 @@ try: def dve(self, line, cell): if not line: raise ValueError("missing variable name for %%dve") - # DiViNe prefers when files are in the current directory - # so write cell into local file - with tempfile.NamedTemporaryFile(dir='.', suffix='.dve') as t: - t.write(cell.encode('utf-8')) - t.flush() + with spot.aux.tmpdir(): + with tempfile.NamedTemporaryFile(dir='.', suffix='.dve') as t: + t.write(cell.encode('utf-8')) + t.flush() - try: - p = subprocess.Popen(['divine', 'compile', - '--ltsmin', t.name], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - universal_newlines=True) - out = p.communicate() - if out[0]: - print(out[0], file=sys.stderr) - ret = p.wait() - if ret: - raise subprocess.CalledProcessError(ret, 'divine') - self.shell.user_ns[line] = load(t.name + '2C') - finally: - spot.aux.rm_f(t.name + '.cpp') - spot.aux.rm_f(t.name + '2C') + try: + p = subprocess.Popen(['divine', 'compile', + '--ltsmin', t.name], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True) + out = p.communicate() + if out[0]: + print(out[0], file=sys.stderr) + ret = p.wait() + if ret: + raise subprocess.CalledProcessError(ret, 'divine') + self.shell.user_ns[line] = load(t.name + '2C') + finally: + spot.aux.rm_f(t.name + '.cpp') + spot.aux.rm_f(t.name + '2C') @magics_class class EditPML(Magics): @@ -179,25 +178,26 @@ try: def pml(self, line, cell): if not line: raise ValueError("missing variable name for %%pml") - with tempfile.NamedTemporaryFile(dir='.', suffix='.pml') as t: - t.write(cell.encode('utf-8')) - t.flush() + with spot.aux.tmpdir(): + with tempfile.NamedTemporaryFile(dir='.', suffix='.pml') as t: + t.write(cell.encode('utf-8')) + t.flush() - try: - p = subprocess.Popen(['spins', t.name], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - universal_newlines=True) - out = p.communicate() - if out[0]: - print(out[0], file=sys.stderr) - ret = p.wait() - if ret: - raise subprocess.CalledProcessError(ret, 'spins') - self.shell.user_ns[line] = load(t.name + '.spins') - finally: - spot.aux.rm_f(t.name + '.spins.c') - spot.aux.rm_f(t.name + '.spins') + try: + p = subprocess.Popen(['spins', t.name], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True) + out = p.communicate() + if out[0]: + print(out[0], file=sys.stderr) + ret = p.wait() + if ret: + raise subprocess.CalledProcessError(ret, 'spins') + self.shell.user_ns[line] = load(t.name + '.spins') + finally: + spot.aux.rm_f(t.name + '.spins.c') + spot.aux.rm_f(t.name + '.spins') ip = get_ipython() ip.register_magics(EditDVE)