Commit 272daf62 authored by Alexandre Duret-Lutz's avatar Alexandre Duret-Lutz

python: add a %%pml magic

Fixes #162.

* python/spot/ltsmin.i: Implement the magic.
* NEWS: Mention it.
* tests/python/ltsmin-pml.ipynb: New file.
* tests/Makefile.am, doc/org/tut.org: Add it.
* tests/python/ipnbdoctest.py: Adjust.
parent a7e4395f
......@@ -65,6 +65,11 @@ New in spot 2.0.1a (not yet released)
* Bindings for language_containment_checker were added.
* Under IPython the spot.ltsmin modules nows offers a
%%pml magic do define promela models, compile them
with spins, and dynamically load them. This is
akin to the %%dve magic that was already supported.
Documentation:
* A new example page shows how to test the equivalence of
......
......@@ -63,8 +63,8 @@ real notebooks instead.
- [[https://spot.lrde.epita.fr/ipynb/decompose.html][=decompose.ipynb=]] illustrates the =decompose_strength()= function
- [[https://spot.lrde.epita.fr/ipynb/testingaut.html][=testingaut.ipynb=]] shows the steps necessary to build a testing
automaton
- [[https://spot.lrde.epita.fr/ipynb/ltsmin-dve.html][=ltsmin-dve.ipynb=]] minimal test for loading a DiVinE model using
the LTSmin interface.
- [[https://spot.lrde.epita.fr/ipynb/ltsmin-dve.html][=ltsmin-dve.ipynb=]] loading a DiVinE model using the LTSmin interface.
- [[https://spot.lrde.epita.fr/ipynb/ltsmin-pml.html][=ltsmin-pml.ipynb=]] loading a Promela model using the LTSmin interface.
- [[https://spot.lrde.epita.fr/ipynb/word.html][=word.ipynb=]] example for the =twa_run= and =twa_word= classes.
- [[https://spot.lrde.epita.fr/ipynb/highlighting.html][=highlighting.ipynb=]] shows how to highlight states or edges in
automata.
......@@ -106,25 +106,31 @@ class model:
res += '\n';
return res
def require(tool):
def require(*tools):
"""
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)
for tool in tools:
if tool == "divine":
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)
elif tool == "spins":
if shutil.which("spins") == None:
print("spins not available", file=sys.stderr)
sys.exit(77)
else:
raise ValueError("unsupported argument for require(): " + tool)
# Load IPython specific support if we can.
......@@ -166,8 +172,36 @@ try:
spot.aux.rm_f(t.name + '.cpp')
spot.aux.rm_f(t.name + '2C')
@magics_class
class EditPML(Magics):
@cell_magic
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()
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)
ip.register_magics(EditPML)
except (ImportError, NameError):
pass
......
......@@ -297,6 +297,7 @@ TESTS_ipython = \
python/formulas.ipynb \
python/highlighting.ipynb \
python/ltsmin-dve.ipynb \
python/ltsmin-pml.ipynb \
python/piperead.ipynb \
python/product.ipynb \
python/randaut.ipynb \
......
......@@ -71,6 +71,10 @@ def sanitize(s):
# normalize graphviz version
s = re.sub(r'Generated by graphviz version.*', 'VERSION', s)
# remove Spins verbose output version
s = re.sub(r'SpinS Promela Compiler.*Compiled C model to .*pml.spins',
'SpinS output', s, flags=re.DOTALL)
# SVG generated by graphviz may put note at different positions
# depending on the graphviz build. Let's just strip anything that
# look like a position.
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment