diff --git a/CHANGES.txt b/CHANGES.txt index 4609c97a93..80b920cd58 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -5,7 +5,9 @@ Changelog Version 0.14.1 (in development) ------------------------------- - +Document the colon-separated ``node[:port[:compass]]`` format used for ``tail`` +and ``head`` points in the ``edge()``- and ``edges()``-methods' (PR Michał +Góral). Version 0.14 diff --git a/docs/examples.rst b/docs/examples.rst index 310869ad00..1d87f08cf2 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -94,6 +94,8 @@ structs_revisited.py :align: center +.. _btree.py: + btree.py -------- diff --git a/docs/manual.rst b/docs/manual.rst index f5a4a92035..9c5ca50c74 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -52,7 +52,7 @@ Their constructors allow to set the graph's :attr:`~.Graph.name`, the :attr:`~.Graph.comment` for the first source code line, etc. Add nodes and edges to the graph object using its :meth:`~.Graph.node` and -:meth:`~.Graph.edge` or :meth:`~.Graph.edges` methods: +:meth:`~.Graph.edge`- or :meth:`~.Graph.edges`-methods: .. code:: python @@ -210,27 +210,6 @@ After creation, they can be edited on the graph object: .. _attributes: -Port and Compass Points ------------------------ - -:meth:`~.Graph.edge` accepts optional port and compass attributes which are -separated with colons in the following form: ``node:port:nw``. When present, -they are converted to native DOT equivalents and modify the edge placement -between two nodes. - -.. code:: python - - >>> dot.edge('node1:port1', 'node2:port5:nw') - >>> dot.edge('node3:port2:_', 'node4:port4:s') - -If you need to use a colon in a node's label, you can declare a node with -:meth:`~.Graph.node` first: - -.. code:: python - >>> dot.node('A', 'node:with:colon') - >>> dot.node('B', 'another:node:with:colon') - >>> dot.edge('A', 'B') - Attributes ---------- @@ -282,6 +261,39 @@ key-value pairs targeting the current (sub-)graph (e.g. for ``rankdir``, :align: center +.. _ports: + +Node ports & compass +-------------------- + +The :meth:`~.Graph.edge`- and :meth:`~.Graph.edges`-methods use the +colon-separated format ``node[:port[:compass]]`` for ``tail`` and ``head`` +nodes. This allows to specify an optional node ``port`` plus an optional +``compass`` point the edge should aim at for the given tail or head node +(:ref:`example `). + +As colons are used to indicate ``port`` and ``compass``, node names with +literal colon(s) (``:``) are not supported. Note that there is no such +restriction for the ``label`` argument, so you can work around by choosing a +colon-free ``name`` together with the wanted ``label``: + +.. code:: python + + >>> cpp = Digraph('C++') + + >>> cpp.node('A', 'std::string') + >>> cpp.node('B', '"spam"') + + >>> cpp.edge('A', 'B') + + >>> print(cpp.source) # doctest: +NORMALIZE_WHITESPACE + digraph "C++" { + A [label="std::string"] + B [label="\"spam\""] + A -> B + } + + Backslash escapes ----------------- @@ -466,7 +478,7 @@ Custom DOT statements To add arbitrary statements to the created DOT_ source, use the :attr:`~.Graph.body` attribute of the :class:`.Graph` or :class:`.Digraph` object. It holds the verbatim list of lines to be written to the source file. -Use its ``append()`` or ``extend()`` method: +Use its ``append()``- or ``extend()``-method: .. code:: python diff --git a/graphviz/dot.py b/graphviz/dot.py index e19a19aa38..8b2acd362f 100644 --- a/graphviz/dot.py +++ b/graphviz/dot.py @@ -133,14 +133,19 @@ def node(self, name, label=None, _attributes=None, **attrs): self.body.append(line) def edge(self, tail_name, head_name, label=None, _attributes=None, **attrs): - """Create an edge between two nodes. Accepts colon-separated strings - which are splitted into node, port and compass. + """Create an edge between two nodes. Args: - tail_name: Start node identifier. - head_name: End node identifier. + tail_name: Start node identifier (format: ``node[:port[:compass]]``). + head_name: End node identifier (format: ``node[:port[:compass]]``). label: Caption to be displayed near the edge. attrs: Any additional edge attributes (must be strings). + + Note: + The ``tail_name`` and ``head_name`` strings are separated by + (optional) colon(s) into ``node`` name, ``port`` name, and + ``compass`` (e.g. ``sw``). + See :ref:`details in the User Guide `. """ tail_name = self._quote_edge(tail_name) head_name = self._quote_edge(head_name) @@ -152,7 +157,14 @@ def edges(self, tail_head_iter): """Create a bunch of edges. Args: - tail_head_iter: Iterable of ``(tail_name, head_name)`` pairs. + tail_head_iter: Iterable of ``(tail_name, head_name)`` pairs (format:``node[:port[:compass]]``). + + + Note: + The ``tail_name`` and ``head_name`` strings are separated by + (optional) colon(s) into ``node`` name, ``port`` name, and + ``compass`` (e.g. ``sw``). + See :ref:`details in the User Guide `. """ edge = self._edge_plain quote = self._quote_edge @@ -199,7 +211,7 @@ def subgraph(self, graph=None, name=None, comment=None, See the :ref:`usage examples in the User Guide `. - .. note:: + Note: If the ``name`` of the subgraph begins with ``'cluster'`` (all lowercase) the layout engine will treat it as a special cluster subgraph. """ @@ -256,7 +268,7 @@ class Graph(Dot): strict (bool): Rendering should merge multi-edges. Note: - All parameters are optional and can be changed under their + All parameters are `optional` and can be changed under their corresponding attribute name after instance creation. """