1010
1111try:
1212 from django.db.models import get_apps, get_app, get_models, get_model
13+
1314 NEW_META_API = False
1415except ImportError:
1516 from django.apps import apps
17+
1618 NEW_META_API = True
1719
1820from django import VERSION
2224
2325def all_fsm_fields_data(model):
2426 if NEW_META_API:
25- return [(field, model) for field in model._meta.get_fields()
26- if isinstance(field, FSMFieldMixin)]
27+ return [(field, model) for field in model._meta.get_fields() if isinstance(field, FSMFieldMixin)]
2728 else:
28- return [(field, model) for field in model._meta.fields
29- if isinstance(field, FSMFieldMixin)]
29+ return [(field, model) for field in model._meta.fields if isinstance(field, FSMFieldMixin)]
3030
3131
3232def node_name(field, state):
3333 opts = field.model._meta
34- return "%s.%s.%s.%s" % (opts.app_label, opts.verbose_name.replace(' ', '_' ), field.name, state)
34+ return "%s.%s.%s.%s" % (opts.app_label, opts.verbose_name.replace(" ", "_" ), field.name, state)
3535
3636
3737def node_label(field, state):
38- if type(state) == int or (type(state) == bool and hasattr(field, ' choices' )):
38+ if type(state) == int or (type(state) == bool and hasattr(field, " choices" )):
3939 return force_text(dict(field.choices).get(state))
4040 else:
4141 return state
@@ -49,62 +49,63 @@ def generate_dot(fields_data):
4949
5050 # dump nodes and edges
5151 for transition in field.get_all_transitions(model):
52- if transition.source == '*' :
52+ if transition.source == "*" :
5353 any_targets.add((transition.target, transition.name))
54- elif transition.source == '+' :
54+ elif transition.source == "+" :
5555 any_except_targets.add((transition.target, transition.name))
5656 else:
57- _targets =\
58- (state for state in transition.target.allowed_states)\
59- if isinstance(transition.target, (GET_STATE, RETURN_VALUE))\
57+ _targets = (
58+ (state for state in transition.target.allowed_states)
59+ if isinstance(transition.target, (GET_STATE, RETURN_VALUE))
6060 else (transition.target,)
61- source_name_pair =\
62- ((state, node_name(field, state)) for state in transition.source.allowed_states)\
63- if isinstance(transition.source, (GET_STATE, RETURN_VALUE))\
61+ )
62+ source_name_pair = (
63+ ((state, node_name(field, state)) for state in transition.source.allowed_states)
64+ if isinstance(transition.source, (GET_STATE, RETURN_VALUE))
6465 else ((transition.source, node_name(field, transition.source)),)
66+ )
6567 for source, source_name in source_name_pair:
6668 if transition.on_error:
6769 on_error_name = node_name(field, transition.on_error)
68- targets.add(
69- (on_error_name, node_label(field, transition.on_error))
70- )
71- edges.add((source_name, on_error_name, (('style', 'dotted'),)))
70+ targets.add((on_error_name, node_label(field, transition.on_error)))
71+ edges.add((source_name, on_error_name, (("style", "dotted"),)))
7272 for target in _targets:
73- add_transition(source, target, transition.name,
74- source_name, field, sources, targets, edges)
73+ add_transition(source, target, transition.name, source_name, field, sources, targets, edges)
7574
76- targets.update(set((node_name(field, target), node_label(field, target))
77- for target, _ in chain(any_targets, any_except_targets)))
75+ targets.update(
76+ set((node_name(field, target), node_label(field, target)) for target, _ in chain(any_targets, any_except_targets))
77+ )
7878 for target, name in any_targets:
7979 target_name = node_name(field, target)
8080 all_nodes = sources | targets
8181 for source_name, label in all_nodes:
8282 sources.add((source_name, label))
83- edges.add((source_name, target_name, ((' label' , name),)))
83+ edges.add((source_name, target_name, ((" label" , name),)))
8484
8585 for target, name in any_except_targets:
8686 target_name = node_name(field, target)
8787 all_nodes = sources | targets
8888 all_nodes.remove(((target_name, node_label(field, target))))
8989 for source_name, label in all_nodes:
9090 sources.add((source_name, label))
91- edges.add((source_name, target_name, ((' label' , name),)))
91+ edges.add((source_name, target_name, ((" label" , name),)))
9292
9393 # construct subgraph
9494 opts = field.model._meta
9595 subgraph = graphviz.Digraph(
9696 name="cluster_%s_%s_%s" % (opts.app_label, opts.object_name, field.name),
97- graph_attr={'label': "%s.%s.%s" % (opts.app_label, opts.object_name, field.name)})
97+ graph_attr={"label": "%s.%s.%s" % (opts.app_label, opts.object_name, field.name)},
98+ )
9899
99100 final_states = targets - sources
100101 for name, label in final_states:
101- subgraph.node(name, label=label, shape=' doublecircle' )
102+ subgraph.node(name, label=label, shape=" doublecircle" )
102103 for name, label in (sources | targets) - final_states:
103- subgraph.node(name, label=label, shape=' circle' )
104+ subgraph.node(name, label=label, shape=" circle" )
104105 if field.default: # Adding initial state notation
105106 if label == field.default:
106- initial_name = node_name(field, ' _initial' )
107- subgraph.node(name=initial_name, label='' , shape=' point' )
107+ initial_name = node_name(field, " _initial" )
108+ subgraph.node(name=initial_name, label="" , shape=" point" )
108109 subgraph.edge(initial_name, name)
109110 for source_name, target_name, attrs in edges:
110111 subgraph.edge(source_name, target_name, **dict(attrs))
@@ -118,7 +119,7 @@ def add_transition(transition_source, transition_target, transition_name, source
118119 target_name = node_name(field, transition_target)
119120 sources.add((source_name, node_label(field, transition_source)))
120121 targets.add((target_name, node_label(field, transition_target)))
121- edges.add((source_name, target_name, ((' label' , transition_name),)))
122+ edges.add((source_name, target_name, ((" label" , transition_name),)))
122123
123124
124125def get_graphviz_layouts():
@@ -127,50 +128,70 @@ def get_graphviz_layouts():
127128
128129 return graphviz.backend.ENGINES
129130 except Exception:
130- return {' sfdp', ' circo', ' twopi', ' dot', ' neato', ' fdp', ' osage', ' patchwork' }
131+ return {" sfdp", " circo", " twopi", " dot", " neato", " fdp", " osage", " patchwork" }
131132
132133
133134class Command(BaseCommand):
134135 requires_system_checks = True
135136
136137 if not HAS_ARGPARSE:
137138 option_list = BaseCommand.option_list + (
138- make_option('--output', '-o', action='store', dest='outputfile',
139- help=('Render output file. Type of output dependent on file extensions. '
140- 'Use png or jpg to render graph to image.')),
139+ make_option(
140+ "--output",
141+ "-o",
142+ action="store",
143+ dest="outputfile",
144+ help=(
145+ "Render output file. Type of output dependent on file extensions. " "Use png or jpg to render graph to image."
146+ ),
147+ ),
141148 # NOQA
142- make_option('--layout', '-l', action='store', dest='layout', default='dot',
143- help=('Layout to be used by GraphViz for visualization. '
144- 'Layouts: %s.' % ' '.join(get_graphviz_layouts()))),
149+ make_option(
150+ "--layout",
151+ "-l",
152+ action="store",
153+ dest="layout",
154+ default="dot",
155+ help=("Layout to be used by GraphViz for visualization. " "Layouts: %s." % " ".join(get_graphviz_layouts())),
156+ ),
145157 )
146158 args = "[appname[.model[.field]]]"
147159 else:
160+
148161 def add_arguments(self, parser):
149162 parser.add_argument(
150- '--output', '-o', action='store', dest='outputfile',
151- help=('Render output file. Type of output dependent on file extensions. '
152- 'Use png or jpg to render graph to image.'))
163+ "--output",
164+ "-o",
165+ action="store",
166+ dest="outputfile",
167+ help=(
168+ "Render output file. Type of output dependent on file extensions. " "Use png or jpg to render graph to image."
169+ ),
170+ )
153171 parser.add_argument(
154- '--layout', '-l', action='store', dest='layout', default='dot',
155- help=('Layout to be used by GraphViz for visualization. '
156- 'Layouts: %s.' % ' '.join(get_graphviz_layouts())))
157- parser.add_argument('args', nargs='*',
158- help=('[appname[.model[.field]]]'))
172+ "--layout",
173+ "-l",
174+ action="store",
175+ dest="layout",
176+ default="dot",
177+ help=("Layout to be used by GraphViz for visualization. " "Layouts: %s." % " ".join(get_graphviz_layouts())),
178+ )
179+ parser.add_argument("args", nargs="*", help=("[appname[.model[.field]]]"))
159180
160- help = ( "Creates a GraphViz dot file with transitions for selected fields")
181+ help = "Creates a GraphViz dot file with transitions for selected fields"
161182
162183 def render_output(self, graph, **options):
163- filename, format = options[' outputfile' ].rsplit('.' , 1)
184+ filename, format = options[" outputfile" ].rsplit("." , 1)
164185
165- graph.engine = options[' layout' ]
186+ graph.engine = options[" layout" ]
166187 graph.format = format
167188 graph.render(filename)
168189
169190 def handle(self, *args, **options):
170191 fields_data = []
171192 if len(args) != 0:
172193 for arg in args:
173- field_spec = arg.split('.' )
194+ field_spec = arg.split("." )
174195
175196 if len(field_spec) == 1:
176197 if NEW_META_API:
@@ -204,7 +225,7 @@ def handle(self, *args, **options):
204225
205226 dotdata = generate_dot(fields_data)
206227
207- if options[' outputfile' ]:
228+ if options[" outputfile" ]:
208229 self.render_output(dotdata, **options)
209230 else:
210231 print(dotdata)
0 commit comments