Skip to content

Commit

Permalink
Add sismic-plantuml CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexandreDecan committed Sep 1, 2019
1 parent 901b3cc commit 622650b
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 4 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Changelog
=========

Unreleased
----------

- (Added) A ``sismic-plantuml`` command-line utility to access ``sismic.io.export_to_plantuml``.


1.4.2 (2019-07-19)
------------------
Expand Down
4 changes: 2 additions & 2 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ Sismic statecharts provides full support for the majority of the UML 2 statechar

installation
format
visualization
execution
code
time

.. toctree::
:caption: Statechart testing
Expand All @@ -79,9 +79,9 @@ Sismic statecharts provides full support for the majority of the UML 2 statechar
:caption: Advanced topics
:maxdepth: 2

time
concurrent
integration
extensions

.. toctree::
:caption: Misc
Expand Down
76 changes: 76 additions & 0 deletions docs/visualization.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
Statecharts visualization
=========================

Sismic is not bundle with any graphical tool that can be used to edit or even view a statechart.
Module :py:mod:`sismic.io` contains routines that can be used to (import and) export statecharts to other formats,
some of them being used by third-party tools that support visualising (or editing) statecharts.

Notably, module :py:mod:`sismic.io` contains a function :py:func:`~sismic.io.export_to_plantuml` that exports a given statechart to
`PlantUML <http://plantuml.com/>`__, a tool based on graphviz that can automatically render statecharts (to some extent).
An online version of PlantUML can be found `here <http://www.plantuml.com/plantuml/>`__.

Function :py:func:`~sismic.io.export_to_plantuml` can be directly called from the command-line
without having to run a Python interpreter, through the ``sismic-plantuml`` (or ``python -m sismic.io.plantuml``)
command-line interface.

.. code-block:: none
usage: sismic-plantuml [-h] [--based-on based] [--show-description]
[--show-preamble] [--show-state-contracts]
[--show-transition-contracts] [--hide-state-action]
[--hide-name] [--hide-transition-action]
statechart
Command-line utility to export Sismic statecharts to plantUML.
See sismic.io.export_to_plantuml for more informations.
positional arguments:
statechart A YAML file describing a statechart
optional arguments:
-h, --help show this help message and exit
--based-on based A previously exported PlantUML representation
for this statechart
--show-description Show statechart description
--show-preamble Show statechart preamble
--show-state-contracts Show state contracts
--show-transition-contracts Show transition contracts
--hide-state-action Hide state action
--hide-name Hide statechart name
--hide-transition-action Hide transition action
For example, the elevator statechart presented in the previous section can be exported to the following PlantUML excerpt.

.. literalinclude:: /examples/elevator/elevator.plantuml

This PlantUML description can automatically be converted to the following statechart representation
using the PlantUML tool (an online version can be found `here <http://www.plantuml.com/plantuml/>`__).

.. image:: /examples/elevator/elevator.png
:align: center




.. seealso:: PlantUML's rendering can be modified to some extent by adjusting the notation used for transitions.
By default, ``-->`` transitions correspond to downward transitions of good length.

A transition can be shortened by using ``->`` instead of ``-->``, and the direction of a transition can be
changed by using ``-up->``, ``-right->``, ``-down->`` or ``-left->``. Both changes can be applied at the same time
using ``-u->``, ``-r->``, ``-d->`` or ``-l->``.
See `PlantUML documentation <http://plantuml.com/state-diagram>`__ for more information.

If you already exported a statechart to PlantUML and made some changes to the direction or length of the
transitions, it is likely that you want to keep these changes when exporting again the (possibly modified)
statechart to PlantUML.

The :py:func:`~sismic.io.export_to_plantuml` function accepts two optional (mutually exclusive) parameters ``based_on``
and ``based_on_filepath`` that can be used to provide an earlier version of a PlantUML text representation
(or a path to such a version if ``based_on_filepath`` is used).
This will then be used to incorporate as much as possible the changes made on transitions.

.. autofunction:: sismic.io.export_to_plantuml
:noindex:


1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
entry_points={
'console_scripts': [
'sismic-bdd=sismic.bdd.__main__:cli',
'sismic-plantuml=sismic.io.plantuml:cli',
],
},

