mirror of https://github.com/dspinellis/UMLGraph
Provided documentation, an example and made some changes in the interface
This commit is contained in:
parent
ffba2e2f55
commit
c9a956a0ac
Binary file not shown.
|
|
@ -0,0 +1,23 @@
|
|||
initial()
|
||||
|
||||
compound_state(Application)
|
||||
state(A, Non Hire)
|
||||
styles(node, [fontname=Helvetica, fontcolor=red])
|
||||
state(B, New Hire,[entry/Candidate Hire, do/Add Employee])
|
||||
compound_end()
|
||||
|
||||
state(C, Employee, [entry/Intake New Employee])
|
||||
state(D, Retiree, [do/Employee Retirement])
|
||||
state(E, Former Employee, [do/Terminate, exit/Archive])
|
||||
|
||||
final()
|
||||
|
||||
transition(initial, B, Accepts offer)
|
||||
transition(initial, A, Rejects offer)
|
||||
transition(B, C, Begins work)
|
||||
transition(C, C, Boring Reality)
|
||||
transition(C, D, Employee Retires, [color=blue])
|
||||
transition(C, E, Employee Terminates, [color=red])
|
||||
transition(D, final)
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
stategraph
|
||||
========
|
||||
|
||||
Stategraph is a python script which allows the declarative specification and drawing of UML state diagrams.
|
||||
|
||||
|
||||
How to use it:
|
||||
--------
|
||||
|
||||
1) Use the commands stated below to declare a state diagram and save it in a text file.
|
||||
2) Change your directory to the place where both the script and the text file are located
|
||||
3) Run the script as stated below
|
||||
4) At the test-output directory you will find the diagram in the format you provided.
|
||||
|
||||
|
||||
State diagram commands
|
||||
--------
|
||||
|
||||
state(id, name, events[])
|
||||
-description:Creates a state
|
||||
-arguments: id: Unique identifier for the state inside the source (mandatory).
|
||||
name: Caption to be displayed (defaults to the state id).
|
||||
events[]: Events of the state (optional).
|
||||
|
||||
|
||||
transition(source, target, label, styling[])
|
||||
-description:Creates a transition
|
||||
-arguments: source: Source state identifier (mandatory).
|
||||
target: Target state identifier (mandatory).
|
||||
label: Caption to be displayed near the transition (optional).
|
||||
styling[]: Array of styling attributes to be applied (optional).
|
||||
|
||||
|
||||
initial()
|
||||
-description:The initial state. To be referred as initial when referenced in a transition.
|
||||
|
||||
|
||||
final()
|
||||
-description:The final state. To be referred as final when referenced in a transition.
|
||||
|
||||
|
||||
compound_state(name)
|
||||
-description: Creates a subgraph which includes states and transitions
|
||||
-arguments: name (optional)
|
||||
|
||||
|
||||
compound_end()
|
||||
-description: Ends the compound state
|
||||
|
||||
|
||||
styles(element, styling[])
|
||||
-description: Applies styling to the element specified
|
||||
-arguments: element (mandatory), styling[] (mandatory)
|
||||
|
||||
|
||||
note(id, note)
|
||||
-description: Applies a note to the state specified
|
||||
-arguments: node_id (mandatory), note (mandatory)
|
||||
|
||||
|
||||
Running the script
|
||||
------------
|
||||
|
||||
Run the script as stategraph.py [-o output_file] [-v] [input file]
|
||||
|
||||
1) If an output file is not specified a pdf is generated using
|
||||
the name of the input file.
|
||||
|
||||
2) The -v parameter will open the diagram for you to view
|
||||
|
||||
example: Running the script as stategraph.py -recruitment.txt -v -o recruitment.png
|
||||
will create a png file called recruitment in the test-output directory as well as
|
||||
open the file right away.
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
A full example containing both the declaration and the resulting diagram can be found
|
||||
under the stategraph example directory.
|
||||
|
||||
The example is called recruitment.txt and the generated pdf is called
|
||||
recruitment.pdf
|
||||
|
||||
|
||||
Support
|
||||
-------
|
||||
|
||||
If you are having issues, please let us know.
|
||||
Contact at: alkisplas@gmail.com
|
||||
|
|
@ -1,53 +1,13 @@
|
|||
"""
|
||||
|
||||
description:
|
||||
|
||||
This script allows the declarative specification of uml state diagrams.
|
||||
|
||||
1) use the commands stated below to form a state diagram and save it in a text file
|
||||
2) change your directory to the place where both the script and the text file are located
|
||||
3) provide the arguments as stated below
|
||||
4) at the test-output directory you will find the diagram both in dot format and in pdf.
|
||||
|
||||
cmd args:
|
||||
|
||||
argv[1]: input file name. (Mandatory)
|
||||
argv[2]: output file name. (Optional). Defaults to the input file's name
|
||||
argv[3]: view. (Optional). If true the generated pdf opens immediately. Defaults to False
|
||||
|
||||
commands:
|
||||
|
||||
state: creates a state
|
||||
arguments: id (mandatory), name (mandatory), events[](optional), style[](optional
|
||||
|
||||
transition: creates a transition
|
||||
arguments: source (mandatory), target (mandatory), label (optional), styling[] (optional)
|
||||
|
||||
initial: the initial node. To be referred as initial
|
||||
|
||||
final: the final node. To be referred as final
|
||||
|
||||
compound_state: creates a subgraph which includes states and transitions
|
||||
arguments: name (optional)
|
||||
|
||||
compound_end: ends the subgraph
|
||||
|
||||
styles: applies styling to the element specified
|
||||
arguments: element (mandatory), styling[] (mandatory)
|
||||
|
||||
note: applies a note to the state specified
|
||||
arguments: node_id (mandatory), note (mandatory)
|
||||
|
||||
"""
|
||||
|
||||
#!/usr/bin/env python
|
||||
|
||||
from graphviz import Digraph
|
||||
from pyparsing import *
|
||||
import sys
|
||||
|
||||
import argparse
|
||||
import os
|
||||
|
||||
# -----Parser-----
|
||||
|
||||
|
||||
LP, RP, LB, RB = map(Suppress, "()[]") # those will be skipped when iterating
|
||||
tokens = "+" + "'" + "=" + "/" + "_"
|
||||
|
||||
|
|
@ -65,10 +25,11 @@ rule = OneOrMore(Group(sentence)) # rule: sentence, sentence, ...
|
|||
|
||||
|
||||
def add_state(graph, args_list):
|
||||
"""
|
||||
Creates the state based on the arguments given
|
||||
|
||||
Args of args_list:
|
||||
""" Creates the state based on the arguments given
|
||||
|
||||
:param args_list:
|
||||
|
||||
args_list[0]: Unique identifier for the state inside the source(MANDATORY).
|
||||
args_list[1]: Caption to be displayed (defaults to the state id).
|
||||
args_list[2]: Events of the state(OPTIONAL).
|
||||
|
|
@ -88,13 +49,14 @@ def add_state(graph, args_list):
|
|||
|
||||
|
||||
def add_transition(graph, args_list):
|
||||
"""
|
||||
Creates the transition based on the arguments given
|
||||
|
||||
Args of args_list:
|
||||
args_list[0]: Start state identifier(MANDATORY).
|
||||
args_list[1]: End state identifier(MANDATORY).
|
||||
args_list[2]: Caption to be displayed near the edge(OPTIONAL).
|
||||
""" Creates the transition based on the arguments given
|
||||
|
||||
:param args_list :
|
||||
|
||||
args_list[0]: Source state identifier(MANDATORY).
|
||||
args_list[1]: Target state identifier(MANDATORY).
|
||||
args_list[2]: Caption to be displayed near the transition(OPTIONAL).
|
||||
args_list[3]: Any styling to be applied(OPTIONAL).
|
||||
"""
|
||||
|
||||
|
|
@ -159,8 +121,8 @@ def compound_state(args_list):
|
|||
|
||||
|
||||
def list_to_dict(alist):
|
||||
"""
|
||||
takes the list that contains the styling arguments to be applied
|
||||
|
||||
""" Takes the list that contains the styling arguments to be applied
|
||||
and turns it to a dictionary which graphviz understands
|
||||
"""
|
||||
|
||||
|
|
@ -172,9 +134,16 @@ def list_to_dict(alist):
|
|||
return changed_dict
|
||||
|
||||
|
||||
# Parses every line of the script and calls an add method depending on that line's action command
|
||||
|
||||
def parse_and_draw(graph, script):
|
||||
|
||||
""" Parses every line of the script and calls
|
||||
an add method depending on that line's action command
|
||||
|
||||
:param graph: current graph being used
|
||||
|
||||
:param script: txt file being parsed
|
||||
"""
|
||||
|
||||
entry = graph
|
||||
try:
|
||||
|
||||
|
|
@ -214,31 +183,45 @@ def parse_and_draw(graph, script):
|
|||
entry.subgraph(graph)
|
||||
graph = entry
|
||||
|
||||
# checks if user wants to view the graph right away
|
||||
if len(sys.argv) == 4:
|
||||
accepted_values = ['true', 'TRUE', 'True']
|
||||
if sys.argv[3] in accepted_values:
|
||||
view = True
|
||||
else:
|
||||
raise Exception("no suitable value for view")
|
||||
else:
|
||||
view = False
|
||||
|
||||
if sys.argv[2]: # if the user has specified an output file
|
||||
graph.render('test-output/'+str(sys.argv[2])+'.gv', view=view)
|
||||
'test-output/'+str(sys.argv[2])+'.pdf'
|
||||
else: # else use the input file's name
|
||||
graph.render('test-output/'+str(sys.argv[1])+'.gv', view=view)
|
||||
'test-output/'+str(sys.argv[1])+'.pdf'
|
||||
return graph
|
||||
|
||||
except Exception as e:
|
||||
|
||||
print "could not draw diagram because: " + str(e)
|
||||
|
||||
|
||||
# Reads data from the input file
|
||||
def render_graph(cmd_args, graph):
|
||||
|
||||
with open(str(sys.argv[1])) as f:
|
||||
""" Renders the graph and generates the output files as specified by the user
|
||||
If an output file is not specified. A pdf is generated using
|
||||
the name of the input file.
|
||||
The extension dot is erased because the format function can't handle it.
|
||||
|
||||
:param cmd_args: contains the input file, the viewing preference and the output file
|
||||
:param graph: graph to render
|
||||
"""
|
||||
|
||||
if cmd_args.output is not None:
|
||||
filename, file_extension = os.path.splitext(cmd_args.output)
|
||||
|
||||
else:
|
||||
filename = os.path.splitext(cmd_args.filename)[0]
|
||||
file_extension = 'pdf'
|
||||
|
||||
graph.format = file_extension.replace('.', '')
|
||||
|
||||
graph.render('test-output/' + filename, view=cmd_args.view)
|
||||
|
||||
|
||||
# parse cmd arguments
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("filename")
|
||||
parser.add_argument("-v", "--view", action="store_true", default=False)
|
||||
parser.add_argument("-o", "--output", type=str)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.filename) as f:
|
||||
content = f.read().splitlines()
|
||||
|
||||
script = "\n".join(content)
|
||||
|
|
@ -246,4 +229,4 @@ script = "\n".join(content)
|
|||
g1 = Digraph('g1', node_attr={'shape': 'box', 'style': 'rounded'})
|
||||
g1.body.extend(['rankdir=LR']) # graph's direction left-->right
|
||||
|
||||
parse_and_draw(g1, script)
|
||||
render_graph(args, parse_and_draw(g1, script))
|
||||
Loading…
Reference in New Issue