New upstream version 0.20.1
Diane Trout
1 year, 3 months ago
0 | 0 | Changelog |
1 | 1 | ========= |
2 | ||
3 | ||
4 | Version 0.20.1 | |
5 | -------------- | |
6 | ||
7 | Fix documentation building: upgrade to Sphinx 5.0. | |
8 | ||
9 | Fix broken user guide links in API documentation. | |
10 | ||
11 | ||
12 | Version 0.20 | |
13 | ------------ | |
14 | ||
15 | Add keyword-only ``neato_no_op`` argument to ``.render()``, ``.pipe()``, | |
16 | and stand-alone ``graphviz.render()`` and ``graphviz.pipe()``. | |
17 | ||
18 | When building a ``Graph`` or ``Digraph``, | |
19 | warn about an expected DOT syntax error in rendering | |
20 | when passing a string that ends with an odd number of backslashes | |
21 | (e.g. invalid ``dot.node('spam', label='\\')`` | |
22 | instead of correct ``..., label=r'\\'`` | |
23 | for a node labled as a backslash). | |
24 | ||
25 | Increase visibility of ``graphviz.escape()`` in the documentation. | |
26 | ||
27 | ||
28 | Version 0.19.2 | |
29 | -------------- | |
30 | ||
31 | Drop Python 3.6 support (end of life 23 Dec 2021). | |
32 | ||
33 | Fix ``ExecutableNotFound`` and ``CalledProcessError`` in ``graphviz.__all__``. | |
34 | ||
35 | Better document ``0.18`` change of behaviour for the ``body`` argument/attribute | |
36 | (lines need to include their final newline). | |
2 | 37 | |
3 | 38 | |
4 | 39 | Version 0.19.1 |
146 | 181 | the yielded lines now include a final newline (``'\n'``). |
147 | 182 | This mimics iteration over ``file`` object lines in text mode. |
148 | 183 | |
184 | Change of behaviour: | |
185 | When adding custom DOT statements using the ``body`` argument | |
186 | of ``Graph`` or ``Digraph`` or appending to the ``body`` attribute | |
187 | of an instance, the lines now need to include their final newline (``'\n'``). | |
188 | ||
149 | 189 | When passing invalid parameters such as unknown ``engine``, ``format``, etc., |
150 | 190 | ``.render()`` now raises early before writing the file. |
151 | 191 | Call ``.save()`` explicitly to produce the previous (less safe) behaviour. |
0 | 0 | The MIT License (MIT) |
1 | 1 | |
2 | Copyright (c) 2013-2021 Sebastian Bank | |
2 | Copyright (c) 2013-2022 Sebastian Bank | |
3 | 3 | |
4 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy |
5 | 5 | of this software and associated documentation files (the "Software"), to deal |
0 | 0 | Metadata-Version: 2.1 |
1 | 1 | Name: graphviz |
2 | Version: 0.19.1 | |
2 | Version: 0.20.1 | |
3 | 3 | Summary: Simple Python interface for Graphviz |
4 | 4 | Home-page: https://github.com/xflr6/graphviz |
5 | 5 | Author: Sebastian Bank |
18 | 18 | Classifier: License :: OSI Approved :: MIT License |
19 | 19 | Classifier: Operating System :: OS Independent |
20 | 20 | Classifier: Programming Language :: Python :: 3 |
21 | Classifier: Programming Language :: Python :: 3.6 | |
22 | 21 | Classifier: Programming Language :: Python :: 3.7 |
23 | 22 | Classifier: Programming Language :: Python :: 3.8 |
24 | 23 | Classifier: Programming Language :: Python :: 3.9 |
25 | 24 | Classifier: Programming Language :: Python :: 3.10 |
26 | 25 | Classifier: Topic :: Scientific/Engineering :: Visualization |
27 | Requires-Python: >=3.6 | |
26 | Requires-Python: >=3.7 | |
28 | 27 | Provides-Extra: dev |
29 | 28 | Provides-Extra: test |
30 | 29 | Provides-Extra: docs |
69 | 68 | Installation |
70 | 69 | ------------ |
71 | 70 | |
72 | This package runs under Python 3.6+, use pip_ to install: | |
71 | This package runs under Python 3.7+, use pip_ to install: | |
73 | 72 | |
74 | 73 | .. code:: bash |
75 | 74 | |
156 | 155 | :align: center |
157 | 156 | :alt: round-table.svg |
158 | 157 | |
158 | **Caveat:** | |
159 | Backslash-escapes and strings of the form ``<...>`` | |
160 | have a special meaning in the DOT language. | |
161 | If you need to render arbitrary strings (e.g. from user input), | |
162 | check the details in the `user guide`_. | |
163 | ||
159 | 164 | |
160 | 165 | See also |
161 | 166 | -------- |
205 | 210 | .. _conda-forge-python-graphviz-feedstock: https://github.com/conda-forge/python-graphviz-feedstock |
206 | 211 | .. _conda-forge-graphviz: https://anaconda.org/conda-forge/graphviz |
207 | 212 | .. _conda-forge-graphviz-feedstock: https://github.com/conda-forge/graphviz-feedstock |
213 | ||
214 | .. _user guide: https://graphviz.readthedocs.io/en/stable/manual.html | |
208 | 215 | |
209 | 216 | .. _pygraphviz: https://pypi.org/project/pygraphviz/ |
210 | 217 | .. _graphviz-python: https://pypi.org/project/graphviz-python/ |
249 | 256 | .. |Binder-stable| image:: https://img.shields.io/badge/launch-binder%20(stable)-579ACA.svg?logo=data:image/png;base64,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 |
250 | 257 | :target: https://mybinder.org/v2/gh/xflr6/graphviz/stable |
251 | 258 | :alt: Binder (stable) |
252 | ||
253 |
36 | 36 | Installation |
37 | 37 | ------------ |
38 | 38 | |
39 | This package runs under Python 3.6+, use pip_ to install: | |
39 | This package runs under Python 3.7+, use pip_ to install: | |
40 | 40 | |
41 | 41 | .. code:: bash |
42 | 42 | |
123 | 123 | :align: center |
124 | 124 | :alt: round-table.svg |
125 | 125 | |
126 | **Caveat:** | |
127 | Backslash-escapes and strings of the form ``<...>`` | |
128 | have a special meaning in the DOT language. | |
129 | If you need to render arbitrary strings (e.g. from user input), | |
130 | check the details in the `user guide`_. | |
131 | ||
126 | 132 | |
127 | 133 | See also |
128 | 134 | -------- |
172 | 178 | .. _conda-forge-python-graphviz-feedstock: https://github.com/conda-forge/python-graphviz-feedstock |
173 | 179 | .. _conda-forge-graphviz: https://anaconda.org/conda-forge/graphviz |
174 | 180 | .. _conda-forge-graphviz-feedstock: https://github.com/conda-forge/graphviz-feedstock |
181 | ||
182 | .. _user guide: https://graphviz.readthedocs.io/en/stable/manual.html | |
175 | 183 | |
176 | 184 | .. _pygraphviz: https://pypi.org/project/pygraphviz/ |
177 | 185 | .. _graphviz-python: https://pypi.org/project/graphviz-python/ |
0 | """pytest command line options and doctest namespace.""" | |
0 | """pytest command line options and doctest flag definition/setup.""" | |
1 | 1 | |
2 | import pytest | |
2 | import doctest | |
3 | import unittest.mock | |
4 | ||
5 | NO_EXE = doctest.register_optionflag('NO_EXE') | |
6 | ||
7 | class NoExeChecker(doctest.OutputChecker): # noqa: E302 | |
8 | ||
9 | def check_output(self, want, got, optionflags, *args, **kwargs) -> bool: | |
10 | if optionflags & NO_EXE: | |
11 | return True | |
12 | return super().check_output(want, got, optionflags, *args, **kwargs) | |
13 | ||
14 | unittest.mock.patch.object(doctest, 'OutputChecker', new=NoExeChecker).start() # noqa: E305 | |
15 | ||
16 | import pytest # noqa: E402 | |
3 | 17 | |
4 | 18 | SKIP_EXE = '--skip-exe' |
5 | 19 |
32 | 32 | .. _DOT command: https://graphviz.org/doc/info/command.html |
33 | 33 | .. _DOT layouts: https://graphviz.org/docs/layouts/ |
34 | 34 | .. _DOT outputs: https://graphviz.org/docs/outputs/ |
35 | .. _DOT neato: https://graphviz.org/docs/layouts/neato/ | |
36 | .. _neato no-op: https://www.graphviz.org/doc/info/command.html#-n | |
35 | 37 | .. _DOT attrs: https://www.graphviz.org/doc/info/attrs.html |
38 | .. _DOT pos: https://graphviz.org/docs/attrs/pos/ | |
39 | .. _DOT overlap: https://graphviz.org/docs/attrs/overlap/ | |
40 | .. _DOT splines: https://graphviz.org/docs/attrs/splines/ | |
36 | 41 | .. _DOT escString: https://www.graphviz.org/docs/attr-types/escString/ |
37 | 42 | .. _DOT shapes: https://graphviz.org/doc/info/shapes.html |
38 | 43 | .. _DOT shapes HTML: https://graphviz.org/doc/info/shapes.html#html |
0 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
1 | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" | |
2 | "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | |
3 | <!-- Generated by graphviz version 2.49.3 (20211023.0002) | |
4 | --> | |
5 | <!-- Title: splines Pages: 1 --> | |
6 | <svg width="112pt" height="76pt" | |
7 | viewBox="0.00 0.00 111.60 75.80" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> | |
8 | <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 71.8)"> | |
9 | <title>splines</title> | |
10 | <polygon fill="white" stroke="transparent" points="-4,4 -4,-71.8 107.6,-71.8 107.6,4 -4,4"/> | |
11 | <!-- a --> | |
12 | <g id="node1" class="node"> | |
13 | <title>a</title> | |
14 | <ellipse fill="blue" stroke="blue" cx="1.8" cy="-1.8" rx="1.8" ry="1.8"/> | |
15 | </g> | |
16 | <!-- b --> | |
17 | <g id="node2" class="node"> | |
18 | <title>b</title> | |
19 | <ellipse fill="green" stroke="green" cx="101.8" cy="-1.8" rx="1.8" ry="1.8"/> | |
20 | </g> | |
21 | <!-- a->b --> | |
22 | <g id="edge1" class="edge"> | |
23 | <title>a->b</title> | |
24 | <path fill="none" stroke="black" d="M1.8,-1.8C31.8,-67.8 71.8,-61.8 101.8,-1.8"/> | |
25 | </g> | |
26 | <!-- c --> | |
27 | <g id="node3" class="node"> | |
28 | <title>c</title> | |
29 | <ellipse fill="red" stroke="red" cx="51.8" cy="-51.8" rx="1.8" ry="1.8"/> | |
30 | </g> | |
31 | </g> | |
32 | </svg> |
8 | 8 | graphviz.Source |
9 | 9 | graphviz.escape |
10 | 10 | graphviz.nohtml |
11 | graphviz.RequiredArgumentError | |
12 | 11 | graphviz.ExecutableNotFound |
13 | 12 | graphviz.CalledProcessError |
13 | graphviz.RequiredArgumentError | |
14 | 14 | graphviz.render |
15 | 15 | graphviz.pipe |
16 | 16 | graphviz.pipe_string |
91 | 91 | Exceptions |
92 | 92 | ---------- |
93 | 93 | |
94 | .. autoexception:: graphviz.ExecutableNotFound | |
95 | ||
96 | .. autoexception:: graphviz.CalledProcessError | |
97 | ||
94 | 98 | .. autoexception:: graphviz.RequiredArgumentError |
95 | ||
96 | .. autoexception:: graphviz.ExecutableNotFound | |
97 | ||
98 | .. autoexception:: graphviz.CalledProcessError | |
99 | 99 | |
100 | 100 | .. autoexception:: graphviz.FileExistsError |
101 | 101 | |
106 | 106 | .. autoexception:: graphviz.UnknownSuffixWarning |
107 | 107 | |
108 | 108 | .. autoexception:: graphviz.FormatSuffixMismatchWarning |
109 | ||
110 | .. autoexception:: graphviz.DotSyntaxWarning | |
109 | 111 | |
110 | 112 | |
111 | 113 | Low-level functions |
267 | 269 | | graph_attr: Mapping of ``(attribute, value)`` pairs for the graph. |
268 | 270 | | node_attr: Mapping of ``(attribute, value)`` pairs set for all nodes. |
269 | 271 | | edge_attr: Mapping of ``(attribute, value)`` pairs set for all edges. |
270 | | body: Iterable of verbatim lines to add to the graph ``body``. | |
272 | | body: Iterable of verbatim lines (including their final newline) | |
273 | | to add to the graph ``body``. | |
271 | 274 | | strict (bool): Rendering should merge multi-edges. |
272 | 275 | | |
273 | 276 | | Note: |
362 | 365 | | (``None`` or ``'graph'``, ``'node'``, ``'edge'``). |
363 | 366 | | attrs: Attributes to be set (must be strings, may be empty). |
364 | 367 | | |
365 | | See the `usage examples in the User Guide <attributes>`. | |
368 | | See the :ref:`usage examples in the User Guide <attributes>`. | |
366 | 369 | | |
367 | 370 | | clear(self, keep_attrs: bool = False) -> None |
368 | 371 | | Reset content to an empty body, clear graph/node/egde_attr mappings. |
389 | 392 | | The ``tail_name`` and ``head_name`` strings are separated |
390 | 393 | | by (optional) colon(s) into ``node`` name, ``port`` name, |
391 | 394 | | and ``compass`` (e.g. ``sw``). |
392 | | See `details in the User Guide <ports>`. | |
395 | | See :ref:`details in the User Guide <node-ports-compass>`. | |
393 | 396 | | |
394 | 397 | | edges(self, tail_head_iter) -> None |
395 | 398 | | Create a bunch of edges. |
403 | 406 | | The ``tail_name`` and ``head_name`` strings are separated |
404 | 407 | | by (optional) colon(s) into ``node`` name, ``port`` name, |
405 | 408 | | and ``compass`` (e.g. ``sw``). |
406 | | See `details in the User Guide <ports>`. | |
409 | | See :ref:`details in the User Guide <node-ports-compass>`. | |
407 | 410 | | |
408 | 411 | | node(self, |
409 | 412 | name: str, |
446 | 449 | | body: Verbatim lines to add to the subgraph ``body`` |
447 | 450 | | (``with``-block use). |
448 | 451 | | |
449 | | See the `usage examples in the User Guide <subgraphs>`. | |
452 | | See the :ref:`usage examples in the User Guide <subgraphs-clusters>`. | |
450 | 453 | | |
451 | 454 | | When used as a context manager, the returned new graph instance |
452 | 455 | | uses ``strict=None`` and the parent graph's values |
468 | 471 | format: Optional[str] = None, |
469 | 472 | renderer: Optional[str] = None, |
470 | 473 | formatter: Optional[str] = None, |
474 | neato_no_op: Union[bool, int, NoneType] = None, | |
471 | 475 | quiet: bool = False, |
472 | 476 | quiet_view: bool = False, *, |
473 | 477 | outfile: Union[os.PathLike, str, NoneType] = None, |
490 | 494 | | (``'cairo'``, ``'gd'``, ...). |
491 | 495 | | formatter: The output formatter used for rendering |
492 | 496 | | (``'cairo'``, ``'gd'``, ...). |
497 | | neato_no_op: Neato layout engine no-op flag. | |
493 | 498 | | quiet (bool): Suppress ``stderr`` output |
494 | 499 | | from the layout subprocess. |
495 | 500 | | quiet_view (bool): Suppress ``stderr`` output |
603 | 608 | format: Optional[str] = None, |
604 | 609 | renderer: Optional[str] = None, |
605 | 610 | formatter: Optional[str] = None, |
611 | neato_no_op: Union[bool, int, NoneType] = None, | |
606 | 612 | quiet: bool = False, *, |
607 | 613 | engine: Optional[str] = None, |
608 | 614 | encoding: Optional[str] = None) -> Union[bytes, str] |
615 | 621 | | (``'cairo'``, ``'gd'``, ...). |
616 | 622 | | formatter: The output formatter used for rendering |
617 | 623 | | (``'cairo'``, ``'gd'``, ...). |
624 | | neato_no_op: Neato layout engine no-op flag. | |
618 | 625 | | quiet (bool): Suppress ``stderr`` output |
619 | 626 | | from the layout subprocess. |
620 | 627 | | engine: Layout engine for rendering |
774 | 781 | | graph_attr: Mapping of ``(attribute, value)`` pairs for the graph. |
775 | 782 | | node_attr: Mapping of ``(attribute, value)`` pairs set for all nodes. |
776 | 783 | | edge_attr: Mapping of ``(attribute, value)`` pairs set for all edges. |
777 | | body: Iterable of verbatim lines to add to the graph ``body``. | |
784 | | body: Iterable of verbatim lines (including their final newline) | |
785 | | to add to the graph ``body``. | |
778 | 786 | | strict (bool): Rendering should merge multi-edges. |
779 | 787 | | |
780 | 788 | | Note: |
869 | 877 | | (``None`` or ``'graph'``, ``'node'``, ``'edge'``). |
870 | 878 | | attrs: Attributes to be set (must be strings, may be empty). |
871 | 879 | | |
872 | | See the `usage examples in the User Guide <attributes>`. | |
880 | | See the :ref:`usage examples in the User Guide <attributes>`. | |
873 | 881 | | |
874 | 882 | | clear(self, keep_attrs: bool = False) -> None |
875 | 883 | | Reset content to an empty body, clear graph/node/egde_attr mappings. |
896 | 904 | | The ``tail_name`` and ``head_name`` strings are separated |
897 | 905 | | by (optional) colon(s) into ``node`` name, ``port`` name, |
898 | 906 | | and ``compass`` (e.g. ``sw``). |
899 | | See `details in the User Guide <ports>`. | |
907 | | See :ref:`details in the User Guide <node-ports-compass>`. | |
900 | 908 | | |
901 | 909 | | edges(self, tail_head_iter) -> None |
902 | 910 | | Create a bunch of edges. |
910 | 918 | | The ``tail_name`` and ``head_name`` strings are separated |
911 | 919 | | by (optional) colon(s) into ``node`` name, ``port`` name, |
912 | 920 | | and ``compass`` (e.g. ``sw``). |
913 | | See `details in the User Guide <ports>`. | |
921 | | See :ref:`details in the User Guide <node-ports-compass>`. | |
914 | 922 | | |
915 | 923 | | node(self, |
916 | 924 | name: str, |
953 | 961 | | body: Verbatim lines to add to the subgraph ``body`` |
954 | 962 | | (``with``-block use). |
955 | 963 | | |
956 | | See the `usage examples in the User Guide <subgraphs>`. | |
964 | | See the :ref:`usage examples in the User Guide <subgraphs-clusters>`. | |
957 | 965 | | |
958 | 966 | | When used as a context manager, the returned new graph instance |
959 | 967 | | uses ``strict=None`` and the parent graph's values |
975 | 983 | format: Optional[str] = None, |
976 | 984 | renderer: Optional[str] = None, |
977 | 985 | formatter: Optional[str] = None, |
986 | neato_no_op: Union[bool, int, NoneType] = None, | |
978 | 987 | quiet: bool = False, |
979 | 988 | quiet_view: bool = False, *, |
980 | 989 | outfile: Union[os.PathLike, str, NoneType] = None, |
997 | 1006 | | (``'cairo'``, ``'gd'``, ...). |
998 | 1007 | | formatter: The output formatter used for rendering |
999 | 1008 | | (``'cairo'``, ``'gd'``, ...). |
1009 | | neato_no_op: Neato layout engine no-op flag. | |
1000 | 1010 | | quiet (bool): Suppress ``stderr`` output |
1001 | 1011 | | from the layout subprocess. |
1002 | 1012 | | quiet_view (bool): Suppress ``stderr`` output |
1110 | 1120 | format: Optional[str] = None, |
1111 | 1121 | renderer: Optional[str] = None, |
1112 | 1122 | formatter: Optional[str] = None, |
1123 | neato_no_op: Union[bool, int, NoneType] = None, | |
1113 | 1124 | quiet: bool = False, *, |
1114 | 1125 | engine: Optional[str] = None, |
1115 | 1126 | encoding: Optional[str] = None) -> Union[bytes, str] |
1122 | 1133 | | (``'cairo'``, ``'gd'``, ...). |
1123 | 1134 | | formatter: The output formatter used for rendering |
1124 | 1135 | | (``'cairo'``, ``'gd'``, ...). |
1136 | | neato_no_op: Neato layout engine no-op flag. | |
1125 | 1137 | | quiet (bool): Suppress ``stderr`` output |
1126 | 1138 | | from the layout subprocess. |
1127 | 1139 | | engine: Layout engine for rendering |
1380 | 1392 | format: Optional[str] = None, |
1381 | 1393 | renderer: Optional[str] = None, |
1382 | 1394 | formatter: Optional[str] = None, |
1395 | neato_no_op: Union[bool, int, NoneType] = None, | |
1383 | 1396 | quiet: bool = False, |
1384 | 1397 | quiet_view: bool = False, *, |
1385 | 1398 | outfile: Union[os.PathLike, str, NoneType] = None, |
1402 | 1415 | | (``'cairo'``, ``'gd'``, ...). |
1403 | 1416 | | formatter: The output formatter used for rendering |
1404 | 1417 | | (``'cairo'``, ``'gd'``, ...). |
1418 | | neato_no_op: Neato layout engine no-op flag. | |
1405 | 1419 | | quiet (bool): Suppress ``stderr`` output |
1406 | 1420 | | from the layout subprocess. |
1407 | 1421 | | quiet_view (bool): Suppress ``stderr`` output |
1498 | 1512 | format: Optional[str] = None, |
1499 | 1513 | renderer: Optional[str] = None, |
1500 | 1514 | formatter: Optional[str] = None, |
1515 | neato_no_op: Union[bool, int, NoneType] = None, | |
1501 | 1516 | quiet: bool = False, *, |
1502 | 1517 | engine: Optional[str] = None, |
1503 | 1518 | encoding: Optional[str] = None) -> Union[bytes, str] |
1510 | 1525 | | (``'cairo'``, ``'gd'``, ...). |
1511 | 1526 | | formatter: The output formatter used for rendering |
1512 | 1527 | | (``'cairo'``, ``'gd'``, ...). |
1528 | | neato_no_op: Neato layout engine no-op flag. | |
1513 | 1529 | | quiet (bool): Suppress ``stderr`` output |
1514 | 1530 | | from the layout subprocess. |
1515 | 1531 | | engine: Layout engine for rendering |
62 | 62 | |
63 | 63 | Use the :meth:`~.Graph.render` method to save the DOT source code |
64 | 64 | and render it with the default ``dot`` `layout engine <DOT layouts_>`_ |
65 | (see :ref:`below <Engines>` for using other layout engines). | |
65 | (see :ref:`below <engines>` for using other layout engines). | |
66 | 66 | |
67 | 67 | .. doctest:: |
68 | 68 | |
87 | 87 | |
88 | 88 | |
89 | 89 | .. include:: _links.rst |
90 | ||
91 | .. attention:: | |
92 | ||
93 | Backslash-escapes and strings of the form ``<...>`` | |
94 | have a special meaning in the DOT_ language | |
95 | and are currently passed on as is by this library. | |
96 | If you need to render arbitrary strings literally (e.g. from user input), | |
97 | consider wrapping them with the :func:`graphviz.escape` function first. | |
98 | See the sections on :ref:`backslash-escapes` | |
99 | and :ref:`quoting-and-html-like-labels` below for details.⏎ |
0 | # -*- coding: utf-8 -*- | |
1 | # | |
2 | 0 | # Configuration file for the Sphinx documentation builder. |
3 | 1 | # |
4 | # This file does only contain a selection of the most common options. For a | |
5 | # full list see the documentation: | |
2 | # This file only contains a selection of the most common options. For a full | |
3 | # list see the documentation: | |
6 | 4 | # https://www.sphinx-doc.org/en/master/usage/configuration.html |
7 | 5 | |
8 | 6 | # -- Path setup -------------------------------------------------------------- |
20 | 18 | # -- Project information ----------------------------------------------------- |
21 | 19 | |
22 | 20 | project = 'graphviz' |
23 | copyright = '2013-2021, Sebastian Bank' | |
21 | copyright = '2013-2022, Sebastian Bank' | |
24 | 22 | author = 'Sebastian Bank' |
25 | 23 | |
26 | # The short X.Y version | |
27 | version = '0.19.1' | |
28 | 24 | # The full version, including alpha/beta/rc tags |
29 | release = version | |
25 | release = '0.20.1' | |
30 | 26 | |
31 | 27 | |
32 | 28 | # -- General configuration --------------------------------------------------- |
33 | ||
34 | # If your documentation needs a minimal Sphinx version, state it here. | |
35 | # | |
36 | # needs_sphinx = '1.0' | |
37 | 29 | |
38 | 30 | # Add any Sphinx extension module names here, as strings. They can be |
39 | 31 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom |
60 | 52 | # Add any paths that contain templates here, relative to this directory. |
61 | 53 | templates_path = ['_templates'] |
62 | 54 | |
63 | # The suffix(es) of source filenames. | |
64 | # You can specify multiple suffix as a list of string: | |
65 | # | |
66 | # source_suffix = ['.rst', '.md'] | |
67 | source_suffix = '.rst' | |
68 | ||
69 | # The master toctree document. | |
70 | master_doc = 'index' | |
71 | ||
72 | # The language for content autogenerated by Sphinx. Refer to documentation | |
73 | # for a list of supported languages. | |
74 | # | |
75 | # This is also used if you do content translation via gettext catalogs. | |
76 | # Usually you set "language" from the command line for these cases. | |
77 | language = None | |
78 | ||
79 | 55 | # List of patterns, relative to source directory, that match files and |
80 | 56 | # directories to ignore when looking for source files. |
81 | # This pattern also affects html_static_path and html_extra_path . | |
57 | # This pattern also affects html_static_path and html_extra_path. | |
82 | 58 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] |
83 | 59 | |
84 | 60 | # The name of the Pygments (syntax highlighting) style to use. |
96 | 72 | html_theme = 'sphinx_rtd_theme' |
97 | 73 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] |
98 | 74 | |
99 | # Theme options are theme-specific and customize the look and feel of a theme | |
100 | # further. For a list of options available for each theme, see the | |
101 | # documentation. | |
102 | # | |
103 | # html_theme_options = {} | |
104 | ||
105 | 75 | # Add any paths that contain custom static files (such as style sheets) here, |
106 | 76 | # relative to this directory. They are copied after the builtin static files, |
107 | 77 | # so a file named "default.css" will overwrite the builtin "default.css". |
108 | 78 | html_static_path = ['_static'] |
109 | ||
110 | # Custom sidebar templates, must be a dictionary that maps document names | |
111 | # to template names. | |
112 | # | |
113 | # The default sidebars (for documents that don't match any pattern) are | |
114 | # defined by theme itself. Builtin themes are using these templates by | |
115 | # default: ``['localtoc.html', 'relations.html', 'sourcelink.html', | |
116 | # 'searchbox.html']``. | |
117 | # | |
118 | # html_sidebars = {} | |
119 | ||
120 | ||
121 | # -- Options for HTMLHelp output --------------------------------------------- | |
122 | ||
123 | # Output file base name for HTML help builder. | |
124 | htmlhelp_basename = 'graphvizdoc' | |
125 | ||
126 | ||
127 | # -- Options for LaTeX output ------------------------------------------------ | |
128 | ||
129 | latex_elements = { | |
130 | # The paper size ('letterpaper' or 'a4paper'). | |
131 | # | |
132 | # 'papersize': 'letterpaper', | |
133 | ||
134 | # The font size ('10pt', '11pt' or '12pt'). | |
135 | # | |
136 | # 'pointsize': '10pt', | |
137 | ||
138 | # Additional stuff for the LaTeX preamble. | |
139 | # | |
140 | # 'preamble': '', | |
141 | ||
142 | # Latex figure (float) alignment | |
143 | # | |
144 | # 'figure_align': 'htbp', | |
145 | } | |
146 | ||
147 | # Grouping the document tree into LaTeX files. List of tuples | |
148 | # (source start file, target name, title, | |
149 | # author, documentclass [howto, manual, or own class]). | |
150 | latex_documents = [ | |
151 | (master_doc, 'graphviz.tex', 'graphviz Documentation', | |
152 | 'Sebastian Bank', 'manual'), | |
153 | ] | |
154 | ||
155 | ||
156 | # -- Options for manual page output ------------------------------------------ | |
157 | ||
158 | # One entry per manual page. List of tuples | |
159 | # (source start file, name, description, authors, manual section). | |
160 | man_pages = [ | |
161 | (master_doc, 'graphviz', 'graphviz Documentation', | |
162 | [author], 1) | |
163 | ] | |
164 | ||
165 | ||
166 | # -- Options for Texinfo output ---------------------------------------------- | |
167 | ||
168 | # Grouping the document tree into Texinfo files. List of tuples | |
169 | # (source start file, target name, title, author, | |
170 | # dir menu entry, description, category) | |
171 | texinfo_documents = [ | |
172 | (master_doc, 'graphviz', 'graphviz Documentation', | |
173 | author, 'graphviz', 'One line description of project.', | |
174 | 'Miscellaneous'), | |
175 | ] | |
176 | 79 | |
177 | 80 | |
178 | 81 | # -- Extension configuration ------------------------------------------------- |
184 | 87 | 'py': ('https://docs.python.org/3', None), |
185 | 88 | } |
186 | 89 | |
187 | # monkey patch, see https://github.com/sphinx-doc/sphinx/issues/2044 | |
188 | from sphinx.ext.autodoc import ClassLevelDocumenter, InstanceAttributeDocumenter | |
189 | ||
190 | def add_directive_header(self, sig): | |
191 | ClassLevelDocumenter.add_directive_header(self, sig) | |
192 | ||
193 | InstanceAttributeDocumenter.add_directive_header = add_directive_header |
47 | 47 | |
48 | 48 | - GitHub Actions |
49 | 49 | `Build workflow <https://github.com/xflr6/graphviz/actions/workflows/build.yaml>`_ |
50 | (Python 3.6 to 3.10, experimental: PyPy 3.6 to 3.8) | |
50 | (Python 3.7 to 3.10, experimental: PyPy 3.7 to 3.8) | |
51 | 51 | - Codecov |
52 | 52 | `test coverage <https://app.codecov.io/gh/xflr6/graphviz>`_ |
53 | 53 | (`main branch <https://app.codecov.io/gh/xflr6/graphviz/branch/master>`_) |
1 | 1 | ------------ |
2 | 2 | |
3 | 3 | :doc:`graphviz <api>` provides a simple pure-Python interface for the Graphviz_ |
4 | graph-drawing software. It runs under Python 3.6+. To install it with pip_, run | |
4 | graph-drawing software. It runs under Python 3.7+. To install it with pip_, run | |
5 | 5 | the following: |
6 | 6 | |
7 | 7 | .. code:: bash |
41 | 41 | in repeated add/render/view cycles) |
42 | 42 | |
43 | 43 | |
44 | .. include:: _links.rst⏎ | |
44 | .. include:: _links.rst |
5 | 5 | |
6 | 6 | .. include:: installation.rst |
7 | 7 | |
8 | ||
9 | 8 | .. include:: basic_usage.rst |
10 | ||
11 | 9 | |
12 | 10 | .. include:: formats.rst |
13 | 11 | |
14 | ||
15 | 12 | .. include:: piped_output.rst |
16 | ||
17 | 13 | |
18 | 14 | .. include:: jupyter_notebooks.rst |
19 | 15 | |
20 | ||
21 | 16 | .. include:: styling.rst |
22 | 17 | |
23 | ||
18 | .. _attributes: | |
24 | 19 | .. include:: attributes.rst |
25 | 20 | |
26 | ||
21 | .. _node-ports-compass: | |
27 | 22 | .. include:: node_ports.rst |
28 | 23 | |
29 | ||
24 | .. _backslash-escapes: | |
30 | 25 | .. include:: escapes.rst |
31 | 26 | |
32 | ||
27 | .. _quoting-and-html-like-labels: | |
33 | 28 | .. include:: quoting.rst |
34 | 29 | |
35 | ||
30 | .. _subgraphs-clusters: | |
36 | 31 | .. include:: subgraphs_and_clusters.rst |
37 | 32 | |
38 | ||
39 | .. _Engines: | |
40 | ||
33 | .. _engines: | |
41 | 34 | .. include:: engines.rst |
42 | 35 | |
36 | .. include:: neato_no_op.rst | |
43 | 37 | |
44 | 38 | .. include:: unflatten.rst |
45 | 39 | |
46 | ||
47 | 40 | .. include:: custom_dot.rst |
48 | 41 | |
49 | ||
50 | .. _Sources: | |
51 | ||
42 | .. _using-raw-dot: | |
52 | 43 | .. include:: raw_dot.rst |
53 | ||
54 | 44 | |
55 | 45 | .. include:: existing_files.rst |
56 | 46 | |
57 | ||
58 | 47 | .. include:: integration_with_viewers.rst |
0 | ``neato`` no-op flag | |
1 | -------------------- | |
2 | ||
3 | The `neato <DOT neato_>`_ layout engine | |
4 | supports an additional `rendering flag <neato no-op_>`_ | |
5 | that allows more control over the node positioning and the edge layout | |
6 | via the `pos <DOT pos_>`_, | |
7 | `overlap <DOT overlap_>`_, | |
8 | and `splines <DOT splines_>`_ attributes. | |
9 | ||
10 | Use the ``neato_no_op`` keyword argument of | |
11 | :meth:`~.Graph.render` or :meth:`~.Graph.pipe` | |
12 | to pass it to the layout command: | |
13 | ||
14 | .. doctest:: | |
15 | ||
16 | >>> doctest_mark_exe() | |
17 | ||
18 | >>> import graphviz | |
19 | ||
20 | >>> n = graphviz.Digraph(name='splines', engine='neato', | |
21 | ... graph_attr={'splines': 'true'}, | |
22 | ... node_attr={'shape': 'point'}) | |
23 | >>> n.node('a', pos='0,0!', color='blue') | |
24 | >>> n.node('b', pos='100,0!', color='green') | |
25 | >>> n.node('c', pos='50,50!', color='red') | |
26 | >>> n.edge('a', 'b', pos='0,0 30,66 70,60 100,0') | |
27 | >>> n.render(neato_no_op=2, directory='doctest-output').replace('\\', '/') | |
28 | 'doctest-output/splines.gv.pdf' | |
29 | ||
30 | .. image:: _static/splines.svg | |
31 | :align: center | |
32 | ||
33 | ||
34 | .. include:: _links.rst |
5 | 5 | - Render `graphviz.org gallery`_ examples with logging: |
6 | 6 | `examples/graphviz-notebook.ipynb <nbviewer graphviz-notebook.ipynb_>`_ |
7 | 7 | (`source <GitHub graphviz-notebook.ipynb_>`_) |
8 | - `Laypout engine <DOT layouts_>`_ comparison: | |
8 | - `Layout engine <DOT layouts_>`_ comparison: | |
9 | 9 | `examples/graphviz-engines.ipynb <nbviewer graphviz-engines.ipynb_>`_ |
10 | 10 | (`source <GitHub graphviz-engines.ipynb_>`_) |
11 | 11 | - Example for :meth:`graphviz.set_jupyter_format`: |
44 | 44 | See :class:`API docs <.Source>`). |
45 | 45 | |
46 | 46 | |
47 | .. include:: _links.rst⏎ | |
47 | .. include:: _links.rst |
66 | 66 | .. code:: bash |
67 | 67 | |
68 | 68 | $ python setup.py sdist bdist_wheel |
69 | $ python -m twine check --strict dist/* | |
69 | 70 | |
70 | 71 | - ``dist/graphviz-$MAJOR.$MINOR[.$BUGFIX].zip`` |
71 | 72 | - ``dist/graphviz-$MAJOR.$MINOR[.$BUGFIX]-py3-none-any.whl`` |
43 | 43 | The method returns a :class:`.Source` object |
44 | 44 | that you can :meth:`~.Source.render`, :meth:`~.Source.view`, etc. |
45 | 45 | with the same basic API as :class:`.Graph` or :class:`.Digraph` objects |
46 | (minus modification, see details :ref:`below <Sources>`). | |
46 | (minus modification, see details :ref:`below <using-raw-dot>`). | |
47 | 47 | |
48 | 48 | .. doctest:: |
49 | 49 |
7 | 7 | { |
8 | 8 | "data": { |
9 | 9 | "text/plain": [ |
10 | "('0.19', (2, 40, 1))" | |
10 | "('0.20.dev0', (2, 40, 1))" | |
11 | 11 | ] |
12 | 12 | }, |
13 | 13 | "execution_count": 1, |
16 | 16 | } |
17 | 17 | ], |
18 | 18 | "source": [ |
19 | "#%cd -q ..\n", | |
19 | "%cd -q ..\n", | |
20 | 20 | "\n", |
21 | 21 | "import graphviz\n", |
22 | 22 | "\n", |
89 | 89 | "</svg>\n" |
90 | 90 | ], |
91 | 91 | "text/plain": [ |
92 | "<graphviz.graphs.Digraph at 0x7fa255779c10>" | |
92 | "<graphviz.graphs.Digraph at 0x7fc7701f6390>" | |
93 | 93 | ] |
94 | 94 | }, |
95 | 95 | "metadata": {}, |
157 | 157 | "</svg>\n" |
158 | 158 | ], |
159 | 159 | "text/plain": [ |
160 | "<graphviz.graphs.Digraph at 0x7fa255779c10>" | |
160 | "<graphviz.graphs.Digraph at 0x7fc7701f6390>" | |
161 | 161 | ] |
162 | 162 | }, |
163 | 163 | "metadata": {}, |
225 | 225 | "</svg>\n" |
226 | 226 | ], |
227 | 227 | "text/plain": [ |
228 | "<graphviz.graphs.Digraph at 0x7fa255779c10>" | |
228 | "<graphviz.graphs.Digraph at 0x7fc7701f6390>" | |
229 | 229 | ] |
230 | 230 | }, |
231 | 231 | "metadata": {}, |
293 | 293 | "</svg>\n" |
294 | 294 | ], |
295 | 295 | "text/plain": [ |
296 | "<graphviz.graphs.Digraph at 0x7fa255779c10>" | |
296 | "<graphviz.graphs.Digraph at 0x7fc7701f6390>" | |
297 | 297 | ] |
298 | 298 | }, |
299 | 299 | "metadata": {}, |
361 | 361 | "</svg>\n" |
362 | 362 | ], |
363 | 363 | "text/plain": [ |
364 | "<graphviz.graphs.Digraph at 0x7fa255779c10>" | |
364 | "<graphviz.graphs.Digraph at 0x7fc7701f6390>" | |
365 | 365 | ] |
366 | 366 | }, |
367 | 367 | "metadata": {}, |
411 | 411 | "</svg>\n" |
412 | 412 | ], |
413 | 413 | "text/plain": [ |
414 | "<graphviz.graphs.Digraph at 0x7fa255779c10>" | |
414 | "<graphviz.graphs.Digraph at 0x7fc7701f6390>" | |
415 | 415 | ] |
416 | 416 | }, |
417 | 417 | "metadata": {}, |
479 | 479 | "</svg>\n" |
480 | 480 | ], |
481 | 481 | "text/plain": [ |
482 | "<graphviz.graphs.Digraph at 0x7fa255779c10>" | |
482 | "<graphviz.graphs.Digraph at 0x7fc7701f6390>" | |
483 | 483 | ] |
484 | 484 | }, |
485 | 485 | "metadata": {}, |
547 | 547 | "</svg>\n" |
548 | 548 | ], |
549 | 549 | "text/plain": [ |
550 | "<graphviz.graphs.Digraph at 0x7fa255779c10>" | |
550 | "<graphviz.graphs.Digraph at 0x7fc7701f6390>" | |
551 | 551 | ] |
552 | 552 | }, |
553 | 553 | "metadata": {}, |
7 | 7 | { |
8 | 8 | "data": { |
9 | 9 | "text/plain": [ |
10 | "('0.19', (2, 49, 3))" | |
10 | "('0.20.dev0', (2, 40, 1))" | |
11 | 11 | ] |
12 | 12 | }, |
13 | 13 | "execution_count": 1, |
16 | 16 | } |
17 | 17 | ], |
18 | 18 | "source": [ |
19 | "#%cd -q ..\n", | |
19 | "%cd -q ..\n", | |
20 | 20 | "\n", |
21 | 21 | "import graphviz\n", |
22 | 22 | "\n", |
57 | 57 | "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n", |
58 | 58 | "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n", |
59 | 59 | " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n", |
60 | "<!-- Generated by graphviz version 2.49.3 (20211023.0002)\n", | |
61 | " -->\n", | |
62 | "<!-- Pages: 1 -->\n", | |
60 | "<!-- Generated by graphviz version 2.40.1 (20161225.0304)\n", | |
61 | " -->\n", | |
62 | "<!-- Title: %3 Pages: 1 -->\n", | |
63 | 63 | "<svg width=\"62pt\" height=\"44pt\"\n", |
64 | 64 | " viewBox=\"0.00 0.00 62.00 44.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", |
65 | 65 | "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 40)\">\n", |
66 | "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-40 58,-40 58,4 -4,4\"/>\n", | |
67 | "<!-- A -->\n", | |
68 | "<g id=\"node1\" class=\"node\">\n", | |
69 | "<title>A</title>\n", | |
70 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n", | |
71 | "<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">"</text>\n", | |
72 | "</g>\n", | |
73 | "</g>\n", | |
74 | "</svg>\n" | |
75 | ], | |
76 | "text/plain": [ | |
77 | "<graphviz.graphs.Digraph at 0x28003e87460>" | |
66 | "<title>%3</title>\n", | |
67 | "<polygon fill=\"#ffffff\" stroke=\"transparent\" points=\"-4,4 -4,-40 58,-40 58,4 -4,4\"/>\n", | |
68 | "<!-- A -->\n", | |
69 | "<g id=\"node1\" class=\"node\">\n", | |
70 | "<title>A</title>\n", | |
71 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"27\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n", | |
72 | "<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">"</text>\n", | |
73 | "</g>\n", | |
74 | "</g>\n", | |
75 | "</svg>\n" | |
76 | ], | |
77 | "text/plain": [ | |
78 | "<graphviz.graphs.Digraph at 0x7f1e5c1cb490>" | |
78 | 79 | ] |
79 | 80 | }, |
80 | 81 | "execution_count": 3, |
107 | 108 | "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n", |
108 | 109 | "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n", |
109 | 110 | " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n", |
110 | "<!-- Generated by graphviz version 2.49.3 (20211023.0002)\n", | |
111 | " -->\n", | |
112 | "<!-- Pages: 1 -->\n", | |
111 | "<!-- Generated by graphviz version 2.40.1 (20161225.0304)\n", | |
112 | " -->\n", | |
113 | "<!-- Title: %3 Pages: 1 -->\n", | |
113 | 114 | "<svg width=\"62pt\" height=\"44pt\"\n", |
114 | 115 | " viewBox=\"0.00 0.00 62.00 44.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", |
115 | 116 | "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 40)\">\n", |
116 | "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-40 58,-40 58,4 -4,4\"/>\n", | |
117 | "<!-- A -->\n", | |
118 | "<g id=\"node1\" class=\"node\">\n", | |
119 | "<title>A</title>\n", | |
120 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n", | |
121 | "<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">"</text>\n", | |
122 | "</g>\n", | |
123 | "</g>\n", | |
124 | "</svg>\n" | |
125 | ], | |
126 | "text/plain": [ | |
127 | "<graphviz.graphs.Digraph at 0x28003e879d0>" | |
117 | "<title>%3</title>\n", | |
118 | "<polygon fill=\"#ffffff\" stroke=\"transparent\" points=\"-4,4 -4,-40 58,-40 58,4 -4,4\"/>\n", | |
119 | "<!-- A -->\n", | |
120 | "<g id=\"node1\" class=\"node\">\n", | |
121 | "<title>A</title>\n", | |
122 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"27\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n", | |
123 | "<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">"</text>\n", | |
124 | "</g>\n", | |
125 | "</g>\n", | |
126 | "</svg>\n" | |
127 | ], | |
128 | "text/plain": [ | |
129 | "<graphviz.graphs.Digraph at 0x7f1e5c1dd310>" | |
128 | 130 | ] |
129 | 131 | }, |
130 | 132 | "execution_count": 4, |
145 | 147 | "name": "stderr", |
146 | 148 | "output_type": "stream", |
147 | 149 | "text": [ |
148 | "Error: <stdin>: syntax error in line 4 scanning a quoted string (missing endquote? longer than 16384?)\n", | |
150 | "/home/jovyan/graphviz/quoting.py:88: DotSyntaxWarning: expect syntax error scanning invalid quoted string: '\\\\'\n", | |
151 | " category=exceptions.DotSyntaxWarning)\n", | |
152 | "Error: <stdin>: syntax error in line 2 scanning a quoted string (missing endquote? longer than 16384?)\n", | |
149 | 153 | "String starting:\"\"]\n", |
150 | 154 | "}\n", |
151 | 155 | "\n" |
190 | 194 | "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n", |
191 | 195 | "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n", |
192 | 196 | " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n", |
193 | "<!-- Generated by graphviz version 2.49.3 (20211023.0002)\n", | |
194 | " -->\n", | |
195 | "<!-- Pages: 1 -->\n", | |
197 | "<!-- Generated by graphviz version 2.40.1 (20161225.0304)\n", | |
198 | " -->\n", | |
199 | "<!-- Title: %3 Pages: 1 -->\n", | |
196 | 200 | "<svg width=\"62pt\" height=\"44pt\"\n", |
197 | 201 | " viewBox=\"0.00 0.00 62.00 44.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", |
198 | 202 | "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 40)\">\n", |
199 | "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-40 58,-40 58,4 -4,4\"/>\n", | |
200 | "<!-- A -->\n", | |
201 | "<g id=\"node1\" class=\"node\">\n", | |
202 | "<title>A</title>\n", | |
203 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n", | |
204 | "<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">\\</text>\n", | |
205 | "</g>\n", | |
206 | "</g>\n", | |
207 | "</svg>\n" | |
208 | ], | |
209 | "text/plain": [ | |
210 | "<graphviz.graphs.Digraph at 0x28003e87bb0>" | |
203 | "<title>%3</title>\n", | |
204 | "<polygon fill=\"#ffffff\" stroke=\"transparent\" points=\"-4,4 -4,-40 58,-40 58,4 -4,4\"/>\n", | |
205 | "<!-- A -->\n", | |
206 | "<g id=\"node1\" class=\"node\">\n", | |
207 | "<title>A</title>\n", | |
208 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"27\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n", | |
209 | "<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">\\</text>\n", | |
210 | "</g>\n", | |
211 | "</g>\n", | |
212 | "</svg>\n" | |
213 | ], | |
214 | "text/plain": [ | |
215 | "<graphviz.graphs.Digraph at 0x7f1e5c1e2d50>" | |
211 | 216 | ] |
212 | 217 | }, |
213 | 218 | "execution_count": 6, |
240 | 245 | "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n", |
241 | 246 | "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n", |
242 | 247 | " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n", |
243 | "<!-- Generated by graphviz version 2.49.3 (20211023.0002)\n", | |
244 | " -->\n", | |
245 | "<!-- Pages: 1 -->\n", | |
248 | "<!-- Generated by graphviz version 2.40.1 (20161225.0304)\n", | |
249 | " -->\n", | |
250 | "<!-- Title: %3 Pages: 1 -->\n", | |
246 | 251 | "<svg width=\"62pt\" height=\"44pt\"\n", |
247 | 252 | " viewBox=\"0.00 0.00 62.00 44.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", |
248 | 253 | "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 40)\">\n", |
249 | "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-40 58,-40 58,4 -4,4\"/>\n", | |
250 | "<!-- A -->\n", | |
251 | "<g id=\"node1\" class=\"node\">\n", | |
252 | "<title>A</title>\n", | |
253 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n", | |
254 | "<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">\\"</text>\n", | |
255 | "</g>\n", | |
256 | "</g>\n", | |
257 | "</svg>\n" | |
258 | ], | |
259 | "text/plain": [ | |
260 | "<graphviz.graphs.Digraph at 0x28003e86e00>" | |
254 | "<title>%3</title>\n", | |
255 | "<polygon fill=\"#ffffff\" stroke=\"transparent\" points=\"-4,4 -4,-40 58,-40 58,4 -4,4\"/>\n", | |
256 | "<!-- A -->\n", | |
257 | "<g id=\"node1\" class=\"node\">\n", | |
258 | "<title>A</title>\n", | |
259 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"27\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n", | |
260 | "<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">\\"</text>\n", | |
261 | "</g>\n", | |
262 | "</g>\n", | |
263 | "</svg>\n" | |
264 | ], | |
265 | "text/plain": [ | |
266 | "<graphviz.graphs.Digraph at 0x7f1e5c1b9ed0>" | |
261 | 267 | ] |
262 | 268 | }, |
263 | 269 | "execution_count": 7, |
297 | 303 | "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n", |
298 | 304 | "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n", |
299 | 305 | " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n", |
300 | "<!-- Generated by graphviz version 2.49.3 (20211023.0002)\n", | |
301 | " -->\n", | |
302 | "<!-- Pages: 1 -->\n", | |
303 | "<svg width=\"87pt\" height=\"44pt\"\n", | |
304 | " viewBox=\"0.00 0.00 87.29 44.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", | |
305 | "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 40)\">\n", | |
306 | "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-40 83.29,-40 83.29,4 -4,4\"/>\n", | |
307 | "<!-- A -->\n", | |
308 | "<g id=\"node1\" class=\"node\">\n", | |
309 | "<title>A</title>\n", | |
310 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"39.65\" cy=\"-18\" rx=\"39.79\" ry=\"18\"/>\n", | |
311 | "<text text-anchor=\"middle\" x=\"39.65\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">node: A</text>\n", | |
312 | "</g>\n", | |
313 | "</g>\n", | |
314 | "</svg>\n" | |
315 | ], | |
316 | "text/plain": [ | |
317 | "<graphviz.graphs.Digraph at 0x28003e87d30>" | |
306 | "<!-- Generated by graphviz version 2.40.1 (20161225.0304)\n", | |
307 | " -->\n", | |
308 | "<!-- Title: %3 Pages: 1 -->\n", | |
309 | "<svg width=\"100pt\" height=\"44pt\"\n", | |
310 | " viewBox=\"0.00 0.00 100.29 44.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", | |
311 | "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 40)\">\n", | |
312 | "<title>%3</title>\n", | |
313 | "<polygon fill=\"#ffffff\" stroke=\"transparent\" points=\"-4,4 -4,-40 96.2918,-40 96.2918,4 -4,4\"/>\n", | |
314 | "<!-- A -->\n", | |
315 | "<g id=\"node1\" class=\"node\">\n", | |
316 | "<title>A</title>\n", | |
317 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"46.1459\" cy=\"-18\" rx=\"46.2923\" ry=\"18\"/>\n", | |
318 | "<text text-anchor=\"middle\" x=\"46.1459\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">node: A</text>\n", | |
319 | "</g>\n", | |
320 | "</g>\n", | |
321 | "</svg>\n" | |
322 | ], | |
323 | "text/plain": [ | |
324 | "<graphviz.graphs.Digraph at 0x7f1e5c267f50>" | |
318 | 325 | ] |
319 | 326 | }, |
320 | 327 | "execution_count": 8, |
347 | 354 | "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n", |
348 | 355 | "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n", |
349 | 356 | " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n", |
350 | "<!-- Generated by graphviz version 2.49.3 (20211023.0002)\n", | |
357 | "<!-- Generated by graphviz version 2.40.1 (20161225.0304)\n", | |
351 | 358 | " -->\n", |
352 | 359 | "<!-- Title: spam Pages: 1 -->\n", |
353 | "<svg width=\"118pt\" height=\"44pt\"\n", | |
354 | " viewBox=\"0.00 0.00 118.49 44.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", | |
360 | "<svg width=\"146pt\" height=\"44pt\"\n", | |
361 | " viewBox=\"0.00 0.00 145.79 44.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", | |
355 | 362 | "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 40)\">\n", |
356 | 363 | "<title>spam</title>\n", |
357 | "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-40 114.49,-40 114.49,4 -4,4\"/>\n", | |
358 | "<!-- A -->\n", | |
359 | "<g id=\"node1\" class=\"node\">\n", | |
360 | "<title>A</title>\n", | |
361 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"55.25\" cy=\"-18\" rx=\"55.49\" ry=\"18\"/>\n", | |
362 | "<text text-anchor=\"middle\" x=\"55.25\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">graph: spam</text>\n", | |
363 | "</g>\n", | |
364 | "</g>\n", | |
365 | "</svg>\n" | |
366 | ], | |
367 | "text/plain": [ | |
368 | "<graphviz.graphs.Digraph at 0x28003ed0340>" | |
364 | "<polygon fill=\"#ffffff\" stroke=\"transparent\" points=\"-4,4 -4,-40 141.7878,-40 141.7878,4 -4,4\"/>\n", | |
365 | "<!-- A -->\n", | |
366 | "<g id=\"node1\" class=\"node\">\n", | |
367 | "<title>A</title>\n", | |
368 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"68.8939\" cy=\"-18\" rx=\"68.7879\" ry=\"18\"/>\n", | |
369 | "<text text-anchor=\"middle\" x=\"68.8939\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">graph: spam</text>\n", | |
370 | "</g>\n", | |
371 | "</g>\n", | |
372 | "</svg>\n" | |
373 | ], | |
374 | "text/plain": [ | |
375 | "<graphviz.graphs.Digraph at 0x7f1e5c1e2890>" | |
369 | 376 | ] |
370 | 377 | }, |
371 | 378 | "execution_count": 9, |
398 | 405 | "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n", |
399 | 406 | "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n", |
400 | 407 | " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n", |
401 | "<!-- Generated by graphviz version 2.49.3 (20211023.0002)\n", | |
402 | " -->\n", | |
403 | "<!-- Pages: 1 -->\n", | |
404 | "<svg width=\"69pt\" height=\"44pt\"\n", | |
405 | " viewBox=\"0.00 0.00 69.09 44.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", | |
406 | "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 40)\">\n", | |
407 | "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-40 65.09,-40 65.09,4 -4,4\"/>\n", | |
408 | "<!-- Generated by graphviz version 2.40.1 (20161225.0304)\n", | |
409 | " -->\n", | |
410 | "<!-- Title: %3 Pages: 1 -->\n", | |
411 | "<svg width=\"79pt\" height=\"44pt\"\n", | |
412 | " viewBox=\"0.00 0.00 79.49 44.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", | |
413 | "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 40)\">\n", | |
414 | "<title>%3</title>\n", | |
415 | "<polygon fill=\"#ffffff\" stroke=\"transparent\" points=\"-4,4 -4,-40 75.4937,-40 75.4937,4 -4,4\"/>\n", | |
408 | 416 | "<!-- A -->\n", |
409 | 417 | "<g id=\"node1\" class=\"node\">\n", |
410 | 418 | "<title>A</title>\n", |
411 | 419 | "<g id=\"a_node1\"><a xlink:href=\"https://example.org/spam\" xlink:title=\"spam\">\n", |
412 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"30.55\" cy=\"-18\" rx=\"30.59\" ry=\"18\"/>\n", | |
413 | "<text text-anchor=\"middle\" x=\"30.55\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">spam</text>\n", | |
420 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"35.7468\" cy=\"-18\" rx=\"35.9954\" ry=\"18\"/>\n", | |
421 | "<text text-anchor=\"middle\" x=\"35.7468\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">spam</text>\n", | |
414 | 422 | "</a>\n", |
415 | 423 | "</g>\n", |
416 | 424 | "</g>\n", |
418 | 426 | "</svg>\n" |
419 | 427 | ], |
420 | 428 | "text/plain": [ |
421 | "<graphviz.graphs.Digraph at 0x28003e874c0>" | |
429 | "<graphviz.graphs.Digraph at 0x7f1e5c16c310>" | |
422 | 430 | ] |
423 | 431 | }, |
424 | 432 | "execution_count": 10, |
451 | 459 | "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n", |
452 | 460 | "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n", |
453 | 461 | " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n", |
454 | "<!-- Generated by graphviz version 2.49.3 (20211023.0002)\n", | |
455 | " -->\n", | |
456 | "<!-- Pages: 1 -->\n", | |
457 | "<svg width=\"99pt\" height=\"83pt\"\n", | |
458 | " viewBox=\"0.00 0.00 98.51 82.95\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", | |
459 | "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 78.95)\">\n", | |
460 | "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-78.95 94.51,-78.95 94.51,4 -4,4\"/>\n", | |
461 | "<!-- A -->\n", | |
462 | "<g id=\"node1\" class=\"node\">\n", | |
463 | "<title>A</title>\n", | |
464 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"45.25\" cy=\"-37.48\" rx=\"45.01\" ry=\"37.45\"/>\n", | |
465 | "<text text-anchor=\"middle\" x=\"45.25\" y=\"-48.78\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">centered</text>\n", | |
466 | "<text text-anchor=\"start\" x=\"21.25\" y=\"-33.78\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">left</text>\n", | |
467 | "<text text-anchor=\"end\" x=\"69.25\" y=\"-18.78\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">right</text>\n", | |
468 | "</g>\n", | |
469 | "</g>\n", | |
470 | "</svg>\n" | |
471 | ], | |
472 | "text/plain": [ | |
473 | "<graphviz.graphs.Digraph at 0x28003e1bfa0>" | |
462 | "<!-- Generated by graphviz version 2.40.1 (20161225.0304)\n", | |
463 | " -->\n", | |
464 | "<!-- Title: %3 Pages: 1 -->\n", | |
465 | "<svg width=\"121pt\" height=\"83pt\"\n", | |
466 | " viewBox=\"0.00 0.00 121.14 82.95\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", | |
467 | "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 78.9533)\">\n", | |
468 | "<title>%3</title>\n", | |
469 | "<polygon fill=\"#ffffff\" stroke=\"transparent\" points=\"-4,4 -4,-78.9533 117.1371,-78.9533 117.1371,4 -4,4\"/>\n", | |
470 | "<!-- A -->\n", | |
471 | "<g id=\"node1\" class=\"node\">\n", | |
472 | "<title>A</title>\n", | |
473 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"56.5685\" cy=\"-37.4767\" rx=\"56.6372\" ry=\"37.4533\"/>\n", | |
474 | "<text text-anchor=\"middle\" x=\"56.5685\" y=\"-48.7767\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">centered</text>\n", | |
475 | "<text text-anchor=\"start\" x=\"24.5685\" y=\"-33.7767\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">left</text>\n", | |
476 | "<text text-anchor=\"end\" x=\"88.5685\" y=\"-18.7767\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">right</text>\n", | |
477 | "</g>\n", | |
478 | "</g>\n", | |
479 | "</svg>\n" | |
480 | ], | |
481 | "text/plain": [ | |
482 | "<graphviz.graphs.Digraph at 0x7f1e5c16cb10>" | |
474 | 483 | ] |
475 | 484 | }, |
476 | 485 | "execution_count": 11, |
499 | 508 | "name": "python", |
500 | 509 | "nbconvert_exporter": "python", |
501 | 510 | "pygments_lexer": "ipython3", |
502 | "version": "3.10.0" | |
511 | "version": "3.7.12" | |
503 | 512 | } |
504 | 513 | }, |
505 | 514 | "nbformat": 4, |
506 | "nbformat_minor": 2 | |
515 | "nbformat_minor": 4 | |
507 | 516 | } |
8 | 8 | { |
9 | 9 | "data": { |
10 | 10 | "text/plain": [ |
11 | "('0.19', (2, 49, 3))" | |
11 | "('0.20.dev0', (2, 40, 1))" | |
12 | 12 | ] |
13 | 13 | }, |
14 | 14 | "execution_count": 1, |
53 | 53 | "outputs": [ |
54 | 54 | { |
55 | 55 | "data": { |
56 | "image/png": "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\n", | |
56 | "image/png": "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\n", | |
57 | 57 | "text/plain": [ |
58 | "<graphviz.graphs.Digraph at 0x13e013ef460>" | |
58 | "<graphviz.graphs.Digraph at 0x7fb0306b1210>" | |
59 | 59 | ] |
60 | 60 | }, |
61 | 61 | "execution_count": 3, |
88 | 88 | "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n", |
89 | 89 | "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n", |
90 | 90 | " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n", |
91 | "<!-- Generated by graphviz version 2.49.3 (20211023.0002)\n", | |
91 | "<!-- Generated by graphviz version 2.40.1 (20161225.0304)\n", | |
92 | 92 | " -->\n", |
93 | "<!-- Pages: 1 -->\n", | |
94 | "<svg width=\"390pt\" height=\"116pt\"\n", | |
95 | " viewBox=\"0.00 0.00 389.98 116.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", | |
93 | "<!-- Title: %3 Pages: 1 -->\n", | |
94 | "<svg width=\"488pt\" height=\"116pt\"\n", | |
95 | " viewBox=\"0.00 0.00 488.38 116.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", | |
96 | 96 | "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 112)\">\n", |
97 | "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-112 385.98,-112 385.98,4 -4,4\"/>\n", | |
97 | "<title>%3</title>\n", | |
98 | "<polygon fill=\"#ffffff\" stroke=\"transparent\" points=\"-4,4 -4,-112 484.3795,-112 484.3795,4 -4,4\"/>\n", | |
98 | 99 | "<!-- A -->\n", |
99 | 100 | "<g id=\"node1\" class=\"node\">\n", |
100 | 101 | "<title>A</title>\n", |
101 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"190.99\" cy=\"-90\" rx=\"53.89\" ry=\"18\"/>\n", | |
102 | "<text text-anchor=\"middle\" x=\"190.99\" y=\"-86.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">King Arthur</text>\n", | |
102 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"239.0398\" cy=\"-90\" rx=\"66.0889\" ry=\"18\"/>\n", | |
103 | "<text text-anchor=\"middle\" x=\"239.0398\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">King Arthur</text>\n", | |
103 | 104 | "</g>\n", |
104 | 105 | "<!-- B -->\n", |
105 | 106 | "<g id=\"node2\" class=\"node\">\n", |
106 | 107 | "<title>B</title>\n", |
107 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"90.99\" cy=\"-18\" rx=\"90.98\" ry=\"18\"/>\n", | |
108 | "<text text-anchor=\"middle\" x=\"90.99\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">Sir Bedevere the Wise</text>\n", | |
108 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"115.0398\" cy=\"-18\" rx=\"115.0796\" ry=\"18\"/>\n", | |
109 | "<text text-anchor=\"middle\" x=\"115.0398\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">Sir Bedevere the Wise</text>\n", | |
109 | 110 | "</g>\n", |
110 | 111 | "<!-- A->B -->\n", |
111 | 112 | "<g id=\"edge1\" class=\"edge\">\n", |
112 | 113 | "<title>A->B</title>\n", |
113 | "<path fill=\"none\" stroke=\"black\" d=\"M168.8,-73.46C155.33,-64.04 137.92,-51.85 122.98,-41.39\"/>\n", | |
114 | "<polygon fill=\"black\" stroke=\"black\" points=\"124.72,-38.33 114.52,-35.47 120.7,-44.07 124.72,-38.33\"/>\n", | |
114 | "<path fill=\"none\" stroke=\"#000000\" d=\"M210.9023,-73.6621C194.0767,-63.8924 172.4517,-51.3359 154.0004,-40.6223\"/>\n", | |
115 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"155.6378,-37.5258 145.2324,-35.5312 152.1228,-43.5793 155.6378,-37.5258\"/>\n", | |
115 | 116 | "</g>\n", |
116 | 117 | "<!-- L -->\n", |
117 | 118 | "<g id=\"node3\" class=\"node\">\n", |
118 | 119 | "<title>L</title>\n", |
119 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"290.99\" cy=\"-18\" rx=\"90.98\" ry=\"18\"/>\n", | |
120 | "<text text-anchor=\"middle\" x=\"290.99\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">Sir Lancelot the Brave</text>\n", | |
120 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"364.0398\" cy=\"-18\" rx=\"116.1796\" ry=\"18\"/>\n", | |
121 | "<text text-anchor=\"middle\" x=\"364.0398\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">Sir Lancelot the Brave</text>\n", | |
121 | 122 | "</g>\n", |
122 | 123 | "<!-- A->L -->\n", |
123 | 124 | "<g id=\"edge2\" class=\"edge\">\n", |
124 | 125 | "<title>A->L</title>\n", |
125 | "<path fill=\"none\" stroke=\"black\" d=\"M213.19,-73.46C226.65,-64.04 244.07,-51.85 259.01,-41.39\"/>\n", | |
126 | "<polygon fill=\"black\" stroke=\"black\" points=\"261.28,-44.07 267.47,-35.47 257.27,-38.33 261.28,-44.07\"/>\n", | |
126 | "<path fill=\"none\" stroke=\"#000000\" d=\"M267.4042,-73.6621C284.3654,-63.8924 306.1649,-51.3359 324.765,-40.6223\"/>\n", | |
127 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"326.6853,-43.5553 333.6037,-35.5312 323.1914,-37.4896 326.6853,-43.5553\"/>\n", | |
127 | 128 | "</g>\n", |
128 | 129 | "<!-- B->L -->\n", |
129 | 130 | "<g id=\"edge3\" class=\"edge\">\n", |
130 | 131 | "<title>B->L</title>\n", |
131 | "<path fill=\"none\" stroke=\"black\" d=\"M182.01,-18C184.62,-18 187.22,-18 189.83,-18\"/>\n", | |
132 | "<polygon fill=\"black\" stroke=\"black\" points=\"189.89,-21.5 199.89,-18 189.89,-14.5 189.89,-21.5\"/>\n", | |
132 | "<path fill=\"none\" stroke=\"#000000\" d=\"M230.2996,-18C232.6341,-18 234.9687,-18 237.3033,-18\"/>\n", | |
133 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"237.5395,-21.5001 247.5395,-18 237.5395,-14.5001 237.5395,-21.5001\"/>\n", | |
133 | 134 | "</g>\n", |
134 | 135 | "</g>\n", |
135 | 136 | "</svg>\n" |
162 | 163 | "name": "python", |
163 | 164 | "nbconvert_exporter": "python", |
164 | 165 | "pygments_lexer": "ipython3", |
165 | "version": "3.10.0" | |
166 | "version": "3.7.12" | |
166 | 167 | } |
167 | 168 | }, |
168 | 169 | "nbformat": 4, |
8 | 8 | "name": "stderr", |
9 | 9 | "output_type": "stream", |
10 | 10 | "text": [ |
11 | "[DEBUG@graphviz.backend.execute] run [WindowsPath('dot'), '-V']\n" | |
11 | "[DEBUG@graphviz.backend.execute] run [PosixPath('dot'), '-V']\n" | |
12 | 12 | ] |
13 | 13 | }, |
14 | 14 | { |
15 | 15 | "data": { |
16 | 16 | "text/plain": [ |
17 | "('0.19', (2, 49, 3))" | |
17 | "('0.20.dev0', (2, 40, 1))" | |
18 | 18 | ] |
19 | 19 | }, |
20 | 20 | "execution_count": 1, |
43 | 43 | "name": "stderr", |
44 | 44 | "output_type": "stream", |
45 | 45 | "text": [ |
46 | "[DEBUG@graphviz.backend.execute] run [WindowsPath('dot'), '-Kdot', '-Tsvg']\n" | |
46 | "[DEBUG@graphviz.backend.execute] run [PosixPath('dot'), '-Kdot', '-Tsvg']\n" | |
47 | 47 | ] |
48 | 48 | }, |
49 | 49 | { |
52 | 52 | "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n", |
53 | 53 | "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n", |
54 | 54 | " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n", |
55 | "<!-- Generated by graphviz version 2.49.3 (20211023.0002)\n", | |
55 | "<!-- Generated by graphviz version 2.40.1 (20161225.0304)\n", | |
56 | 56 | " -->\n", |
57 | "<!-- Pages: 1 -->\n", | |
58 | "<svg width=\"390pt\" height=\"116pt\"\n", | |
59 | " viewBox=\"0.00 0.00 389.98 116.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", | |
57 | "<!-- Title: %3 Pages: 1 -->\n", | |
58 | "<svg width=\"488pt\" height=\"116pt\"\n", | |
59 | " viewBox=\"0.00 0.00 488.38 116.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", | |
60 | 60 | "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 112)\">\n", |
61 | "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-112 385.98,-112 385.98,4 -4,4\"/>\n", | |
61 | "<title>%3</title>\n", | |
62 | "<polygon fill=\"#ffffff\" stroke=\"transparent\" points=\"-4,4 -4,-112 484.3795,-112 484.3795,4 -4,4\"/>\n", | |
62 | 63 | "<!-- A -->\n", |
63 | 64 | "<g id=\"node1\" class=\"node\">\n", |
64 | 65 | "<title>A</title>\n", |
65 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"190.99\" cy=\"-90\" rx=\"53.89\" ry=\"18\"/>\n", | |
66 | "<text text-anchor=\"middle\" x=\"190.99\" y=\"-86.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">King Arthur</text>\n", | |
66 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"239.0398\" cy=\"-90\" rx=\"66.0889\" ry=\"18\"/>\n", | |
67 | "<text text-anchor=\"middle\" x=\"239.0398\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">King Arthur</text>\n", | |
67 | 68 | "</g>\n", |
68 | 69 | "<!-- B -->\n", |
69 | 70 | "<g id=\"node2\" class=\"node\">\n", |
70 | 71 | "<title>B</title>\n", |
71 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"90.99\" cy=\"-18\" rx=\"90.98\" ry=\"18\"/>\n", | |
72 | "<text text-anchor=\"middle\" x=\"90.99\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">Sir Bedevere the Wise</text>\n", | |
72 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"115.0398\" cy=\"-18\" rx=\"115.0796\" ry=\"18\"/>\n", | |
73 | "<text text-anchor=\"middle\" x=\"115.0398\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">Sir Bedevere the Wise</text>\n", | |
73 | 74 | "</g>\n", |
74 | 75 | "<!-- A->B -->\n", |
75 | 76 | "<g id=\"edge1\" class=\"edge\">\n", |
76 | 77 | "<title>A->B</title>\n", |
77 | "<path fill=\"none\" stroke=\"black\" d=\"M168.8,-73.46C155.33,-64.04 137.92,-51.85 122.98,-41.39\"/>\n", | |
78 | "<polygon fill=\"black\" stroke=\"black\" points=\"124.72,-38.33 114.52,-35.47 120.7,-44.07 124.72,-38.33\"/>\n", | |
78 | "<path fill=\"none\" stroke=\"#000000\" d=\"M210.9023,-73.6621C194.0767,-63.8924 172.4517,-51.3359 154.0004,-40.6223\"/>\n", | |
79 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"155.6378,-37.5258 145.2324,-35.5312 152.1228,-43.5793 155.6378,-37.5258\"/>\n", | |
79 | 80 | "</g>\n", |
80 | 81 | "<!-- L -->\n", |
81 | 82 | "<g id=\"node3\" class=\"node\">\n", |
82 | 83 | "<title>L</title>\n", |
83 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"290.99\" cy=\"-18\" rx=\"90.98\" ry=\"18\"/>\n", | |
84 | "<text text-anchor=\"middle\" x=\"290.99\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">Sir Lancelot the Brave</text>\n", | |
84 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"364.0398\" cy=\"-18\" rx=\"116.1796\" ry=\"18\"/>\n", | |
85 | "<text text-anchor=\"middle\" x=\"364.0398\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">Sir Lancelot the Brave</text>\n", | |
85 | 86 | "</g>\n", |
86 | 87 | "<!-- A->L -->\n", |
87 | 88 | "<g id=\"edge2\" class=\"edge\">\n", |
88 | 89 | "<title>A->L</title>\n", |
89 | "<path fill=\"none\" stroke=\"black\" d=\"M213.19,-73.46C226.65,-64.04 244.07,-51.85 259.01,-41.39\"/>\n", | |
90 | "<polygon fill=\"black\" stroke=\"black\" points=\"261.28,-44.07 267.47,-35.47 257.27,-38.33 261.28,-44.07\"/>\n", | |
90 | "<path fill=\"none\" stroke=\"#000000\" d=\"M267.4042,-73.6621C284.3654,-63.8924 306.1649,-51.3359 324.765,-40.6223\"/>\n", | |
91 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"326.6853,-43.5553 333.6037,-35.5312 323.1914,-37.4896 326.6853,-43.5553\"/>\n", | |
91 | 92 | "</g>\n", |
92 | 93 | "<!-- B->L -->\n", |
93 | 94 | "<g id=\"edge3\" class=\"edge\">\n", |
94 | 95 | "<title>B->L</title>\n", |
95 | "<path fill=\"none\" stroke=\"black\" d=\"M182.01,-18C184.62,-18 187.22,-18 189.83,-18\"/>\n", | |
96 | "<polygon fill=\"black\" stroke=\"black\" points=\"189.89,-21.5 199.89,-18 189.89,-14.5 189.89,-21.5\"/>\n", | |
96 | "<path fill=\"none\" stroke=\"#000000\" d=\"M230.2996,-18C232.6341,-18 234.9687,-18 237.3033,-18\"/>\n", | |
97 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"237.5395,-21.5001 247.5395,-18 237.5395,-14.5001 237.5395,-21.5001\"/>\n", | |
97 | 98 | "</g>\n", |
98 | 99 | "</g>\n", |
99 | 100 | "</svg>\n" |
100 | 101 | ], |
101 | 102 | "text/plain": [ |
102 | "<graphviz.graphs.Digraph at 0x203f26fb670>" | |
103 | "<graphviz.graphs.Digraph at 0x7fe7ac3fc910>" | |
103 | 104 | ] |
104 | 105 | }, |
105 | 106 | "execution_count": 2, |
129 | 130 | "name": "stderr", |
130 | 131 | "output_type": "stream", |
131 | 132 | "text": [ |
132 | "[DEBUG@graphviz.backend.execute] run [WindowsPath('dot'), '-Kdot', '-Tsvg']\n" | |
133 | "[DEBUG@graphviz.backend.execute] run [PosixPath('dot'), '-Kdot', '-Tsvg']\n" | |
133 | 134 | ] |
134 | 135 | }, |
135 | 136 | { |
138 | 139 | "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n", |
139 | 140 | "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n", |
140 | 141 | " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n", |
141 | "<!-- Generated by graphviz version 2.49.3 (20211023.0002)\n", | |
142 | "<!-- Generated by graphviz version 2.40.1 (20161225.0304)\n", | |
142 | 143 | " -->\n", |
143 | 144 | "<!-- Title: the holy hand grenade Pages: 1 -->\n", |
144 | 145 | "<svg width=\"332pt\" height=\"44pt\"\n", |
145 | 146 | " viewBox=\"0.00 0.00 332.00 44.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", |
146 | 147 | "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 40)\">\n", |
147 | 148 | "<title>the holy hand grenade</title>\n", |
148 | "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-40 328,-40 328,4 -4,4\"/>\n", | |
149 | "<polygon fill=\"#ffffff\" stroke=\"transparent\" points=\"-4,4 -4,-40 328,-40 328,4 -4,4\"/>\n", | |
149 | 150 | "<!-- 1 -->\n", |
150 | 151 | "<g id=\"node1\" class=\"node\">\n", |
151 | 152 | "<title>1</title>\n", |
152 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n", | |
153 | "<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">1</text>\n", | |
153 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"27\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n", | |
154 | "<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">1</text>\n", | |
154 | 155 | "</g>\n", |
155 | 156 | "<!-- 2 -->\n", |
156 | 157 | "<g id=\"node2\" class=\"node\">\n", |
157 | 158 | "<title>2</title>\n", |
158 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"117\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n", | |
159 | "<text text-anchor=\"middle\" x=\"117\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">2</text>\n", | |
159 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"117\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n", | |
160 | "<text text-anchor=\"middle\" x=\"117\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">2</text>\n", | |
160 | 161 | "</g>\n", |
161 | 162 | "<!-- 1->2 -->\n", |
162 | 163 | "<g id=\"edge1\" class=\"edge\">\n", |
163 | 164 | "<title>1->2</title>\n", |
164 | "<path fill=\"none\" stroke=\"black\" d=\"M54.4,-18C62.39,-18 71.31,-18 79.82,-18\"/>\n", | |
165 | "<polygon fill=\"black\" stroke=\"black\" points=\"79.92,-21.5 89.92,-18 79.92,-14.5 79.92,-21.5\"/>\n", | |
165 | "<path fill=\"none\" stroke=\"#000000\" d=\"M54.003,-18C62.0277,-18 70.9665,-18 79.5309,-18\"/>\n", | |
166 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"79.7051,-21.5001 89.705,-18 79.705,-14.5001 79.7051,-21.5001\"/>\n", | |
166 | 167 | "</g>\n", |
167 | 168 | "<!-- 3 -->\n", |
168 | 169 | "<g id=\"node3\" class=\"node\">\n", |
169 | 170 | "<title>3</title>\n", |
170 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"207\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n", | |
171 | "<text text-anchor=\"middle\" x=\"207\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">3</text>\n", | |
171 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"207\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n", | |
172 | "<text text-anchor=\"middle\" x=\"207\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">3</text>\n", | |
172 | 173 | "</g>\n", |
173 | 174 | "<!-- 2->3 -->\n", |
174 | 175 | "<g id=\"edge2\" class=\"edge\">\n", |
175 | 176 | "<title>2->3</title>\n", |
176 | "<path fill=\"none\" stroke=\"black\" d=\"M144.4,-18C152.39,-18 161.31,-18 169.82,-18\"/>\n", | |
177 | "<polygon fill=\"black\" stroke=\"black\" points=\"169.92,-21.5 179.92,-18 169.92,-14.5 169.92,-21.5\"/>\n", | |
177 | "<path fill=\"none\" stroke=\"#000000\" d=\"M144.003,-18C152.0277,-18 160.9665,-18 169.5309,-18\"/>\n", | |
178 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"169.7051,-21.5001 179.705,-18 169.705,-14.5001 169.7051,-21.5001\"/>\n", | |
178 | 179 | "</g>\n", |
179 | 180 | "<!-- lob -->\n", |
180 | 181 | "<g id=\"node4\" class=\"node\">\n", |
181 | 182 | "<title>lob</title>\n", |
182 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"297\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n", | |
183 | "<text text-anchor=\"middle\" x=\"297\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">lob</text>\n", | |
183 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"297\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n", | |
184 | "<text text-anchor=\"middle\" x=\"297\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">lob</text>\n", | |
184 | 185 | "</g>\n", |
185 | 186 | "<!-- 3->lob -->\n", |
186 | 187 | "<g id=\"edge3\" class=\"edge\">\n", |
187 | 188 | "<title>3->lob</title>\n", |
188 | "<path fill=\"none\" stroke=\"black\" d=\"M234.4,-18C242.39,-18 251.31,-18 259.82,-18\"/>\n", | |
189 | "<polygon fill=\"black\" stroke=\"black\" points=\"259.92,-21.5 269.92,-18 259.92,-14.5 259.92,-21.5\"/>\n", | |
189 | "<path fill=\"none\" stroke=\"#000000\" d=\"M234.003,-18C242.0277,-18 250.9665,-18 259.5309,-18\"/>\n", | |
190 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"259.7051,-21.5001 269.705,-18 259.705,-14.5001 259.7051,-21.5001\"/>\n", | |
190 | 191 | "</g>\n", |
191 | 192 | "</g>\n", |
192 | 193 | "</svg>\n" |
193 | 194 | ], |
194 | 195 | "text/plain": [ |
195 | "<graphviz.sources.Source at 0x203f26fa8c0>" | |
196 | "<graphviz.sources.Source at 0x7fe7ac3fc390>" | |
196 | 197 | ] |
197 | 198 | }, |
198 | 199 | "execution_count": 3, |
214 | 215 | "name": "stderr", |
215 | 216 | "output_type": "stream", |
216 | 217 | "text": [ |
217 | "[DEBUG@graphviz.backend.execute] run [WindowsPath('dot'), '-Kdot', '-Tsvg']\n" | |
218 | "[DEBUG@graphviz.backend.execute] run [PosixPath('dot'), '-Kdot', '-Tsvg']\n" | |
218 | 219 | ] |
219 | 220 | }, |
220 | 221 | { |
223 | 224 | "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n", |
224 | 225 | "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n", |
225 | 226 | " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n", |
226 | "<!-- Generated by graphviz version 2.49.3 (20211023.0002)\n", | |
227 | "<!-- Generated by graphviz version 2.40.1 (20161225.0304)\n", | |
227 | 228 | " -->\n", |
228 | 229 | "<!-- Title: finite_state_machine Pages: 1 -->\n", |
229 | "<svg width=\"576pt\" height=\"258pt\"\n", | |
230 | " viewBox=\"0.00 0.00 576.00 258.45\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", | |
231 | "<g id=\"graph0\" class=\"graph\" transform=\"scale(0.77 0.77) rotate(0) translate(4 331.69)\">\n", | |
230 | "<svg width=\"576pt\" height=\"248pt\"\n", | |
231 | " viewBox=\"0.00 0.00 576.00 248.40\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", | |
232 | "<g id=\"graph0\" class=\"graph\" transform=\"scale(.7099 .7099) rotate(0) translate(4 345.8939)\">\n", | |
232 | 233 | "<title>finite_state_machine</title>\n", |
233 | "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-331.69 744.17,-331.69 744.17,4 -4,4\"/>\n", | |
234 | "<polygon fill=\"#ffffff\" stroke=\"transparent\" points=\"-4,4 -4,-345.8939 807.3633,-345.8939 807.3633,4 -4,4\"/>\n", | |
234 | 235 | "<!-- LR_0 -->\n", |
235 | 236 | "<g id=\"node1\" class=\"node\">\n", |
236 | 237 | "<title>LR_0</title>\n", |
237 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"35.85\" cy=\"-83.85\" rx=\"31.71\" ry=\"31.71\"/>\n", | |
238 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"35.85\" cy=\"-83.85\" rx=\"35.69\" ry=\"35.69\"/>\n", | |
239 | "<text text-anchor=\"middle\" x=\"35.85\" y=\"-80.15\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">LR_0</text>\n", | |
238 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"38.4469\" cy=\"-88.4469\" rx=\"34.3995\" ry=\"34.3995\"/>\n", | |
239 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"38.4469\" cy=\"-88.4469\" rx=\"38.394\" ry=\"38.394\"/>\n", | |
240 | "<text text-anchor=\"middle\" x=\"38.4469\" y=\"-84.7469\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">LR_0</text>\n", | |
240 | 241 | "</g>\n", |
241 | 242 | "<!-- LR_2 -->\n", |
242 | 243 | "<g id=\"node5\" class=\"node\">\n", |
243 | 244 | "<title>LR_2</title>\n", |
244 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"174.54\" cy=\"-151.85\" rx=\"31.7\" ry=\"31.7\"/>\n", | |
245 | "<text text-anchor=\"middle\" x=\"174.54\" y=\"-148.15\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">LR_2</text>\n", | |
245 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"188.3408\" cy=\"-159.4469\" rx=\"34.394\" ry=\"34.394\"/>\n", | |
246 | "<text text-anchor=\"middle\" x=\"188.3408\" y=\"-155.7469\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">LR_2</text>\n", | |
246 | 247 | "</g>\n", |
247 | 248 | "<!-- LR_0->LR_2 -->\n", |
248 | 249 | "<g id=\"edge1\" class=\"edge\">\n", |
249 | 250 | "<title>LR_0->LR_2</title>\n", |
250 | "<path fill=\"none\" stroke=\"black\" d=\"M68.21,-99.45C88.53,-109.56 115.1,-122.77 136.47,-133.4\"/>\n", | |
251 | "<polygon fill=\"black\" stroke=\"black\" points=\"135.06,-136.61 145.58,-137.94 138.18,-130.35 135.06,-136.61\"/>\n", | |
252 | "<text text-anchor=\"middle\" x=\"107.19\" y=\"-129.65\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">SS(B)</text>\n", | |
251 | "<path fill=\"none\" stroke=\"#000000\" d=\"M73.2124,-104.9142C95.4839,-115.4635 124.4765,-129.1964 147.795,-140.2417\"/>\n", | |
252 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"146.5421,-143.5209 157.0778,-144.6386 149.5387,-137.1947 146.5421,-143.5209\"/>\n", | |
253 | "<text text-anchor=\"middle\" x=\"115.3939\" y=\"-138.2469\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">SS(B)</text>\n", | |
253 | 254 | "</g>\n", |
254 | 255 | "<!-- LR_1 -->\n", |
255 | 256 | "<g id=\"node6\" class=\"node\">\n", |
256 | 257 | "<title>LR_1</title>\n", |
257 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"174.54\" cy=\"-42.85\" rx=\"31.7\" ry=\"31.7\"/>\n", | |
258 | "<text text-anchor=\"middle\" x=\"174.54\" y=\"-39.15\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">LR_1</text>\n", | |
258 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"188.3408\" cy=\"-45.4469\" rx=\"34.394\" ry=\"34.394\"/>\n", | |
259 | "<text text-anchor=\"middle\" x=\"188.3408\" y=\"-41.7469\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">LR_1</text>\n", | |
259 | 260 | "</g>\n", |
260 | 261 | "<!-- LR_0->LR_1 -->\n", |
261 | 262 | "<g id=\"edge2\" class=\"edge\">\n", |
262 | 263 | "<title>LR_0->LR_1</title>\n", |
263 | "<path fill=\"none\" stroke=\"black\" d=\"M70.29,-73.82C89.49,-68.06 113.72,-60.79 133.88,-54.74\"/>\n", | |
264 | "<polygon fill=\"black\" stroke=\"black\" points=\"135.13,-58.02 143.7,-51.8 133.12,-51.32 135.13,-58.02\"/>\n", | |
265 | "<text text-anchor=\"middle\" x=\"107.19\" y=\"-71.65\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">SS(S)</text>\n", | |
264 | "<path fill=\"none\" stroke=\"#000000\" d=\"M75.4994,-77.8177C96.6252,-71.7574 123.2023,-64.1332 145.2564,-57.8066\"/>\n", | |
265 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"146.3881,-61.1232 155.0353,-55.0013 144.4578,-54.3945 146.3881,-61.1232\"/>\n", | |
266 | "<text text-anchor=\"middle\" x=\"115.3939\" y=\"-76.2469\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">SS(S)</text>\n", | |
266 | 267 | "</g>\n", |
267 | 268 | "<!-- LR_3 -->\n", |
268 | 269 | "<g id=\"node2\" class=\"node\">\n", |
269 | 270 | "<title>LR_3</title>\n", |
270 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"323.24\" cy=\"-35.85\" rx=\"31.71\" ry=\"31.71\"/>\n", | |
271 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"323.24\" cy=\"-35.85\" rx=\"35.69\" ry=\"35.69\"/>\n", | |
272 | "<text text-anchor=\"middle\" x=\"323.24\" y=\"-32.15\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">LR_3</text>\n", | |
271 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"353.2347\" cy=\"-38.4469\" rx=\"34.3995\" ry=\"34.3995\"/>\n", | |
272 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"353.2347\" cy=\"-38.4469\" rx=\"38.394\" ry=\"38.394\"/>\n", | |
273 | "<text text-anchor=\"middle\" x=\"353.2347\" y=\"-34.7469\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">LR_3</text>\n", | |
273 | 274 | "</g>\n", |
274 | 275 | "<!-- LR_4 -->\n", |
275 | 276 | "<g id=\"node3\" class=\"node\">\n", |
276 | 277 | "<title>LR_4</title>\n", |
277 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"323.24\" cy=\"-291.85\" rx=\"31.71\" ry=\"31.71\"/>\n", | |
278 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"323.24\" cy=\"-291.85\" rx=\"35.69\" ry=\"35.69\"/>\n", | |
279 | "<text text-anchor=\"middle\" x=\"323.24\" y=\"-288.15\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">LR_4</text>\n", | |
278 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"353.2347\" cy=\"-303.4469\" rx=\"34.3995\" ry=\"34.3995\"/>\n", | |
279 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"353.2347\" cy=\"-303.4469\" rx=\"38.394\" ry=\"38.394\"/>\n", | |
280 | "<text text-anchor=\"middle\" x=\"353.2347\" y=\"-299.7469\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">LR_4</text>\n", | |
280 | 281 | "</g>\n", |
281 | 282 | "<!-- LR_8 -->\n", |
282 | 283 | "<g id=\"node4\" class=\"node\">\n", |
283 | 284 | "<title>LR_8</title>\n", |
284 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"704.32\" cy=\"-152.85\" rx=\"31.71\" ry=\"31.71\"/>\n", | |
285 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"704.32\" cy=\"-152.85\" rx=\"35.69\" ry=\"35.69\"/>\n", | |
286 | "<text text-anchor=\"middle\" x=\"704.32\" y=\"-149.15\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">LR_8</text>\n", | |
285 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"764.9164\" cy=\"-159.4469\" rx=\"34.3995\" ry=\"34.3995\"/>\n", | |
286 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"764.9164\" cy=\"-159.4469\" rx=\"38.394\" ry=\"38.394\"/>\n", | |
287 | "<text text-anchor=\"middle\" x=\"764.9164\" y=\"-155.7469\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">LR_8</text>\n", | |
287 | 288 | "</g>\n", |
288 | 289 | "<!-- LR_6 -->\n", |
289 | 290 | "<g id=\"node7\" class=\"node\">\n", |
290 | 291 | "<title>LR_6</title>\n", |
291 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"323.24\" cy=\"-172.85\" rx=\"31.7\" ry=\"31.7\"/>\n", | |
292 | "<text text-anchor=\"middle\" x=\"323.24\" y=\"-169.15\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">LR_6</text>\n", | |
292 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"353.2347\" cy=\"-179.4469\" rx=\"34.394\" ry=\"34.394\"/>\n", | |
293 | "<text text-anchor=\"middle\" x=\"353.2347\" y=\"-175.7469\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">LR_6</text>\n", | |
293 | 294 | "</g>\n", |
294 | 295 | "<!-- LR_8->LR_6 -->\n", |
295 | 296 | "<g id=\"edge13\" class=\"edge\">\n", |
296 | 297 | "<title>LR_8->LR_6</title>\n", |
297 | "<path fill=\"none\" stroke=\"black\" d=\"M668.7,-158.83C625.38,-165.98 548.87,-177.52 482.78,-181.85 454.53,-183.7 447.36,-183.19 419.08,-181.85 401.3,-181.01 381.7,-179.28 364.95,-177.56\"/>\n", | |
298 | "<polygon fill=\"black\" stroke=\"black\" points=\"365.25,-174.07 354.94,-176.5 364.51,-181.04 365.25,-174.07\"/>\n", | |
299 | "<text text-anchor=\"middle\" x=\"513.28\" y=\"-183.65\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">S(b)</text>\n", | |
298 | "<path fill=\"none\" stroke=\"#000000\" d=\"M726.9091,-165.4889C679.8084,-172.6439 597.0195,-184.1344 525.5755,-188.4469 495.0117,-190.2918 487.2723,-189.7751 456.6817,-188.4469 437.3205,-187.6063 415.9784,-185.8847 397.7331,-184.1702\"/>\n", | |
299 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"397.9588,-180.6757 387.6682,-183.1962 397.2846,-187.6432 397.9588,-180.6757\"/>\n", | |
300 | "<text text-anchor=\"middle\" x=\"558.5755\" y=\"-190.2469\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">S(b)</text>\n", | |
300 | 301 | "</g>\n", |
301 | 302 | "<!-- LR_5 -->\n", |
302 | 303 | "<g id=\"node8\" class=\"node\">\n", |
303 | 304 | "<title>LR_5</title>\n", |
304 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"450.93\" cy=\"-107.85\" rx=\"31.7\" ry=\"31.7\"/>\n", | |
305 | "<text text-anchor=\"middle\" x=\"450.93\" y=\"-104.15\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">LR_5</text>\n", | |
305 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"491.1286\" cy=\"-112.4469\" rx=\"34.394\" ry=\"34.394\"/>\n", | |
306 | "<text text-anchor=\"middle\" x=\"491.1286\" y=\"-108.7469\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">LR_5</text>\n", | |
306 | 307 | "</g>\n", |
307 | 308 | "<!-- LR_8->LR_5 -->\n", |
308 | 309 | "<g id=\"edge14\" class=\"edge\">\n", |
309 | 310 | "<title>LR_8->LR_5</title>\n", |
310 | "<path fill=\"none\" stroke=\"black\" d=\"M668.83,-147.36C628.46,-140.82 559.62,-129.34 500.78,-117.85 497.99,-117.3 495.11,-116.73 492.22,-116.15\"/>\n", | |
311 | "<polygon fill=\"black\" stroke=\"black\" points=\"492.89,-112.72 482.4,-114.17 491.51,-119.58 492.89,-112.72\"/>\n", | |
312 | "<text text-anchor=\"middle\" x=\"575.62\" y=\"-139.65\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">S(a)</text>\n", | |
311 | "<path fill=\"none\" stroke=\"#000000\" d=\"M726.6271,-153.9547C691.452,-148.7973 637.9082,-140.6643 591.5755,-132.4469 572.9886,-129.1504 552.543,-125.1485 534.9769,-121.5931\"/>\n", | |
312 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"535.5004,-118.128 525.0029,-119.5601 534.1023,-124.9869 535.5004,-118.128\"/>\n", | |
313 | "<text text-anchor=\"middle\" x=\"626.0225\" y=\"-147.2469\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">S(a)</text>\n", | |
313 | 314 | "</g>\n", |
314 | 315 | "<!-- LR_2->LR_4 -->\n", |
315 | 316 | "<g id=\"edge6\" class=\"edge\">\n", |
316 | 317 | "<title>LR_2->LR_4</title>\n", |
317 | "<path fill=\"none\" stroke=\"black\" d=\"M198.14,-173.42C222.46,-196.62 261.37,-233.76 289.13,-260.26\"/>\n", | |
318 | "<polygon fill=\"black\" stroke=\"black\" points=\"287,-263.06 296.65,-267.43 291.83,-257.99 287,-263.06\"/>\n", | |
319 | "<text text-anchor=\"middle\" x=\"246.89\" y=\"-241.65\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">S(A)</text>\n", | |
318 | "<path fill=\"none\" stroke=\"#000000\" d=\"M214.4688,-182.2642C242.0117,-206.3171 285.6174,-244.3975 316.5904,-271.4459\"/>\n", | |
319 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"314.3408,-274.1281 324.1752,-278.0696 318.9453,-268.8556 314.3408,-274.1281\"/>\n", | |
320 | "<text text-anchor=\"middle\" x=\"268.7878\" y=\"-256.2469\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">S(A)</text>\n", | |
320 | 321 | "</g>\n", |
321 | 322 | "<!-- LR_2->LR_6 -->\n", |
322 | 323 | "<g id=\"edge4\" class=\"edge\">\n", |
323 | 324 | "<title>LR_2->LR_6</title>\n", |
324 | "<path fill=\"none\" stroke=\"black\" d=\"M206.29,-156.25C228.1,-159.37 257.6,-163.59 281.38,-167\"/>\n", | |
325 | "<polygon fill=\"black\" stroke=\"black\" points=\"281.13,-170.5 291.52,-168.45 282.12,-163.57 281.13,-170.5\"/>\n", | |
326 | "<text text-anchor=\"middle\" x=\"246.89\" y=\"-167.65\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">SS(b)</text>\n", | |
325 | "<path fill=\"none\" stroke=\"#000000\" d=\"M222.908,-163.6396C247.9462,-166.6765 282.0002,-170.8069 309.0187,-174.084\"/>\n", | |
326 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"308.6472,-177.5645 318.9959,-175.2941 309.4901,-170.6154 308.6472,-177.5645\"/>\n", | |
327 | "<text text-anchor=\"middle\" x=\"268.7878\" y=\"-175.2469\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">SS(b)</text>\n", | |
327 | 328 | "</g>\n", |
328 | 329 | "<!-- LR_2->LR_5 -->\n", |
329 | 330 | "<g id=\"edge5\" class=\"edge\">\n", |
330 | 331 | "<title>LR_2->LR_5</title>\n", |
331 | "<path fill=\"none\" stroke=\"black\" d=\"M204.48,-140.61C226.77,-132.49 258.56,-122.07 287.39,-116.85 328.17,-109.46 375.56,-107.58 408.61,-107.32\"/>\n", | |
332 | "<polygon fill=\"black\" stroke=\"black\" points=\"408.82,-110.82 418.81,-107.29 408.8,-103.82 408.82,-110.82\"/>\n", | |
333 | "<text text-anchor=\"middle\" x=\"323.24\" y=\"-120.65\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">SS(a)</text>\n", | |
332 | "<path fill=\"none\" stroke=\"#000000\" d=\"M220.8332,-147.3168C246.0707,-138.4771 282.1505,-127.0986 314.7878,-121.4469 359.0488,-113.7825 410.4168,-111.9436 446.2537,-111.7723\"/>\n", | |
333 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"446.3926,-115.2723 456.3905,-111.7663 446.3885,-108.2723 446.3926,-115.2723\"/>\n", | |
334 | "<text text-anchor=\"middle\" x=\"353.2347\" y=\"-125.2469\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">SS(a)</text>\n", | |
334 | 335 | "</g>\n", |
335 | 336 | "<!-- LR_1->LR_3 -->\n", |
336 | 337 | "<g id=\"edge3\" class=\"edge\">\n", |
337 | 338 | "<title>LR_1->LR_3</title>\n", |
338 | "<path fill=\"none\" stroke=\"black\" d=\"M206.65,-41.36C227.15,-40.38 254.31,-39.09 277.16,-38\"/>\n", | |
339 | "<polygon fill=\"black\" stroke=\"black\" points=\"277.49,-41.49 287.31,-37.51 277.16,-34.49 277.49,-41.49\"/>\n", | |
340 | "<text text-anchor=\"middle\" x=\"246.89\" y=\"-44.65\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">S($end)</text>\n", | |
339 | "<path fill=\"none\" stroke=\"#000000\" d=\"M222.908,-43.9795C246.5853,-42.9744 278.325,-41.627 304.5534,-40.5135\"/>\n", | |
340 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"304.8328,-44.0049 314.6753,-40.0839 304.5358,-37.0112 304.8328,-44.0049\"/>\n", | |
341 | "<text text-anchor=\"middle\" x=\"268.7878\" y=\"-47.2469\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">S($end)</text>\n", | |
341 | 342 | "</g>\n", |
342 | 343 | "<!-- LR_6->LR_6 -->\n", |
343 | 344 | "<g id=\"edge9\" class=\"edge\">\n", |
344 | 345 | "<title>LR_6->LR_6</title>\n", |
345 | "<path fill=\"none\" stroke=\"black\" d=\"M311.26,-202.53C310.87,-213.59 314.86,-222.69 323.24,-222.69 328.86,-222.69 332.51,-218.58 334.18,-212.53\"/>\n", | |
346 | "<polygon fill=\"black\" stroke=\"black\" points=\"337.67,-212.83 335.21,-202.53 330.7,-212.12 337.67,-212.83\"/>\n", | |
347 | "<text text-anchor=\"middle\" x=\"323.24\" y=\"-226.49\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">S(b)</text>\n", | |
346 | "<path fill=\"none\" stroke=\"#000000\" d=\"M340.1169,-211.4545C339.907,-222.7382 344.2796,-231.8939 353.2347,-231.8939 359.2514,-231.8939 363.1995,-227.7609 365.079,-221.6263\"/>\n", | |
347 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"368.583,-221.8119 366.3525,-211.4545 361.6372,-220.9422 368.583,-221.8119\"/>\n", | |
348 | "<text text-anchor=\"middle\" x=\"353.2347\" y=\"-235.6939\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">S(b)</text>\n", | |
348 | 349 | "</g>\n", |
349 | 350 | "<!-- LR_6->LR_5 -->\n", |
350 | 351 | "<g id=\"edge10\" class=\"edge\">\n", |
351 | 352 | "<title>LR_6->LR_5</title>\n", |
352 | "<path fill=\"none\" stroke=\"black\" d=\"M351.82,-158.58C369.91,-149.23 393.77,-136.89 413.43,-126.72\"/>\n", | |
353 | "<polygon fill=\"black\" stroke=\"black\" points=\"415.14,-129.78 422.41,-122.08 411.92,-123.56 415.14,-129.78\"/>\n", | |
354 | "<text text-anchor=\"middle\" x=\"389.08\" y=\"-147.65\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">S(a)</text>\n", | |
353 | "<path fill=\"none\" stroke=\"#000000\" d=\"M384.525,-164.2436C404.1831,-154.6921 429.7327,-142.278 450.8909,-131.9977\"/>\n", | |
354 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"452.4973,-135.1085 459.9622,-127.5901 449.4381,-128.8123 452.4973,-135.1085\"/>\n", | |
355 | "<text text-anchor=\"middle\" x=\"424.1817\" y=\"-155.2469\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">S(a)</text>\n", | |
355 | 356 | "</g>\n", |
356 | 357 | "<!-- LR_5->LR_5 -->\n", |
357 | 358 | "<g id=\"edge8\" class=\"edge\">\n", |
358 | 359 | "<title>LR_5->LR_5</title>\n", |
359 | "<path fill=\"none\" stroke=\"black\" d=\"M439.69,-138.02C439.45,-148.86 443.2,-157.69 450.93,-157.69 456.01,-157.69 459.36,-153.89 461,-148.21\"/>\n", | |
360 | "<polygon fill=\"black\" stroke=\"black\" points=\"464.51,-148.35 462.17,-138.02 457.56,-147.56 464.51,-148.35\"/>\n", | |
361 | "<text text-anchor=\"middle\" x=\"450.93\" y=\"-161.49\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">S(a)</text>\n", | |
360 | "<path fill=\"none\" stroke=\"#000000\" d=\"M478.7566,-144.7125C478.6257,-155.8774 482.7497,-164.8939 491.1286,-164.8939 496.7582,-164.8939 500.467,-160.8237 502.2551,-154.7664\"/>\n", | |
361 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"505.7446,-155.067 503.5006,-144.7125 498.7977,-154.2064 505.7446,-155.067\"/>\n", | |
362 | "<text text-anchor=\"middle\" x=\"491.1286\" y=\"-168.6939\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">S(a)</text>\n", | |
362 | 363 | "</g>\n", |
363 | 364 | "<!-- LR_7 -->\n", |
364 | 365 | "<g id=\"node9\" class=\"node\">\n", |
365 | 366 | "<title>LR_7</title>\n", |
366 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"575.62\" cy=\"-84.85\" rx=\"31.7\" ry=\"31.7\"/>\n", | |
367 | "<text text-anchor=\"middle\" x=\"575.62\" y=\"-81.15\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">LR_7</text>\n", | |
367 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"626.0225\" cy=\"-89.4469\" rx=\"34.394\" ry=\"34.394\"/>\n", | |
368 | "<text text-anchor=\"middle\" x=\"626.0225\" y=\"-85.7469\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">LR_7</text>\n", | |
368 | 369 | "</g>\n", |
369 | 370 | "<!-- LR_5->LR_7 -->\n", |
370 | 371 | "<g id=\"edge7\" class=\"edge\">\n", |
371 | 372 | "<title>LR_5->LR_7</title>\n", |
372 | "<path fill=\"none\" stroke=\"black\" d=\"M482.57,-102.1C498.09,-99.19 517.14,-95.62 533.88,-92.49\"/>\n", | |
373 | "<polygon fill=\"black\" stroke=\"black\" points=\"534.76,-95.88 543.95,-90.6 533.47,-89 534.76,-95.88\"/>\n", | |
374 | "<text text-anchor=\"middle\" x=\"513.28\" y=\"-102.65\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">S(b)</text>\n", | |
373 | "<path fill=\"none\" stroke=\"#000000\" d=\"M525.168,-106.6431C542.4218,-103.7012 563.5777,-100.0941 582.0497,-96.9445\"/>\n", | |
374 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"582.7245,-100.38 591.994,-95.249 581.5479,-93.4796 582.7245,-100.38\"/>\n", | |
375 | "<text text-anchor=\"middle\" x=\"558.5755\" y=\"-107.2469\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">S(b)</text>\n", | |
375 | 376 | "</g>\n", |
376 | 377 | "<!-- LR_7->LR_8 -->\n", |
377 | 378 | "<g id=\"edge11\" class=\"edge\">\n", |
378 | 379 | "<title>LR_7->LR_8</title>\n", |
379 | "<path fill=\"none\" stroke=\"black\" d=\"M604.38,-99.37C618.26,-106.67 635.28,-115.67 650.47,-123.85 654.74,-126.14 659.19,-128.56 663.62,-130.98\"/>\n", | |
380 | "<polygon fill=\"black\" stroke=\"black\" points=\"662.17,-134.17 672.62,-135.9 665.53,-128.03 662.17,-134.17\"/>\n", | |
381 | "<text text-anchor=\"middle\" x=\"637.97\" y=\"-127.65\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">S(b)</text>\n", | |
380 | "<path fill=\"none\" stroke=\"#000000\" d=\"M657,-104.732C672.4832,-112.4022 691.492,-121.8649 708.4694,-130.4469 712.7313,-132.6013 717.1681,-134.8574 721.5984,-137.1192\"/>\n", | |
381 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"720.1286,-140.2987 730.6252,-141.7387 723.3177,-134.0672 720.1286,-140.2987\"/>\n", | |
382 | "<text text-anchor=\"middle\" x=\"693.4694\" y=\"-134.2469\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">S(b)</text>\n", | |
382 | 383 | "</g>\n", |
383 | 384 | "<!-- LR_7->LR_5 -->\n", |
384 | 385 | "<g id=\"edge12\" class=\"edge\">\n", |
385 | 386 | "<title>LR_7->LR_5</title>\n", |
386 | "<path fill=\"none\" stroke=\"black\" d=\"M545.05,-75.8C531.36,-72.99 515.01,-71.6 500.78,-75.85 495.43,-77.44 490.13,-79.83 485.1,-82.59\"/>\n", | |
387 | "<polygon fill=\"black\" stroke=\"black\" points=\"483.11,-79.7 476.38,-87.89 486.75,-85.69 483.11,-79.7\"/>\n", | |
388 | "<text text-anchor=\"middle\" x=\"513.28\" y=\"-79.65\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">S(a)</text>\n", | |
387 | "<path fill=\"none\" stroke=\"#000000\" d=\"M592.6491,-80.1131C577.456,-77.3057 559.3781,-76.0067 543.5755,-80.4469 538.2486,-81.9437 532.927,-84.1479 527.8273,-86.7112\"/>\n", | |
388 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"525.9854,-83.7304 518.9342,-91.6381 529.3777,-89.8535 525.9854,-83.7304\"/>\n", | |
389 | "<text text-anchor=\"middle\" x=\"558.5755\" y=\"-84.2469\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">S(a)</text>\n", | |
389 | 390 | "</g>\n", |
390 | 391 | "</g>\n", |
391 | 392 | "</svg>\n" |
392 | 393 | ], |
393 | 394 | "text/plain": [ |
394 | "<graphviz.graphs.Digraph at 0x203f27271f0>" | |
395 | "<graphviz.graphs.Digraph at 0x7fe7ac39d890>" | |
395 | 396 | ] |
396 | 397 | }, |
397 | 398 | "execution_count": 4, |
440 | 441 | "name": "stderr", |
441 | 442 | "output_type": "stream", |
442 | 443 | "text": [ |
443 | "[DEBUG@graphviz.backend.execute] run [WindowsPath('dot'), '-Kdot', '-Tsvg']\n" | |
444 | "[DEBUG@graphviz.backend.execute] run [PosixPath('dot'), '-Kdot', '-Tsvg']\n" | |
444 | 445 | ] |
445 | 446 | }, |
446 | 447 | { |
449 | 450 | "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n", |
450 | 451 | "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n", |
451 | 452 | " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n", |
452 | "<!-- Generated by graphviz version 2.49.3 (20211023.0002)\n", | |
453 | "<!-- Generated by graphviz version 2.40.1 (20161225.0304)\n", | |
453 | 454 | " -->\n", |
454 | 455 | "<!-- Title: G Pages: 1 -->\n", |
455 | 456 | "<svg width=\"222pt\" height=\"364pt\"\n", |
456 | 457 | " viewBox=\"0.00 0.00 222.00 364.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", |
457 | 458 | "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 360)\">\n", |
458 | 459 | "<title>G</title>\n", |
459 | "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-360 218,-360 218,4 -4,4\"/>\n", | |
460 | "<polygon fill=\"#ffffff\" stroke=\"transparent\" points=\"-4,4 -4,-360 218,-360 218,4 -4,4\"/>\n", | |
460 | 461 | "<g id=\"clust1\" class=\"cluster\">\n", |
461 | 462 | "<title>cluster0</title>\n", |
462 | "<polygon fill=\"none\" stroke=\"black\" points=\"64,-152 64,-348 206,-348 206,-152 64,-152\"/>\n", | |
463 | "<polygon fill=\"none\" stroke=\"#000000\" points=\"64,-152 64,-348 206,-348 206,-152 64,-152\"/>\n", | |
463 | 464 | "</g>\n", |
464 | 465 | "<g id=\"clust2\" class=\"cluster\">\n", |
465 | 466 | "<title>cluster1</title>\n", |
466 | "<polygon fill=\"none\" stroke=\"black\" points=\"64,-8 64,-132 206,-132 206,-8 64,-8\"/>\n", | |
467 | "<polygon fill=\"none\" stroke=\"#000000\" points=\"64,-8 64,-132 206,-132 206,-8 64,-8\"/>\n", | |
467 | 468 | "</g>\n", |
468 | 469 | "<!-- a -->\n", |
469 | 470 | "<g id=\"node1\" class=\"node\">\n", |
470 | 471 | "<title>a</title>\n", |
471 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"135\" cy=\"-322\" rx=\"27\" ry=\"18\"/>\n", | |
472 | "<text text-anchor=\"middle\" x=\"135\" y=\"-318.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">a</text>\n", | |
472 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"135\" cy=\"-322\" rx=\"27\" ry=\"18\"/>\n", | |
473 | "<text text-anchor=\"middle\" x=\"135\" y=\"-318.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">a</text>\n", | |
473 | 474 | "</g>\n", |
474 | 475 | "<!-- b -->\n", |
475 | 476 | "<g id=\"node2\" class=\"node\">\n", |
476 | 477 | "<title>b</title>\n", |
477 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-250\" rx=\"27\" ry=\"18\"/>\n", | |
478 | "<text text-anchor=\"middle\" x=\"99\" y=\"-246.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">b</text>\n", | |
478 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"99\" cy=\"-250\" rx=\"27\" ry=\"18\"/>\n", | |
479 | "<text text-anchor=\"middle\" x=\"99\" y=\"-246.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">b</text>\n", | |
479 | 480 | "</g>\n", |
480 | 481 | "<!-- a->b -->\n", |
481 | 482 | "<g id=\"edge1\" class=\"edge\">\n", |
482 | 483 | "<title>a->b</title>\n", |
483 | "<path fill=\"none\" stroke=\"black\" d=\"M126.65,-304.76C122.29,-296.28 116.85,-285.71 111.96,-276.2\"/>\n", | |
484 | "<polygon fill=\"black\" stroke=\"black\" points=\"114.99,-274.44 107.3,-267.15 108.77,-277.64 114.99,-274.44\"/>\n", | |
484 | "<path fill=\"none\" stroke=\"#000000\" d=\"M126.2854,-304.5708C122.0403,-296.0807 116.8464,-285.6929 112.1337,-276.2674\"/>\n", | |
485 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"115.237,-274.6477 107.6343,-267.2687 108.976,-277.7782 115.237,-274.6477\"/>\n", | |
485 | 486 | "</g>\n", |
486 | 487 | "<!-- c -->\n", |
487 | 488 | "<g id=\"node3\" class=\"node\">\n", |
488 | 489 | "<title>c</title>\n", |
489 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"171\" cy=\"-250\" rx=\"27\" ry=\"18\"/>\n", | |
490 | "<text text-anchor=\"middle\" x=\"171\" y=\"-246.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">c</text>\n", | |
490 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"171\" cy=\"-250\" rx=\"27\" ry=\"18\"/>\n", | |
491 | "<text text-anchor=\"middle\" x=\"171\" y=\"-246.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">c</text>\n", | |
491 | 492 | "</g>\n", |
492 | 493 | "<!-- a->c -->\n", |
493 | 494 | "<g id=\"edge2\" class=\"edge\">\n", |
494 | 495 | "<title>a->c</title>\n", |
495 | "<path fill=\"none\" stroke=\"black\" d=\"M143.35,-304.76C147.71,-296.28 153.15,-285.71 158.04,-276.2\"/>\n", | |
496 | "<polygon fill=\"black\" stroke=\"black\" points=\"161.23,-277.64 162.7,-267.15 155.01,-274.44 161.23,-277.64\"/>\n", | |
496 | "<path fill=\"none\" stroke=\"#000000\" d=\"M143.7146,-304.5708C147.9597,-296.0807 153.1536,-285.6929 157.8663,-276.2674\"/>\n", | |
497 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"161.024,-277.7782 162.3657,-267.2687 154.763,-274.6477 161.024,-277.7782\"/>\n", | |
497 | 498 | "</g>\n", |
498 | 499 | "<!-- d -->\n", |
499 | 500 | "<g id=\"node4\" class=\"node\">\n", |
500 | 501 | "<title>d</title>\n", |
501 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-178\" rx=\"27\" ry=\"18\"/>\n", | |
502 | "<text text-anchor=\"middle\" x=\"99\" y=\"-174.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">d</text>\n", | |
502 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"99\" cy=\"-178\" rx=\"27\" ry=\"18\"/>\n", | |
503 | "<text text-anchor=\"middle\" x=\"99\" y=\"-174.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">d</text>\n", | |
503 | 504 | "</g>\n", |
504 | 505 | "<!-- b->d -->\n", |
505 | 506 | "<g id=\"edge3\" class=\"edge\">\n", |
506 | 507 | "<title>b->d</title>\n", |
507 | "<path fill=\"none\" stroke=\"black\" d=\"M99,-231.7C99,-223.98 99,-214.71 99,-206.11\"/>\n", | |
508 | "<polygon fill=\"black\" stroke=\"black\" points=\"102.5,-206.1 99,-196.1 95.5,-206.1 102.5,-206.1\"/>\n", | |
508 | "<path fill=\"none\" stroke=\"#000000\" d=\"M99,-231.8314C99,-224.131 99,-214.9743 99,-206.4166\"/>\n", | |
509 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"102.5001,-206.4132 99,-196.4133 95.5001,-206.4133 102.5001,-206.4132\"/>\n", | |
509 | 510 | "</g>\n", |
510 | 511 | "<!-- f -->\n", |
511 | 512 | "<g id=\"node7\" class=\"node\">\n", |
512 | 513 | "<title>f</title>\n", |
513 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-34\" rx=\"27\" ry=\"18\"/>\n", | |
514 | "<text text-anchor=\"middle\" x=\"99\" y=\"-30.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">f</text>\n", | |
514 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"99\" cy=\"-34\" rx=\"27\" ry=\"18\"/>\n", | |
515 | "<text text-anchor=\"middle\" x=\"99\" y=\"-30.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">f</text>\n", | |
515 | 516 | "</g>\n", |
516 | 517 | "<!-- b->f -->\n", |
517 | 518 | "<g id=\"edge7\" class=\"edge\">\n", |
518 | 519 | "<title>b->f</title>\n", |
519 | "<path fill=\"none\" stroke=\"black\" d=\"M112.75,-234.07C120.96,-224.1 130.62,-210.25 135,-196 142.02,-173.17 145.55,-157.68 145.58,-142.23\"/>\n", | |
520 | "<polygon fill=\"black\" stroke=\"black\" points=\"149.07,-141.82 145.1,-132 142.07,-142.15 149.07,-141.82\"/>\n", | |
520 | "<path fill=\"none\" stroke=\"#000000\" d=\"M113.1229,-234.2844C121.2535,-224.1468 130.6901,-210.2347 135,-196 141.9225,-173.1366 145.3998,-157.6593 145.432,-142.2164\"/>\n", | |
521 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"148.9176,-141.8227 144.9572,-131.9959 141.9251,-142.1476 148.9176,-141.8227\"/>\n", | |
521 | 522 | "</g>\n", |
522 | 523 | "<!-- c->d -->\n", |
523 | 524 | "<g id=\"edge4\" class=\"edge\">\n", |
524 | 525 | "<title>c->d</title>\n", |
525 | "<path fill=\"none\" stroke=\"black\" d=\"M156.43,-234.83C146.25,-224.94 132.48,-211.55 120.97,-200.36\"/>\n", | |
526 | "<polygon fill=\"black\" stroke=\"black\" points=\"123.41,-197.85 113.8,-193.38 118.53,-202.87 123.41,-197.85\"/>\n", | |
526 | "<path fill=\"none\" stroke=\"#000000\" d=\"M155.7307,-234.7307C145.803,-224.803 132.6847,-211.6847 121.5637,-200.5637\"/>\n", | |
527 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"123.7933,-197.8436 114.2473,-193.2473 118.8436,-202.7933 123.7933,-197.8436\"/>\n", | |
527 | 528 | "</g>\n", |
528 | 529 | "<!-- e -->\n", |
529 | 530 | "<g id=\"node5\" class=\"node\">\n", |
530 | 531 | "<title>e</title>\n", |
531 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-106\" rx=\"27\" ry=\"18\"/>\n", | |
532 | "<text text-anchor=\"middle\" x=\"99\" y=\"-102.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">e</text>\n", | |
532 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"99\" cy=\"-106\" rx=\"27\" ry=\"18\"/>\n", | |
533 | "<text text-anchor=\"middle\" x=\"99\" y=\"-102.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">e</text>\n", | |
533 | 534 | "</g>\n", |
534 | 535 | "<!-- c->e -->\n", |
535 | 536 | "<g id=\"edge10\" class=\"edge\">\n", |
536 | 537 | "<title>c->e</title>\n", |
537 | "<path fill=\"none\" stroke=\"black\" d=\"M135,-152C130.7,-144.41 125.16,-136.77 119.71,-129.99\"/>\n", | |
538 | "<polygon fill=\"black\" stroke=\"black\" points=\"122.07,-127.36 112.97,-121.94 116.71,-131.86 122.07,-127.36\"/>\n", | |
538 | "<path fill=\"none\" stroke=\"#000000\" d=\"M135,-152C130.7681,-144.3996 125.3302,-136.7278 119.9697,-129.8859\"/>\n", | |
539 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"122.3507,-127.2677 113.3176,-121.7311 116.9265,-131.6924 122.3507,-127.2677\"/>\n", | |
539 | 540 | "</g>\n", |
540 | 541 | "<!-- g -->\n", |
541 | 542 | "<g id=\"node6\" class=\"node\">\n", |
542 | 543 | "<title>g</title>\n", |
543 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"171\" cy=\"-34\" rx=\"27\" ry=\"18\"/>\n", | |
544 | "<text text-anchor=\"middle\" x=\"171\" y=\"-30.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">g</text>\n", | |
544 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"171\" cy=\"-34\" rx=\"27\" ry=\"18\"/>\n", | |
545 | "<text text-anchor=\"middle\" x=\"171\" y=\"-30.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">g</text>\n", | |
545 | 546 | "</g>\n", |
546 | 547 | "<!-- c->g -->\n", |
547 | 548 | "<g id=\"edge9\" class=\"edge\">\n", |
548 | 549 | "<title>c->g</title>\n", |
549 | "<path fill=\"none\" stroke=\"black\" d=\"M171,-152C171,-148.77 171,-145.53 171,-142.29\"/>\n", | |
550 | "<polygon fill=\"black\" stroke=\"black\" points=\"174.5,-141.99 171,-132 167.5,-142 174.5,-141.99\"/>\n", | |
550 | "<path fill=\"none\" stroke=\"#000000\" d=\"M171,-152.004C171,-148.766 171,-145.516 171,-142.2656\"/>\n", | |
551 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"174.5001,-141.9975 171,-131.9976 167.5001,-141.9976 174.5001,-141.9975\"/>\n", | |
551 | 552 | "</g>\n", |
552 | 553 | "<!-- d->e -->\n", |
553 | 554 | "<g id=\"edge8\" class=\"edge\">\n", |
554 | 555 | "<title>d->e</title>\n", |
555 | "<path fill=\"none\" stroke=\"black\" d=\"M99,-159.7C99,-151.98 99,-142.71 99,-134.11\"/>\n", | |
556 | "<polygon fill=\"black\" stroke=\"black\" points=\"102.5,-134.1 99,-124.1 95.5,-134.1 102.5,-134.1\"/>\n", | |
556 | "<path fill=\"none\" stroke=\"#000000\" d=\"M99,-159.8314C99,-152.131 99,-142.9743 99,-134.4166\"/>\n", | |
557 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"102.5001,-134.4132 99,-124.4133 95.5001,-134.4133 102.5001,-134.4132\"/>\n", | |
557 | 558 | "</g>\n", |
558 | 559 | "<!-- h -->\n", |
559 | 560 | "<g id=\"node8\" class=\"node\">\n", |
560 | 561 | "<title>h</title>\n", |
561 | "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-106\" rx=\"27\" ry=\"18\"/>\n", | |
562 | "<text text-anchor=\"middle\" x=\"27\" y=\"-102.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">h</text>\n", | |
562 | "<ellipse fill=\"none\" stroke=\"#000000\" cx=\"27\" cy=\"-106\" rx=\"27\" ry=\"18\"/>\n", | |
563 | "<text text-anchor=\"middle\" x=\"27\" y=\"-102.3\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">h</text>\n", | |
563 | 564 | "</g>\n", |
564 | 565 | "<!-- d->h -->\n", |
565 | 566 | "<g id=\"edge11\" class=\"edge\">\n", |
566 | 567 | "<title>d->h</title>\n", |
567 | "<path fill=\"none\" stroke=\"black\" d=\"M84.43,-162.83C74.25,-152.94 60.48,-139.55 48.97,-128.36\"/>\n", | |
568 | "<polygon fill=\"black\" stroke=\"black\" points=\"51.41,-125.85 41.8,-121.38 46.53,-130.87 51.41,-125.85\"/>\n", | |
568 | "<path fill=\"none\" stroke=\"#000000\" d=\"M83.7307,-162.7307C73.803,-152.803 60.6847,-139.6847 49.5637,-128.5637\"/>\n", | |
569 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"51.7933,-125.8436 42.2473,-121.2473 46.8436,-130.7933 51.7933,-125.8436\"/>\n", | |
569 | 570 | "</g>\n", |
570 | 571 | "<!-- e->g -->\n", |
571 | 572 | "<g id=\"edge5\" class=\"edge\">\n", |
572 | 573 | "<title>e->g</title>\n", |
573 | "<path fill=\"none\" stroke=\"black\" d=\"M113.57,-90.83C123.75,-80.94 137.52,-67.55 149.03,-56.36\"/>\n", | |
574 | "<polygon fill=\"black\" stroke=\"black\" points=\"151.47,-58.87 156.2,-49.38 146.59,-53.85 151.47,-58.87\"/>\n", | |
574 | "<path fill=\"none\" stroke=\"#000000\" d=\"M114.2693,-90.7307C124.197,-80.803 137.3153,-67.6847 148.4363,-56.5637\"/>\n", | |
575 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"151.1564,-58.7933 155.7527,-49.2473 146.2067,-53.8436 151.1564,-58.7933\"/>\n", | |
575 | 576 | "</g>\n", |
576 | 577 | "<!-- e->f -->\n", |
577 | 578 | "<g id=\"edge6\" class=\"edge\">\n", |
578 | 579 | "<title>e->f</title>\n", |
579 | "<path fill=\"none\" stroke=\"black\" d=\"M99,-87.7C99,-79.98 99,-70.71 99,-62.11\"/>\n", | |
580 | "<polygon fill=\"black\" stroke=\"black\" points=\"102.5,-62.1 99,-52.1 95.5,-62.1 102.5,-62.1\"/>\n", | |
580 | "<path fill=\"none\" stroke=\"#000000\" d=\"M99,-87.8314C99,-80.131 99,-70.9743 99,-62.4166\"/>\n", | |
581 | "<polygon fill=\"#000000\" stroke=\"#000000\" points=\"102.5001,-62.4132 99,-52.4133 95.5001,-62.4133 102.5001,-62.4132\"/>\n", | |
581 | 582 | "</g>\n", |
582 | 583 | "</g>\n", |
583 | 584 | "</svg>\n" |
584 | 585 | ], |
585 | 586 | "text/plain": [ |
586 | "<graphviz.graphs.Digraph at 0x203f2726cb0>" | |
587 | "<graphviz.graphs.Digraph at 0x7fe7ac4083d0>" | |
587 | 588 | ] |
588 | 589 | }, |
589 | 590 | "execution_count": 5, |
630 | 631 | "name": "python", |
631 | 632 | "nbconvert_exporter": "python", |
632 | 633 | "pygments_lexer": "ipython3", |
633 | "version": "3.10.0" | |
634 | "version": "3.7.12" | |
634 | 635 | } |
635 | 636 | }, |
636 | 637 | "nbformat": 4, |
637 | "nbformat_minor": 1 | |
638 | "nbformat_minor": 4 | |
638 | 639 | } |
30 | 30 | from .backend import (DOT_BINARY, UNFLATTEN_BINARY, |
31 | 31 | render, pipe, pipe_string, pipe_lines, pipe_lines_string, |
32 | 32 | unflatten, version, view) |
33 | from .exceptions import (RequiredArgumentError, FileExistsError, | |
33 | from .exceptions import (ExecutableNotFound, CalledProcessError, | |
34 | RequiredArgumentError, FileExistsError, | |
34 | 35 | UnknownSuffixWarning, FormatSuffixMismatchWarning, |
35 | ExecutableNotFound, CalledProcessError) | |
36 | DotSyntaxWarning) | |
36 | 37 | from .graphs import Graph, Digraph |
37 | 38 | from .jupyter_integration import SUPPORTED_JUPYTER_FORMATS |
38 | 39 | from .parameters import ENGINES, FORMATS, RENDERERS, FORMATTERS |
47 | 48 | 'escape', 'nohtml', |
48 | 49 | 'render', 'pipe', 'pipe_string', 'pipe_lines', 'pipe_lines_string', |
49 | 50 | 'unflatten', 'version', 'view', |
51 | 'ExecutableNotFound', 'CalledProcessError', | |
50 | 52 | 'RequiredArgumentError', 'FileExistsError', |
51 | 53 | 'UnknownSuffixWarning', 'FormatSuffixMismatchWarning', |
52 | 'ExecutableNotFound, CalledProcessError', | |
54 | 'DotSyntaxWarning', | |
53 | 55 | 'set_default_engine', 'set_default_format', 'set_jupyter_format'] |
54 | 56 | |
55 | 57 | __title__ = 'graphviz' |
56 | __version__ = '0.19.1' | |
58 | __version__ = '0.20.1' | |
57 | 59 | __author__ = 'Sebastian Bank <sebastian.bank@uni-leipzig.de>' |
58 | 60 | __license__ = 'MIT, see LICENSE.txt' |
59 | __copyright__ = 'Copyright (c) 2013-2021 Sebastian Bank' | |
61 | __copyright__ = 'Copyright (c) 2013-2022 Sebastian Bank' | |
60 | 62 | |
61 | 63 | ENGINES = ENGINES |
62 | 64 | """:class:`set` of known layout commands used for rendering |
85 | 87 | """:class:`pathlib.Path` of unflatten command (``Path('unflatten')``).""" |
86 | 88 | |
87 | 89 | |
90 | ExecutableNotFound = ExecutableNotFound | |
91 | ||
92 | ||
93 | CalledProcessError = CalledProcessError | |
94 | ||
95 | ||
88 | 96 | RequiredArgumentError = RequiredArgumentError |
89 | 97 | |
90 | 98 | |
91 | ExecutableNotFound = ExecutableNotFound | |
99 | FileExistsError = FileExistsError | |
92 | 100 | |
93 | 101 | |
94 | 102 | UnknownSuffixWarning = UnknownSuffixWarning |
97 | 105 | FormatSuffixMismatchWarning = FormatSuffixMismatchWarning |
98 | 106 | |
99 | 107 | |
100 | CalledProcessError = CalledProcessError | |
101 | ||
102 | ||
103 | FileExistsError = FileExistsError | |
108 | DotSyntaxWarning = DotSyntaxWarning |
0 | """Python 3.6 to 3.8 compatibility and platform compatibility.""" | |
0 | """Python 3.7 to 3.8 compatibility and platform compatibility.""" | |
1 | 1 | |
2 | import pathlib | |
2 | import os | |
3 | 3 | import platform |
4 | 4 | import sys |
5 | 5 | import typing |
40 | 40 | return startupinfo |
41 | 41 | |
42 | 42 | |
43 | def make_subprocess_arg(arg: typing.Union[str, pathlib.Path]): | |
43 | def make_subprocess_arg(arg: typing.Union[str, os.PathLike]) -> typing.Union[str, os.PathLike]: | |
44 | 44 | """Return subprocess argument as is (default no-op).""" |
45 | 45 | return arg |
46 | 46 | |
47 | 47 | |
48 | 48 | if platform.system() == 'Windows' and sys.version_info < (3, 8): # pragma: no cover |
49 | def make_subprocess_arg(arg: typing.Union[str, pathlib.Path]) -> str: # noqa: F811 | |
49 | def make_subprocess_arg(arg: typing.Union[str, os.PathLike]) -> str: # noqa: F811 | |
50 | 50 | """Workaround https://bugs.python.org/issue41649 (not backported).""" |
51 | return str(arg) | |
51 | return os.fspath(arg) |
38 | 38 | return decorator |
39 | 39 | |
40 | 40 | |
41 | def mkdirs(filename, *, mode: int = 0o777) -> None: | |
41 | def mkdirs(filename: typing.Union[os.PathLike, str], *, mode: int = 0o777) -> None: | |
42 | 42 | """Recursively create directories up to the path of ``filename`` |
43 | 43 | as needed.""" |
44 | 44 | dirname = os.path.dirname(filename) |
66 | 66 | |
67 | 67 | |
68 | 68 | @typing.overload |
69 | def promote_pathlike(filepath: typing.Union[os.PathLike, str] | |
70 | ) -> pathlib.Path: | |
69 | def promote_pathlike(filepath: typing.Union[os.PathLike, str]) -> pathlib.Path: | |
71 | 70 | """Return path object for path-like-object.""" |
72 | 71 | |
73 | 72 |
13 | 13 | |
14 | 14 | def command(engine: str, format_: str, *, |
15 | 15 | renderer: typing.Optional[str] = None, |
16 | formatter: typing.Optional[str] = None | |
16 | formatter: typing.Optional[str] = None, | |
17 | neato_no_op: typing.Union[bool, int, None] = None | |
17 | 18 | ) -> typing.List[typing.Union[os.PathLike, str]]: |
18 | 19 | """Return ``subprocess.Popen`` argument list for rendering. |
19 | 20 | |
21 | 22 | Upstream documentation: |
22 | 23 | - https://www.graphviz.org/doc/info/command.html#-K |
23 | 24 | - https://www.graphviz.org/doc/info/command.html#-T |
25 | - https://www.graphviz.org/doc/info/command.html#-n | |
24 | 26 | """ |
25 | 27 | if formatter is not None and renderer is None: |
26 | 28 | raise exceptions.RequiredArgumentError('formatter given without renderer') |
33 | 35 | output_format = [f for f in (format_, renderer, formatter) if f is not None] |
34 | 36 | output_format_flag = ':'.join(output_format) |
35 | 37 | |
36 | return [DOT_BINARY, f'-K{engine}', f'-T{output_format_flag}'] | |
38 | cmd = [DOT_BINARY, f'-K{engine}', f'-T{output_format_flag}'] | |
39 | ||
40 | if neato_no_op: | |
41 | cmd.append(f'-n{neato_no_op:d}') | |
42 | ||
43 | return cmd |
22 | 22 | def run_check(cmd: typing.Sequence[typing.Union[os.PathLike, str]], *, |
23 | 23 | input_lines: typing.Optional[typing.Iterator[bytes]] = ..., |
24 | 24 | encoding: None = ..., |
25 | capture_output: bool = ..., | |
26 | 25 | quiet: bool = ..., |
27 | 26 | **kwargs) -> subprocess.CompletedProcess: |
28 | 27 | """Accept bytes input_lines with default ``encoding=None```.""" |
32 | 31 | def run_check(cmd: typing.Sequence[typing.Union[os.PathLike, str]], *, |
33 | 32 | input_lines: typing.Optional[typing.Iterator[str]] = ..., |
34 | 33 | encoding: str, |
35 | capture_output: bool = ..., | |
36 | 34 | quiet: bool = ..., |
37 | 35 | **kwargs) -> subprocess.CompletedProcess: |
38 | 36 | """Accept string input_lines when given ``encoding``.""" |
51 | 49 | def run_check(cmd: typing.Sequence[typing.Union[os.PathLike, str]], *, |
52 | 50 | input_lines: typing.Optional[BytesOrStrIterator] = None, |
53 | 51 | encoding: typing.Optional[str] = None, |
54 | capture_output: bool = False, | |
55 | 52 | quiet: bool = False, |
56 | 53 | **kwargs) -> subprocess.CompletedProcess: |
57 | 54 | """Run the command described by ``cmd`` |
67 | 64 | if not kwargs.pop('check', True): # pragma: no cover |
68 | 65 | raise NotImplementedError('check must be True or omited') |
69 | 66 | |
70 | if capture_output: # Python 3.6 compat | |
71 | kwargs['stdout'] = kwargs['stderr'] = subprocess.PIPE | |
72 | ||
73 | 67 | if encoding is not None: |
74 | 68 | kwargs['encoding'] = encoding |
75 | 69 | |
79 | 73 | if input_lines is not None: |
80 | 74 | assert kwargs.get('input') is None |
81 | 75 | assert iter(input_lines) is input_lines |
76 | if kwargs.pop('capture_output'): | |
77 | kwargs['stdout'] = kwargs['stderr'] = subprocess.PIPE | |
82 | 78 | proc = _run_input_lines(cmd, input_lines, kwargs=kwargs) |
83 | 79 | else: |
84 | 80 | proc = subprocess.run(cmd, **kwargs) |
122 | 118 | |
123 | 119 | |
124 | 120 | class ExecutableNotFound(RuntimeError): |
125 | """:class:`RuntimeError` raised if the Graphviz executable is not found.""" | |
121 | """:exc:`RuntimeError` raised if the Graphviz executable is not found.""" | |
126 | 122 | |
127 | 123 | _msg = ('failed to execute {!r}, ' |
128 | 124 | 'make sure the Graphviz executables are on your systems\' PATH') |
132 | 128 | |
133 | 129 | |
134 | 130 | class CalledProcessError(subprocess.CalledProcessError): |
135 | """:class:`~subprocess.CalledProcessError` raised if a subprocess ``returncode`` is not ``0``.""" # noqa: E501 | |
131 | """:exc:`~subprocess.CalledProcessError` raised if a subprocess ``returncode`` is not ``0``.""" # noqa: E501 | |
136 | 132 | |
137 | 133 | def __str__(self) -> 'str': |
138 | 134 | return f'{super().__str__()} [stderr: {self.stderr!r}]' |
14 | 14 | def pipe(engine: str, format: str, data: bytes, |
15 | 15 | renderer: typing.Optional[str] = None, |
16 | 16 | formatter: typing.Optional[str] = None, |
17 | neato_no_op: typing.Union[bool, int, None] = None, | |
17 | 18 | quiet: bool = False) -> bytes: |
18 | 19 | """Return ``data`` (``bytes``) piped through ``engine`` into ``format`` as ``bytes``. |
19 | 20 | |
23 | 24 | data: Binary (encoded) DOT source bytes to render. |
24 | 25 | renderer: Output renderer (``'cairo'``, ``'gd'``, ...). |
25 | 26 | formatter: Output formatter (``'cairo'``, ``'gd'``, ...). |
27 | neato_no_op: Neato layout engine no-op flag. | |
26 | 28 | quiet: Suppress ``stderr`` output from the layout subprocess. |
27 | 29 | |
28 | 30 | Returns: |
48 | 50 | The layout command is started from the current directory. |
49 | 51 | """ |
50 | 52 | cmd = dot_command.command(engine, format, |
51 | renderer=renderer, formatter=formatter) | |
53 | renderer=renderer, | |
54 | formatter=formatter, | |
55 | neato_no_op=neato_no_op) | |
52 | 56 | kwargs = {'input': data} |
53 | 57 | |
54 | 58 | proc = execute.run_check(cmd, capture_output=True, quiet=quiet, **kwargs) |
59 | 63 | encoding: str, |
60 | 64 | renderer: typing.Optional[str] = None, |
61 | 65 | formatter: typing.Optional[str] = None, |
66 | neato_no_op: typing.Union[bool, int, None] = None, | |
62 | 67 | quiet: bool = False) -> str: |
63 | 68 | """Return ``input_string`` piped through ``engine`` into ``format`` as string. |
64 | 69 | |
69 | 74 | encoding: Encoding to en/decode subprocess stdin and stdout (required). |
70 | 75 | renderer: Output renderer (``'cairo'``, ``'gd'``, ...). |
71 | 76 | formatter: Output formatter (``'cairo'``, ``'gd'``, ...). |
77 | neato_no_op: Neato layout engine no-op flag. | |
72 | 78 | quiet: Suppress ``stderr`` output from the layout subprocess. |
73 | 79 | |
74 | 80 | Returns: |
95 | 101 | The layout command is started from the current directory. |
96 | 102 | """ |
97 | 103 | cmd = dot_command.command(engine, format, |
98 | renderer=renderer, formatter=formatter) | |
104 | renderer=renderer, | |
105 | formatter=formatter, | |
106 | neato_no_op=neato_no_op) | |
99 | 107 | kwargs = {'input': input_string, 'encoding': encoding} |
100 | 108 | |
101 | 109 | proc = execute.run_check(cmd, capture_output=True, quiet=quiet, **kwargs) |
106 | 114 | input_encoding: str, |
107 | 115 | renderer: typing.Optional[str] = None, |
108 | 116 | formatter: typing.Optional[str] = None, |
117 | neato_no_op: typing.Union[bool, int, None] = None, | |
109 | 118 | quiet: bool = False) -> bytes: |
110 | 119 | r"""Return ``input_lines`` piped through ``engine`` into ``format`` as ``bytes``. |
111 | 120 | |
116 | 125 | input_encoding: Encode input_lines for subprocess stdin (required). |
117 | 126 | renderer: Output renderer (``'cairo'``, ``'gd'``, ...). |
118 | 127 | formatter: Output formatter (``'cairo'``, ``'gd'``, ...). |
128 | neato_no_op: Neato layout engine no-op flag. | |
119 | 129 | quiet: Suppress ``stderr`` output from the layout subprocess. |
120 | 130 | |
121 | 131 | Returns: |
142 | 152 | The layout command is started from the current directory. |
143 | 153 | """ |
144 | 154 | cmd = dot_command.command(engine, format, |
145 | renderer=renderer, formatter=formatter) | |
155 | renderer=renderer, | |
156 | formatter=formatter, | |
157 | neato_no_op=neato_no_op) | |
146 | 158 | kwargs = {'input_lines': (line.encode(input_encoding) for line in input_lines)} |
147 | 159 | |
148 | 160 | proc = execute.run_check(cmd, capture_output=True, quiet=quiet, **kwargs) |
153 | 165 | encoding: str, |
154 | 166 | renderer: typing.Optional[str] = None, |
155 | 167 | formatter: typing.Optional[str] = None, |
168 | neato_no_op: typing.Union[bool, int, None] = None, | |
156 | 169 | quiet: bool = False) -> str: |
157 | 170 | r"""Return ``input_lines`` piped through ``engine`` into ``format`` as string. |
158 | 171 | |
163 | 176 | encoding: Encoding to en/decode subprocess stdin and stdout (required). |
164 | 177 | renderer: Output renderer (``'cairo'``, ``'gd'``, ...). |
165 | 178 | formatter: Output formatter (``'cairo'``, ``'gd'``, ...). |
179 | neato_no_op: Neato layout engine no-op flag. | |
166 | 180 | quiet: Suppress ``stderr`` output from the layout subprocess. |
167 | 181 | |
168 | 182 | Returns: |
189 | 203 | The layout command is started from the current directory. |
190 | 204 | """ |
191 | 205 | cmd = dot_command.command(engine, format, |
192 | renderer=renderer, formatter=formatter) | |
206 | renderer=renderer, | |
207 | formatter=formatter, | |
208 | neato_no_op=neato_no_op) | |
193 | 209 | kwargs = {'input_lines': input_lines, 'encoding': encoding} |
194 | 210 | |
195 | 211 | proc = execute.run_check(cmd, capture_output=True, quiet=quiet, **kwargs) |
159 | 159 | filepath: typing.Union[os.PathLike, str], |
160 | 160 | renderer: typing.Optional[str] = ..., |
161 | 161 | formatter: typing.Optional[str] = ..., |
162 | neato_no_op: typing.Union[bool, int, None] = ..., | |
162 | 163 | quiet: bool = ..., *, |
163 | 164 | outfile: typing.Union[os.PathLike, str, None] = ..., |
164 | 165 | raise_if_result_exists: bool = ..., |
172 | 173 | filepath: typing.Union[os.PathLike, str, None] = ..., |
173 | 174 | renderer: typing.Optional[str] = ..., |
174 | 175 | formatter: typing.Optional[str] = ..., |
176 | neato_no_op: typing.Union[bool, int, None] = ..., | |
175 | 177 | quiet: bool = False, *, |
176 | 178 | outfile: typing.Union[os.PathLike, str, None] = ..., |
177 | 179 | raise_if_result_exists: bool = ..., |
185 | 187 | filepath: typing.Union[os.PathLike, str, None] = ..., |
186 | 188 | renderer: typing.Optional[str] = ..., |
187 | 189 | formatter: typing.Optional[str] = ..., |
190 | neato_no_op: typing.Union[bool, int, None] = ..., | |
188 | 191 | quiet: bool = False, *, |
189 | 192 | outfile: typing.Union[os.PathLike, str, None] = ..., |
190 | 193 | raise_if_result_exists: bool = ..., |
198 | 201 | filepath: typing.Union[os.PathLike, str, None] = None, |
199 | 202 | renderer: typing.Optional[str] = None, |
200 | 203 | formatter: typing.Optional[str] = None, |
204 | neato_no_op: typing.Union[bool, int, None] = None, | |
201 | 205 | quiet: bool = False, *, |
202 | 206 | outfile: typing.Union[os.PathLike, str, None] = None, |
203 | 207 | raise_if_result_exists: bool = False, |
214 | 218 | in which case it defaults to ``outfile.with_suffix('.gv')``. |
215 | 219 | renderer: Output renderer (``'cairo'``, ``'gd'``, ...). |
216 | 220 | formatter: Output formatter (``'cairo'``, ``'gd'``, ...). |
221 | neato_no_op: Neato layout engine no-op flag. | |
217 | 222 | quiet: Suppress ``stderr`` output from the layout subprocess. |
218 | 223 | outfile: Path for the rendered output file. |
219 | 224 | raise_if_result_exits: Raise :exc:`graphviz.FileExistsError` |
306 | 311 | args = ['-O', filepath.name] |
307 | 312 | |
308 | 313 | cmd = dot_command.command(engine, format, |
309 | renderer=renderer, formatter=formatter) | |
314 | renderer=renderer, | |
315 | formatter=formatter, | |
316 | neato_no_op=neato_no_op) | |
310 | 317 | |
311 | 318 | if raise_if_result_exists and os.path.exists(outfile): |
312 | 319 | raise exceptions.FileExistsError(f'output file exists: {os.fspath(outfile)!r}') |
9 | 9 | __all__ = ['GraphSyntax', 'DigraphSyntax', 'Dot'] |
10 | 10 | |
11 | 11 | |
12 | def comment(line: str): | |
12 | def comment(line: str) -> str: | |
13 | 13 | """Return comment header line.""" |
14 | 14 | return f'// {line}\n' |
15 | 15 | |
214 | 214 | The ``tail_name`` and ``head_name`` strings are separated |
215 | 215 | by (optional) colon(s) into ``node`` name, ``port`` name, |
216 | 216 | and ``compass`` (e.g. ``sw``). |
217 | See `details in the User Guide <ports>`. | |
217 | See :ref:`details in the User Guide <node-ports-compass>`. | |
218 | 218 | """ |
219 | 219 | tail_name = self._quote_edge(tail_name) |
220 | 220 | head_name = self._quote_edge(head_name) |
234 | 234 | The ``tail_name`` and ``head_name`` strings are separated |
235 | 235 | by (optional) colon(s) into ``node`` name, ``port`` name, |
236 | 236 | and ``compass`` (e.g. ``sw``). |
237 | See `details in the User Guide <ports>`. | |
237 | See :ref:`details in the User Guide <node-ports-compass>`. | |
238 | 238 | """ |
239 | 239 | edge = self._edge_plain |
240 | 240 | quote = self._quote_edge |
251 | 251 | (``None`` or ``'graph'``, ``'node'``, ``'edge'``). |
252 | 252 | attrs: Attributes to be set (must be strings, may be empty). |
253 | 253 | |
254 | See the `usage examples in the User Guide <attributes>`. | |
254 | See the :ref:`usage examples in the User Guide <attributes>`. | |
255 | 255 | """ |
256 | 256 | if kw is not None and kw.lower() not in ('graph', 'node', 'edge'): |
257 | 257 | raise ValueError('attr statement must target graph, node, or edge:' |
293 | 293 | body: Verbatim lines to add to the subgraph ``body`` |
294 | 294 | (``with``-block use). |
295 | 295 | |
296 | See the `usage examples in the User Guide <subgraphs>`. | |
296 | See the :ref:`usage examples in the User Guide <subgraphs-clusters>`. | |
297 | 297 | |
298 | 298 | When used as a context manager, the returned new graph instance |
299 | 299 | uses ``strict=None`` and the parent graph's values |
1 | 1 | |
2 | 2 | from .backend.execute import ExecutableNotFound, CalledProcessError |
3 | 3 | |
4 | __all__ = ['RequiredArgumentError', 'FileExistsError', | |
4 | __all__ = ['ExecutableNotFound', 'CalledProcessError', | |
5 | 'RequiredArgumentError', 'FileExistsError', | |
5 | 6 | 'UnknownSuffixWarning', 'FormatSuffixMismatchWarning', |
6 | 'ExecutableNotFound', 'CalledProcessError'] | |
7 | 'DotSyntaxWarning'] | |
7 | 8 | |
8 | 9 | |
9 | 10 | class RequiredArgumentError(TypeError): |
10 | """:class:`TypeError` raised if a required argument is missing.""" | |
11 | """:exc:`TypeError` raised if a required argument is missing.""" | |
11 | 12 | |
12 | 13 | |
13 | 14 | class FileExistsError(FileExistsError): |
14 | """:class:`FileNotFoundError` raised with ``raise_if_exists=True``.""" | |
15 | """:exc:`FileExistsError` raised with ``raise_if_exists=True``.""" | |
15 | 16 | |
16 | 17 | |
17 | 18 | class UnknownSuffixWarning(RuntimeWarning): |
18 | """:class:`RuntimeWarning` raised if the suffix of ``outfile`` is unknown | |
19 | """:exc:`RuntimeWarning` raised if the suffix of ``outfile`` is unknown | |
19 | 20 | and the given ``format`` is used instead.""" |
20 | 21 | |
21 | 22 | |
22 | 23 | class FormatSuffixMismatchWarning(UserWarning): |
23 | """:class:`UserWarning` raised if the suffix ``outfile`` | |
24 | """:exc:`UserWarning` raised if the suffix ``outfile`` | |
24 | 25 | does not match the given ``format``.""" |
26 | ||
27 | ||
28 | class DotSyntaxWarning(RuntimeWarning): | |
29 | """:exc:`RuntimeWarning` raised if a quoted string | |
30 | is expected to cause a ``CalledProcessError`` from rendering.""" |
95 | 95 | graph_attr: Mapping of ``(attribute, value)`` pairs for the graph. |
96 | 96 | node_attr: Mapping of ``(attribute, value)`` pairs set for all nodes. |
97 | 97 | edge_attr: Mapping of ``(attribute, value)`` pairs set for all edges. |
98 | body: Iterable of verbatim lines to add to the graph ``body``. | |
98 | body: Iterable of verbatim lines (including their final newline) | |
99 | to add to the graph ``body``. | |
99 | 100 | strict (bool): Rendering should merge multi-edges. |
100 | 101 | |
101 | 102 | Note: |
40 | 40 | 'vrml', |
41 | 41 | 'wbmp', |
42 | 42 | 'webp', |
43 | 'xlib', | |
44 | 'x11'} | |
43 | 'xlib', 'x11'} | |
45 | 44 | |
46 | 45 | DEFAULT_FORMAT = 'pdf' |
47 | 46 |
23 | 23 | format: typing.Optional[str] = ..., |
24 | 24 | renderer: typing.Optional[str] = ..., |
25 | 25 | formatter: typing.Optional[str] = ..., |
26 | neato_no_op: typing.Union[bool, int, None] = ..., | |
26 | 27 | quiet: bool = ..., *, |
27 | 28 | engine: typing.Optional[str] = ..., |
28 | 29 | encoding: None = ...) -> bytes: |
33 | 34 | format: typing.Optional[str] = ..., |
34 | 35 | renderer: typing.Optional[str] = ..., |
35 | 36 | formatter: typing.Optional[str] = ..., |
37 | neato_no_op: typing.Union[bool, int, None] = ..., | |
36 | 38 | quiet: bool = ..., *, |
37 | 39 | engine: typing.Optional[str] = ..., |
38 | 40 | encoding: str) -> str: |
43 | 45 | format: typing.Optional[str] = ..., |
44 | 46 | renderer: typing.Optional[str] = ..., |
45 | 47 | formatter: typing.Optional[str] = ..., |
48 | neato_no_op: typing.Union[bool, int, None] = ..., | |
46 | 49 | quiet: bool = ..., *, |
47 | 50 | engine: typing.Optional[str] = ..., |
48 | 51 | encoding: typing.Optional[str]) -> typing.Union[bytes, str]: |
52 | 55 | format: typing.Optional[str] = None, |
53 | 56 | renderer: typing.Optional[str] = None, |
54 | 57 | formatter: typing.Optional[str] = None, |
58 | neato_no_op: typing.Union[bool, int, None] = None, | |
55 | 59 | quiet: bool = False, *, |
56 | 60 | engine: typing.Optional[str] = None, |
57 | 61 | encoding: typing.Optional[str] = None) -> typing.Union[bytes, str]: |
64 | 68 | (``'cairo'``, ``'gd'``, ...). |
65 | 69 | formatter: The output formatter used for rendering |
66 | 70 | (``'cairo'``, ``'gd'``, ...). |
71 | neato_no_op: Neato layout engine no-op flag. | |
67 | 72 | quiet (bool): Suppress ``stderr`` output |
68 | 73 | from the layout subprocess. |
69 | 74 | engine: Layout engine for rendering |
98 | 103 | return self._pipe_legacy(format, |
99 | 104 | renderer=renderer, |
100 | 105 | formatter=formatter, |
106 | neato_no_op=neato_no_op, | |
101 | 107 | quiet=quiet, |
102 | 108 | engine=engine, |
103 | 109 | encoding=encoding) |
107 | 113 | format: typing.Optional[str] = None, |
108 | 114 | renderer: typing.Optional[str] = None, |
109 | 115 | formatter: typing.Optional[str] = None, |
116 | neato_no_op: typing.Union[bool, int, None] = None, | |
110 | 117 | quiet: bool = False, *, |
111 | 118 | engine: typing.Optional[str] = None, |
112 | 119 | encoding: typing.Optional[str] = None) -> typing.Union[bytes, str]: |
113 | 120 | return self._pipe_future(format, |
114 | 121 | renderer=renderer, |
115 | 122 | formatter=formatter, |
123 | neato_no_op=neato_no_op, | |
116 | 124 | quiet=quiet, |
117 | 125 | engine=engine, |
118 | 126 | encoding=encoding) |
120 | 128 | def _pipe_future(self, format: typing.Optional[str] = None, *, |
121 | 129 | renderer: typing.Optional[str] = None, |
122 | 130 | formatter: typing.Optional[str] = None, |
131 | neato_no_op: typing.Union[bool, int, None] = None, | |
123 | 132 | quiet: bool = False, |
124 | 133 | engine: typing.Optional[str] = None, |
125 | 134 | encoding: typing.Optional[str] = None) -> typing.Union[bytes, str]: |
127 | 136 | format=format, |
128 | 137 | renderer=renderer, |
129 | 138 | formatter=formatter, |
139 | neato_no_op=neato_no_op, | |
130 | 140 | quiet=quiet, |
131 | 141 | verify=True) |
132 | 142 |
2 | 2 | import functools |
3 | 3 | import re |
4 | 4 | import typing |
5 | import warnings | |
5 | 6 | |
6 | 7 | from . import _tools |
8 | from . import exceptions | |
7 | 9 | |
8 | 10 | __all__ = ['quote', 'quote_edge', |
9 | 11 | 'a_list', 'attr_list', |
20 | 22 | |
21 | 23 | COMPASS = {'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw', 'c', '_'} # TODO |
22 | 24 | |
23 | QUOTE_OPTIONAL_BACKSLASHES = re.compile(r'(?P<bs>(?:\\\\)*)' | |
24 | r'\\?(?P<quote>")') | |
25 | ||
26 | ESCAPE_UNESCAPED_QUOTES = functools.partial(QUOTE_OPTIONAL_BACKSLASHES.sub, | |
27 | r'\g<bs>\\\g<quote>') | |
25 | FINAL_ODD_BACKSLASHES = re.compile(r'(?<!\\)(?:\\{2})*\\$') | |
26 | ||
27 | QUOTE_WITH_OPTIONAL_BACKSLASHES = re.compile(r''' | |
28 | (?P<escaped_backslashes>(?:\\{2})*) | |
29 | \\? # treat \" same as " | |
30 | (?P<literal_quote>") | |
31 | ''', flags=re.VERBOSE) | |
32 | ||
33 | ESCAPE_UNESCAPED_QUOTES = functools.partial(QUOTE_WITH_OPTIONAL_BACKSLASHES.sub, | |
34 | r'\g<escaped_backslashes>' | |
35 | r'\\' | |
36 | r'\g<literal_quote>') | |
28 | 37 | |
29 | 38 | |
30 | 39 | @_tools.deprecate_positional_args(supported_number=1) |
32 | 41 | is_html_string=HTML_STRING.match, |
33 | 42 | is_valid_id=ID.match, |
34 | 43 | dot_keywords=KEYWORDS, |
44 | endswith_odd_number_of_backslashes=FINAL_ODD_BACKSLASHES.search, | |
35 | 45 | escape_unescaped_quotes=ESCAPE_UNESCAPED_QUOTES) -> str: |
36 | 46 | r"""Return DOT identifier from string, quote if needed. |
37 | 47 | |
71 | 81 | if is_html_string(identifier) and not isinstance(identifier, NoHtml): |
72 | 82 | pass |
73 | 83 | elif not is_valid_id(identifier) or identifier.lower() in dot_keywords: |
84 | if endswith_odd_number_of_backslashes(identifier): | |
85 | warnings.warn('expect syntax error scanning invalid quoted string:' | |
86 | f' {identifier!r}', | |
87 | category=exceptions.DotSyntaxWarning) | |
74 | 88 | return f'"{escape_unescaped_quotes(identifier)}"' |
75 | 89 | return identifier |
76 | 90 |
26 | 26 | format: typing.Optional[str] = None, |
27 | 27 | renderer: typing.Optional[str] = None, |
28 | 28 | formatter: typing.Optional[str] = None, |
29 | neato_no_op: typing.Union[bool, int, None] = None, | |
29 | 30 | quiet: bool = False, |
30 | 31 | quiet_view: bool = False, *, |
31 | 32 | outfile: typing.Union[os.PathLike, str, None] = None, |
48 | 49 | (``'cairo'``, ``'gd'``, ...). |
49 | 50 | formatter: The output formatter used for rendering |
50 | 51 | (``'cairo'``, ``'gd'``, ...). |
52 | neato_no_op: Neato layout engine no-op flag. | |
51 | 53 | quiet (bool): Suppress ``stderr`` output |
52 | 54 | from the layout subprocess. |
53 | 55 | quiet_view (bool): Suppress ``stderr`` output |
102 | 104 | format=format, |
103 | 105 | renderer=renderer, |
104 | 106 | formatter=formatter, |
107 | neato_no_op=neato_no_op, | |
105 | 108 | quiet=quiet, |
106 | 109 | outfile=outfile, |
107 | 110 | raise_if_result_exists=raise_if_result_exists, |
0 | 0 | Metadata-Version: 2.1 |
1 | 1 | Name: graphviz |
2 | Version: 0.19.1 | |
2 | Version: 0.20.1 | |
3 | 3 | Summary: Simple Python interface for Graphviz |
4 | 4 | Home-page: https://github.com/xflr6/graphviz |
5 | 5 | Author: Sebastian Bank |
18 | 18 | Classifier: License :: OSI Approved :: MIT License |
19 | 19 | Classifier: Operating System :: OS Independent |
20 | 20 | Classifier: Programming Language :: Python :: 3 |
21 | Classifier: Programming Language :: Python :: 3.6 | |
22 | 21 | Classifier: Programming Language :: Python :: 3.7 |
23 | 22 | Classifier: Programming Language :: Python :: 3.8 |
24 | 23 | Classifier: Programming Language :: Python :: 3.9 |
25 | 24 | Classifier: Programming Language :: Python :: 3.10 |
26 | 25 | Classifier: Topic :: Scientific/Engineering :: Visualization |
27 | Requires-Python: >=3.6 | |
26 | Requires-Python: >=3.7 | |
28 | 27 | Provides-Extra: dev |
29 | 28 | Provides-Extra: test |
30 | 29 | Provides-Extra: docs |
69 | 68 | Installation |
70 | 69 | ------------ |
71 | 70 | |
72 | This package runs under Python 3.6+, use pip_ to install: | |
71 | This package runs under Python 3.7+, use pip_ to install: | |
73 | 72 | |
74 | 73 | .. code:: bash |
75 | 74 | |
156 | 155 | :align: center |
157 | 156 | :alt: round-table.svg |
158 | 157 | |
158 | **Caveat:** | |
159 | Backslash-escapes and strings of the form ``<...>`` | |
160 | have a special meaning in the DOT language. | |
161 | If you need to render arbitrary strings (e.g. from user input), | |
162 | check the details in the `user guide`_. | |
163 | ||
159 | 164 | |
160 | 165 | See also |
161 | 166 | -------- |
205 | 210 | .. _conda-forge-python-graphviz-feedstock: https://github.com/conda-forge/python-graphviz-feedstock |
206 | 211 | .. _conda-forge-graphviz: https://anaconda.org/conda-forge/graphviz |
207 | 212 | .. _conda-forge-graphviz-feedstock: https://github.com/conda-forge/graphviz-feedstock |
213 | ||
214 | .. _user guide: https://graphviz.readthedocs.io/en/stable/manual.html | |
208 | 215 | |
209 | 216 | .. _pygraphviz: https://pypi.org/project/pygraphviz/ |
210 | 217 | .. _graphviz-python: https://pypi.org/project/graphviz-python/ |
249 | 256 | .. |Binder-stable| image:: https://img.shields.io/badge/launch-binder%20(stable)-579ACA.svg?logo=data:image/png;base64,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 |
250 | 257 | :target: https://mybinder.org/v2/gh/xflr6/graphviz/stable |
251 | 258 | :alt: Binder (stable) |
252 | ||
253 |
30 | 30 | docs/jupyter_notebooks.rst |
31 | 31 | docs/license.rst |
32 | 32 | docs/manual.rst |
33 | docs/neato_no_op.rst | |
33 | 34 | docs/node_ports.rst |
34 | 35 | docs/notebooks.rst |
35 | 36 | docs/piped_output.rst |
62 | 63 | docs/_static/qtconsole.png |
63 | 64 | docs/_static/rank_same.svg |
64 | 65 | docs/_static/round-table.svg |
66 | docs/_static/splines.svg | |
65 | 67 | docs/_static/structs.svg |
66 | 68 | docs/_static/structs_revisited.svg |
67 | 69 | docs/_static/traffic_lights.svg |
6 | 6 | twine |
7 | 7 | |
8 | 8 | [docs] |
9 | sphinx>=1.8 | |
9 | sphinx>=5 | |
10 | 10 | sphinx-autodoc-typehints |
11 | 11 | sphinx-rtd-theme |
12 | 12 | |
13 | 13 | [test] |
14 | pytest>=6 | |
14 | pytest>=7 | |
15 | 15 | pytest-mock>=3 |
16 | 16 | mock>=4 |
17 | 17 | pytest-cov |
2 | 2 | |
3 | 3 | """Run the tests with https://pytest.org.""" |
4 | 4 | |
5 | import doctest | |
6 | 5 | import pathlib |
7 | 6 | import platform |
8 | 7 | import sys |
9 | from unittest import mock | |
8 | ||
9 | import pytest | |
10 | 10 | |
11 | 11 | SELF = pathlib.Path(__file__) |
12 | ||
13 | NO_EXE = doctest.register_optionflag('NO_EXE') | |
14 | 12 | |
15 | 13 | ARGS = [#'--skip-exe', |
16 | 14 | #'--only-exe', |
26 | 24 | ARGS += ['--capture=sys', '--color=no'] |
27 | 25 | |
28 | 26 | |
29 | class NoExeChecker(doctest.OutputChecker): | |
30 | ||
31 | def check_output(self, want, got, optionflags, *args, **kwargs) -> bool: | |
32 | if optionflags & NO_EXE: | |
33 | return True | |
34 | return super().check_output(want, got, optionflags, *args, **kwargs) | |
35 | ||
36 | ||
37 | mock.patch.object(doctest, 'OutputChecker', new=NoExeChecker).start() | |
38 | import pytest # noqa: E402 | |
39 | ||
40 | ||
41 | 27 | print('run', [SELF.name] + sys.argv[1:]) |
42 | 28 | args = ARGS + sys.argv[1:] |
43 | 29 |
2 | 2 | |
3 | 3 | setup( |
4 | 4 | name='graphviz', |
5 | version='0.19.1', | |
5 | version='0.20.1', | |
6 | 6 | author='Sebastian Bank', |
7 | 7 | author_email='sebastian.bank@uni-leipzig.de', |
8 | 8 | description='Simple Python interface for Graphviz', |
18 | 18 | }, |
19 | 19 | packages=find_packages(), |
20 | 20 | platforms='any', |
21 | python_requires='>=3.6', | |
21 | python_requires='>=3.7', | |
22 | 22 | extras_require={ |
23 | 23 | 'dev': ['tox>=3', 'flake8', 'pep8-naming', 'wheel', 'twine'], |
24 | 'test': ['pytest>=6', | |
24 | 'test': ['pytest>=7', | |
25 | 25 | 'pytest-mock>=3', 'mock>=4', |
26 | 26 | 'pytest-cov', 'coverage'], |
27 | 'docs': ['sphinx>=1.8', 'sphinx-autodoc-typehints', 'sphinx-rtd-theme'], | |
27 | 'docs': ['sphinx>=5', 'sphinx-autodoc-typehints', 'sphinx-rtd-theme'], | |
28 | 28 | }, |
29 | 29 | long_description=pathlib.Path('README.rst').read_text(encoding='utf-8'), |
30 | 30 | classifiers=[ |
34 | 34 | 'License :: OSI Approved :: MIT License', |
35 | 35 | 'Operating System :: OS Independent', |
36 | 36 | 'Programming Language :: Python :: 3', |
37 | 'Programming Language :: Python :: 3.6', | |
38 | 37 | 'Programming Language :: Python :: 3.7', |
39 | 38 | 'Programming Language :: Python :: 3.8', |
40 | 39 | 'Programming Language :: Python :: 3.9', |
53 | 53 | mock_run.assert_called_once_with([_common.EXPECTED_DOT_BINARY, |
54 | 54 | '-Kdot', '-Tpng'], |
55 | 55 | input=b'nongraph', |
56 | stdout=subprocess.PIPE, | |
57 | stderr=subprocess.PIPE, | |
56 | capture_output=True, | |
58 | 57 | startupinfo=_common.StartupinfoMatcher()) |
59 | 58 | if not quiet: |
60 | 59 | mock_out.decode.assert_not_called() |
96 | 95 | mock_run.assert_called_once_with([_common.EXPECTED_DOT_BINARY, |
97 | 96 | '-Kdot', '-Tpng'], |
98 | 97 | input=b'nongraph', |
99 | stdout=subprocess.PIPE, | |
100 | stderr=subprocess.PIPE, | |
98 | capture_output=True, | |
101 | 99 | startupinfo=_common.StartupinfoMatcher()) |
102 | 100 | assert capsys.readouterr() == ('', '' if quiet else 'stderr') |
103 | 101 | |
115 | 113 | mock_run.assert_called_once_with([_common.EXPECTED_DOT_BINARY, '-Kdot', '-Tpng'], |
116 | 114 | input='nongraph', |
117 | 115 | encoding=encoding, |
118 | stdout=subprocess.PIPE, | |
119 | stderr=subprocess.PIPE, | |
116 | capture_output=True, | |
120 | 117 | startupinfo=_common.StartupinfoMatcher()) |
121 | 118 | assert capsys.readouterr() == ('', '' if quiet else 'stderr') |
122 | 119 |
118 | 118 | if directory is not None: |
119 | 119 | filepath = os.path.join(directory, filepath) |
120 | 120 | |
121 | result = graphviz.render('dot', 'pdf', filepath, quiet=quiet) | |
121 | result = graphviz.render('dot', 'pdf', filepath, | |
122 | neato_no_op=True, | |
123 | quiet=quiet) | |
122 | 124 | |
123 | 125 | assert result == f'{filepath}.pdf' |
124 | 126 | |
125 | 127 | mock_run.assert_called_once_with([_common.EXPECTED_DOT_BINARY, |
126 | '-Kdot', '-Tpdf', '-O', 'nonfilepath'], | |
127 | stdout=subprocess.PIPE, | |
128 | stderr=subprocess.PIPE, | |
128 | '-Kdot', '-Tpdf', | |
129 | '-n1', | |
130 | '-O', 'nonfilepath'], | |
131 | capture_output=True, | |
129 | 132 | cwd=_tools.promote_pathlike(directory), |
130 | 133 | startupinfo=_common.StartupinfoMatcher()) |
131 | 134 | assert capsys.readouterr() == ('', '' if quiet else 'stderr') |
38 | 38 | mock_run.assert_called_once_with([_common.EXPECTED_UNFLATTEN_BINARY, |
39 | 39 | '-l', '10', '-f', '-c', '23'], |
40 | 40 | input='nonsource', |
41 | stdout=subprocess.PIPE, | |
42 | stderr=subprocess.PIPE, | |
41 | capture_output=True, | |
43 | 42 | startupinfo=_common.StartupinfoMatcher(), |
44 | 43 | encoding='utf-8') |
45 | 44 | assert capsys.readouterr() == ('', '') |
29 | 29 | return cls('graph { spam -- \\ }') |
30 | 30 | else: |
31 | 31 | invalid_dot = cls() |
32 | invalid_dot.edge('spam', '\\') | |
32 | with pytest.warns(graphviz.DotSyntaxWarning, match=r'syntax error'): | |
33 | invalid_dot.edge('spam', '\\') | |
33 | 34 | return invalid_dot |
34 | 35 | |
35 | 36 | |
115 | 116 | mock_render.assert_called_once_with(dot.engine, dot.format, |
116 | 117 | mock_save.return_value, |
117 | 118 | renderer=None, formatter=None, |
119 | neato_no_op=None, | |
118 | 120 | outfile=None, |
119 | 121 | raise_if_result_exists=False, |
120 | 122 | overwrite_filepath=False, |
142 | 144 | mock_render.assert_called_once_with(dot.engine, dot.format, |
143 | 145 | mock_save.return_value, |
144 | 146 | renderer=None, formatter=None, |
147 | neato_no_op=None, | |
145 | 148 | outfile=pathlib.Path(outfile), |
146 | 149 | raise_if_result_exists=True, |
147 | 150 | overwrite_filepath=True, |
155 | 158 | quiet, cls, |
156 | 159 | filename='format.gv', format='jpg', |
157 | 160 | renderer='cairo', formatter='core'): |
158 | args = [''] if cls.__name__ == 'Source' else [] | |
159 | dot = cls(*args, filename=filename, format=format, | |
161 | dot = cls(*[''] if cls.__name__ == 'Source' else [], | |
162 | filename=filename, format=format, | |
160 | 163 | renderer=renderer, formatter=formatter) |
161 | 164 | |
162 | 165 | assert dot.format == format |
170 | 173 | mock_save.assert_called_once_with(None, None, skip_existing=None) |
171 | 174 | mock_render.assert_called_once_with('dot', format, mock_save.return_value, |
172 | 175 | renderer=renderer, formatter=formatter, |
176 | neato_no_op=None, | |
177 | outfile=None, | |
178 | raise_if_result_exists=False, | |
179 | overwrite_filepath=False, | |
180 | quiet=quiet) | |
181 | ||
182 | ||
183 | @pytest.mark.parametrize( | |
184 | 'neato_no_op', [None, False, True, 0, 1, 2]) | |
185 | def test_neato_no_op_mocked(mocker, mock_render, | |
186 | quiet, cls, neato_no_op, | |
187 | engine='neato', | |
188 | filename='neato_no_op.gv', format='svg'): | |
189 | dot = cls(*[''] if cls.__name__ == 'Source' else [], | |
190 | engine=engine, | |
191 | filename=filename, format=format) | |
192 | ||
193 | mock_save = mocker.patch.object(dot, 'save', autospec=True) | |
194 | ||
195 | assert dot.render(neato_no_op=neato_no_op, | |
196 | quiet=quiet) is mock_render.return_value | |
197 | ||
198 | mock_save.assert_called_once_with(None, None, skip_existing=None) | |
199 | mock_render.assert_called_once_with(engine, format, mock_save.return_value, | |
200 | renderer=None, formatter=None, | |
201 | neato_no_op=neato_no_op, | |
173 | 202 | outfile=None, |
174 | 203 | raise_if_result_exists=False, |
175 | 204 | overwrite_filepath=False, |
205 | 234 | expected_args = ['dot', 'pdf', mocker.ANY] |
206 | 235 | expected_kwargs = {'quiet': quiet, |
207 | 236 | 'renderer': None, |
208 | 'formatter': None} | |
237 | 'formatter': None, | |
238 | 'neato_no_op': None} | |
209 | 239 | |
210 | 240 | if encoding == input_encoding: |
211 | 241 | assert result is mock_pipe_lines_string.return_value |
231 | 261 | |
232 | 262 | mock_pipe_lines.assert_called_once_with(dot.engine, format_, mocker.ANY, |
233 | 263 | renderer=None, formatter=None, |
264 | neato_no_op=None, | |
234 | 265 | input_encoding='utf-8', |
235 | 266 | quiet=False) |
236 | 267 | _, _, data = mock_pipe_lines.call_args.args |
291 | 322 | input_encoding=input_encoding, |
292 | 323 | quiet=False, |
293 | 324 | renderer=None, |
294 | formatter=None) | |
325 | formatter=None, | |
326 | neato_no_op=None) | |
295 | 327 | |
296 | 328 | |
297 | 329 | def test_repr_mimebundle_image_svg_xml_mocked(mocker, dot): |
21 | 21 | assert cls().filename == f'{cls.__name__}.gv' |
22 | 22 | assert type('Subcls', (cls,), {})().filename == 'Subcls.gv' |
23 | 23 | assert cls('spam').filename == 'spam.gv' |
24 | ||
25 | ||
26 | @pytest.mark.parametrize( | |
27 | 'cls, body_lines, expected', | |
28 | [(graphviz.Graph, ['\tspam -- {\n', '\t\teggs, ham\n', '\t}\n'], | |
29 | 'graph {\n\tspam -- {\n\t\teggs, ham\n\t}\n}\n'), | |
30 | (graphviz.Digraph, ['\tspam -> {\n', '\t\teggs, ham\n', '\t}\n'], | |
31 | 'digraph {\n\tspam -> {\n\t\teggs, ham\n\t}\n}\n')], | |
32 | ids=lambda p: getattr(p, '__name__', '...')) | |
33 | def test_init_body(cls, body_lines, expected): | |
34 | dot = cls(body=iter(body_lines)) | |
35 | assert dot.source == expected | |
24 | 36 | |
25 | 37 | |
26 | 38 | @pytest.mark.exe |
0 | 0 | import functools |
1 | 1 | import os |
2 | import warnings | |
2 | 3 | |
3 | 4 | import pytest |
4 | 5 | |
43 | 44 | def func(first, second, third=None, **kwargs): |
44 | 45 | pass |
45 | 46 | |
46 | with pytest.warns(None) as captured: | |
47 | with warnings.catch_warnings(): | |
48 | warnings.simplefilter('error') | |
47 | 49 | func('first', 'second', third='third', extra='extra') |
48 | 50 | |
49 | assert not captured | |
50 | ||
51 | with pytest.warns(category, match=match) as captured: | |
52 | func('first', 'second', 'third', extra='extra') | |
53 | ||
54 | assert bool(captured) == bool(category is not None) | |
51 | if category is not None: | |
52 | with pytest.warns(category, match=match): | |
53 | func('first', 'second', 'third', extra='extra') | |
54 | else: | |
55 | with warnings.catch_warnings(): | |
56 | warnings.simplefilter('error') | |
57 | func('first', 'second', 'third', extra='extra') |