Expand Down
53 changes: 52 additions & 1 deletion sismic/io/plantuml.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import argparse
import re
import sys

from typing import Dict, List, Tuple, Optional
from ..io import import_from_yaml
from ..model import (
DeepHistoryState, FinalState, Transition, CompoundState,
OrthogonalState, ShallowHistoryState, Statechart,
Expand Down Expand Up @@ -297,4 +300,52 @@ def export_to_plantuml(
with open(filepath, 'w') as f:
f.write(output)

return output
return output


def cli(args=None) -> int:
parser = argparse.ArgumentParser(
prog='sismic-plantuml',
description='Command-line utility to export Sismic statecharts to plantUML.\n'
'See sismic.io.export_to_plantuml for more informations.'
)

parser.add_argument('statechart', metavar='statechart', type=str,
help='A YAML file describing a statechart')
parser.add_argument('--based-on', metavar='based', type=str, default=None,
help='A previously exported PlantUML representation for this statechart.')

parser.add_argument('--show-description', dest='statechart_description', action='store_true', default=False, help='Show statechart description')
parser.add_argument('--show-preamble', dest='statechart_preamble', action='store_true', default=False, help='Show statechart preamble')
parser.add_argument('--show-state-contracts', dest='state_contracts', action='store_true', default=False, help='Show state contracts')
parser.add_argument('--show-transition-contracts', dest='transition_contracts', action='store_false', default=False, help='Show transition contracts')
parser.add_argument('--hide-state-action', dest='state_action', action='store_false', default=True, help='Hide state action')
parser.add_argument('--hide-name', dest='statechart_name', action='store_false', default=True, help='Hide statechart name')
parser.add_argument('--hide-transition-action', dest='transition_action', action='store_false', default=True, help='Hide transition action')

args, parameters = parser.parse_known_args(args)

statechart = import_from_yaml(filepath=args.statechart)

if args.based_on:
with open(args.based_on, 'r') as f:
args.based_on = f.read()

exporter = PlantUMLExporter(
statechart,
based_on=args.based_on,
statechart_name=args.statechart_name,
statechart_description=args.statechart_description,
statechart_preamble=args.statechart_preamble,
state_contracts=args.state_contracts,
state_action=args.state_action,
transition_contracts=args.transition_contracts,
transition_action=args.transition_action,
)

print(exporter.export())
return 0


if __name__ == '__main__':
sys.exit(cli())
2 changes: 1 addition & 1 deletion sismic/io/yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class SCHEMA:
}


def import_from_yaml(text: Iterable[str]=None, filepath: str=None, *, ignore_schema: bool=False, ignore_validation: bool=False) -> Statechart:
def import_from_yaml(text: str=None, filepath: str=None, *, ignore_schema: bool=False, ignore_validation: bool=False) -> Statechart:
"""
Import a statechart from a YAML representation (first argument) or a YAML file (filepath argument).
Expand Down
16 changes: 16 additions & 0 deletions tests/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from sismic.model import Statechart
from sismic.exceptions import StatechartError
from sismic.io import import_from_yaml, export_to_yaml, export_to_plantuml
from sismic.io.plantuml import cli


def compare_statecharts(s1, s2):
Expand Down Expand Up @@ -152,3 +153,18 @@ def test_export_based_on_filepath(self, elevator):
assert p1 == export_to_plantuml(statechart, based_on_filepath=filepath)


def test_cli(self, capsys):
filepath = 'docs/examples/elevator/elevator.yaml'
statechart = import_from_yaml(filepath=filepath)

# Check default parameters
cli([filepath])
out, _ = capsys.readouterr()
assert export_to_plantuml(statechart) == out.strip()

# Check all parameters
cli([filepath, '--based-on', 'docs/examples/elevator/elevator.plantuml', '--show-description', '--show-preamble', '--show-state-contracts', '--show-transition-contracts', '--hide-state-action', '--hide-name', '--hide-transition-action'])
out, _ = capsys.readouterr()
export = export_to_plantuml(statechart, based_on_filepath='docs/examples/elevator/elevator.plantuml', statechart_description=True, statechart_preamble=True, state_contracts=True, transition_contracts=True, state_action=False, statechart_name=False, transition_action=False)
assert export == out.strip()

0 comments on commit 622650b

Please sign in to comment.