cleanup ltsmin bindings

* python/spot/aux.py (rm_f): new function.
* python/spot/ltsmin.i: Replace the %require magic by a simple function.
Rewrite the %%dve magic.
* tests/python/otfcrash.py: Simplify using spot.ltsmin.require()
* tests/python/ltsmin.ipynb: Likewise, also add more text for the
documentation.
* NEWS: Adjust.
This commit is contained in:
Alexandre Duret-Lutz 2016-02-16 19:08:28 +01:00
parent 9b5a763538
commit 9692d734a9
5 changed files with 559 additions and 611 deletions

8
NEWS
View file

@ -104,11 +104,9 @@ New in spot 1.99.7a (not yet released)
Python: Python:
* The ltsmin interface has been binded in Python. See * The ltsmin interface has been binded in Python. It also
https://spot.lrde.epita.fr/ipynb/ltsmin.html for a short example. comes with a %%dve cell magic to edit DiVinE models in the notebook.
See https://spot.lrde.epita.fr/ipynb/ltsmin.html for a short example.
* The ltsmin interface support two extra 'magic commands' when ipython
is used: %dve and %%require.
* spot.setup() sets de maximum number of states to display in * spot.setup() sets de maximum number of states to display in
automata to 50 by default, as more states is likely to be automata to 50 by default, as more states is likely to be

View file

@ -24,7 +24,8 @@ Auxiliary functions for Spot's Python bindings
from functools import lru_cache from functools import lru_cache
import subprocess import subprocess
import sys import sys
import os
import errno
def extend(*classes): def extend(*classes):
""" """
@ -68,3 +69,14 @@ def ostream_to_svg(ostr):
Encode an ostringstream as utf-8 and send it to dot for cocnversion to SVG. Encode an ostringstream as utf-8 and send it to dot for cocnversion to SVG.
""" """
return str_to_svg(ostr.str().encode('utf-8')) return str_to_svg(ostr.str().encode('utf-8'))
def rm_f(filename):
"""
Remove filename if it exists.
"""
try:
os.remove(filename)
except OSError as e:
if e.errno != errno.ENOENT:
raise

View file

@ -67,6 +67,9 @@ namespace std {
%pythoncode %{ %pythoncode %{
import spot import spot
import spot.aux
import sys
import subprocess
def load(filename): def load(filename):
return model.load(filename) return model.load(filename)
@ -107,75 +110,65 @@ class model:
res += '\n'; res += '\n';
return res return res
def require(tool):
"""
Exit with status code 77 if the required tool is not installed.
This function is mostly useful in Spot test suite, where 77 is a
code used to indicate that some test should be skipped.
"""
if tool != "divine":
raise ValueError("unsupported argument for require(): " + tool)
import shutil
if shutil.which("divine") == None:
print ("divine not available", file=sys.stderr)
sys.exit(77)
out = subprocess.check_output(['divine', 'compile',
'--help'], stderr=subprocess.STDOUT)
if b'LTSmin' not in out:
print ("divine available but no support for LTSmin",
file=sys.stderr)
sys.exit(77)
# Load IPython specific support if we can. # Load IPython specific support if we can.
try: try:
# Load only if we are running IPython. # Load only if we are running IPython.
__IPYTHON__ __IPYTHON__
from IPython.core.magic import (Magics, magics_class, line_cell_magic) from IPython.core.magic import Magics, magics_class, cell_magic
from IPython.core.magic_arguments \
import (argument, magic_arguments, parse_argstring)
import os import os
import tempfile import tempfile
import sys
import shutil
try:
import ipywidgets as widgets
except ImportError:
pass
# This class provides support for %%dve model description
@magics_class @magics_class
class EditDVE(Magics): class EditDVE(Magics):
@line_cell_magic @cell_magic
def dve(self, line, cell=None): def dve(self, line, cell):
try: if not line:
# DiViNe prefers when files are in the current directory raise ValueError("missing variable name for %%dve")
# so write cell into local file # DiViNe prefers when files are in the current directory
t = tempfile.NamedTemporaryFile(dir=os.getcwd()) # so write cell into local file
filename = t.name + '.dve' with tempfile.NamedTemporaryFile(dir='.', suffix='.dve') as t:
f = open(filename,"w") t.write(cell.encode('utf-8'))
f.write(cell) t.flush()
f.close()
# Then compile and unlink temporary files
import subprocess
out=""
self.shell.user_ns[line] = None
out = subprocess.check_call(['divine', 'compile',
'--ltsmin', filename])
os.unlink(filename)
os.unlink(filename + '.cpp')
self.shell.user_ns[line] = load(filename + '2C')
os.unlink(filename + '2C')
except Exception as error:
try: try:
os.unlink(filename) p = subprocess.Popen(['divine', 'compile',
os.unlink(filename + '.cpp') '--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: finally:
if out != "": spot.aux.rm_f(t.name + '.cpp')
raise RuntimeError(out) from error spot.aux.rm_f(t.name + '2C')
raise error
@line_cell_magic
def require(self, line, cell=None):
if line != "divine":
print ("Unknown" + line, file=sys.stderr)
sys.exit(77)
if cell != None:
print ("No support for Cell magic command")
sys.exit(77)
if shutil.which("divine") == None:
print ("divine not available", file=sys.stderr)
sys.exit(77)
import subprocess
out = subprocess.check_output(['divine', 'compile',
'--help'], stderr=subprocess.STDOUT)
if b'LTSmin' not in out:
print ("divine available but no support for LTSmin",
file=sys.stderr)
sys.exit(77)
ip = get_ipython() ip = get_ipython()
ip.register_magics(EditDVE) ip.register_magics(EditDVE)

File diff suppressed because it is too large Load diff

View file

@ -4,14 +4,7 @@ import tempfile
import shutil import shutil
import sys import sys
# this test requires divine with --ltsmin support spot.ltsmin.require('divine')
if shutil.which("divine") == None:
sys.exit(77)
import subprocess
out = subprocess.check_output(['divine', 'compile',
'--help'], stderr=subprocess.STDOUT)
if b'LTSmin' not in out:
sys.exit(77)
# the test case actually starts here # the test case actually starts here
with tempfile.NamedTemporaryFile(dir='.', suffix='.dve') as fp: with tempfile.NamedTemporaryFile(dir='.', suffix='.dve') as fp: