Developer Guide

Setup Development Environment

  1. Install pip3 and tox:

    wget https://bootstrap.pypa.io/get-pip.py
    sudo python3 get-pip.py
    sudo pip3 install tox
    
  2. Configure git pre-commit hook:

    sudo pip3 install flake8 pep8-naming
    flake8 --install-hook
    git config flake8.strict true
    

Building Documentation

tox -e doc

Output will be available at .tox/doc/tmp/html. It is recommended to install the webdev package:

sudo pip3 install webdev

So a development web server can serve any location like this:

$ webdev .tox/doc/tmp/html

Running Test Suite

tox -e py27,py34

Running Coverage

tox -e coverage

plantweb

Plantweb module entry point.

Submodules

plantweb.__main__

plantweb executable module entry point.

plantweb.args

Argument management module.

Functions

plantweb.args.parse_args(argv=None)

Argument parsing routine.

Parameters:argv – A list of argument strings.
Rtype argv:list
Returns:A parsed and verified arguments namespace.
Return type:argparse.Namespace

plantweb.defaults

Plantweb main rendering module.

Functions

plantweb.defaults.read_defaults(cached=True)

Get the defaults values.

Parameters:cached (bool) – Read cached default values or determine them from the list of providers. See DEFAULTS_PROVIDERS.
Returns:A dictionary like DEFAULT_CONFIG with the user defaults.
Return type:dict

Variables

plantweb.defaults.DEFAULT_CONFIG

Default configuration for plantweb.

Note

The default engine will be used only when the engine was unset and it was unable to be auto-determined.

To set a different default configuration create a JSON file .plantwebrc in your git repository root or in your home, as defined in DEFAULTS_PROVIDERS.

{'cache_dir': '~/.cache/plantweb',
 'engine': 'plantuml',
 'format': 'svg',
 'server': 'http://plantuml.com/plantuml/',
 'use_cache': True}
plantweb.defaults.DEFAULTS_PROVIDERS

List of defaults providers ordered by read priority.

Last items will be processed last and thus will override previous values.

Available providers are:

git://
Will fetch the repository root from current working directory using git’s git rev-parse --show-toplevel and then read the specified file from that path.
file://
Will read the file specified. User expansion ~ is supported.
python://

Will import the given variable or function:

  • If a function, it will be executed without arguments and its result will be used.
  • If a variable, it must be a dictionary similar to DEFAULT_CONFIG.
['python://plantweb.defaults.DEFAULT_CONFIG',
 'file://~/.plantwebrc',
 'git://.plantwebrc']

plantweb.directive

Sphinx directives for rendering PlantUML, Graphviz and Ditaa using Plantweb.

Functions

  • setup(): Setup function that makes this module a Sphinx extension.
  • builder_inited_handler(): We use this event handler to grab user defaults for Plantweb and use them
  • defaults_provider(): Defaults provider that allows to register Sphinx user defaults.
plantweb.directive.setup(app)

Setup function that makes this module a Sphinx extension.

See http://www.sphinx-doc.org/en/stable/extdev/appapi.html#sphinx.application.Sphinx.add_config_value

plantweb.directive.builder_inited_handler(app)

We use this event handler to grab user defaults for Plantweb and use them in Plantweb rendering.

See https://plantweb.readthedocs.io/index.html#overriding-defaults

This is the handler of the ‘builder-inited’ event emitted by Sphinx.

Emitted when the builder object has been created. It is available as app.builder.

See http://www.sphinx-doc.org/en/stable/extdev/appapi.html#event-builder-inited

plantweb.directive.defaults_provider()

Defaults provider that allows to register Sphinx user defaults.

This dummy defaults provider just returns it’s attribute overrides if it exists.

Returns:The dictionary of the form DEFAULT_CONFIG.
Return type:dict

Classes

class plantweb.directive.Plantweb(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine)

FIXME: Document.

Inheritance

Inheritance diagram of Plantweb

class plantweb.directive.UmlDirective(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine)

Specialized uml directive for Plantweb Plantweb engine.

See Plantweb.

Inheritance

Inheritance diagram of UmlDirective

class plantweb.directive.GraphDirective(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine)

Specialized graph directive for Plantweb graphviz engine.

See Plantweb.

Inheritance

Inheritance diagram of GraphDirective

class plantweb.directive.DiagramDirective(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine)

Specialized diagram directive for Plantweb ditaa engine.

See Plantweb.

Inheritance

Inheritance diagram of DiagramDirective

plantweb.main

Application entry point module.

Functions

  • main(): Application main function.
plantweb.main.main(args)

Application main function.

Parameters:args (argparse.Namespace) – An arguments namespace.
Returns:Exit code.
Return type:int

plantweb.plantuml

Plantuml encoding module.

Functions

plantweb.plantuml.plantuml(server, extension, content)

Call the PlantUML server.

Parameters:
  • server (str) – Base URL for the server.
  • extension (str) – File format / extension to use for the request.
  • content (str) – Content to render.
Returns:

Response of the request.

Return type:

str

plantweb.render

Plantweb main rendering module.

Functions

  • render_file(): Render given PlantUML, Graphviz or DITAA file.
  • render(): Render given PlantUML, Graphviz or DITAA content.
  • render_cached(): Render given content in the PlantUML server or fetch it from cache.
  • determine_engine(): Determine the engine used in the given content.
plantweb.render.render_file(infile, outfile=None, renderopts=None, cacheopts=None)

Render given PlantUML, Graphviz or DITAA file.

Parameters:
  • infile (str) – Path to source file to render.
  • outfile (str) – Path to output file. If None, the filename will be auto-determined and saved to the current working directory.
  • renderopts (dict) – Rendering options (engine, format and server) as in render().
  • cacheopts (dict) – Caching options (use_cache and cache_dir) as in render().
Returns:

Path to output file.

Return type:

str

plantweb.render.render(content, engine=None, format=None, server=None, cacheopts=None)

Render given PlantUML, Graphviz or DITAA content.

Parameters:
  • content (str) – Content to render.
  • engine (str) – Engine to use to render the content. One of 'plantuml', 'graphviz' or 'ditaa'. If None, the engine will be auto-determined by looking into the content for the @startxxxx tags, and if unable to be auto-determined the default engine will be used.
  • format (str) – Format of the rendered content. Raster png or vector svg. Please note that engine ditaa can only render to png. If None, the default formatwill always be selected unless the engine doesn’t supports it.
  • server (str) – URL to PlantUML server. This will passed as is to render_cached(). If None the default server URL will be used.
Returns:

A tuple of (output, format, engine, sha) with the bytes of the rendered output, a string with the name of the output format, a string with the name of the engine used or detected and a string of the sha256 for identifying the cache file.

Return type:

tuple

plantweb.render.render_cached(server, format, content, use_cache=None, cache_dir=None)

Render given content in the PlantUML server or fetch it from cache.

Parameters:
  • server (str) – URL to PlantUML server.
  • format (str) – File format to render the content. One of the supported by the PlantUML server (svg or png).
  • content (str) – Content to render with mandatory @startxxx tags.
  • use_cache (bool) – Use local cache to avoid requesting the server for already rendered diagrams. If None, the default value will be used.
  • cache_dir (str) – Directory to store the cached diagrams. If None the default value will be used.
Returns:

A tuple of (content, sha) with the bytes of the rendered content and a sha256 hash string identifying the content.

Return type:

tuple

plantweb.render.determine_engine(content)

Determine the engine used in the given content.

The engine is determined by the @startXXX used at the beginning of the file. Possible values are:

@startuml --> plantuml
@startdot --> graphviz
@startditaa --> ditaa
Parameters:content (str) – Content to analyze.
Returns:The name of the engine found, or None.
Return type:str

Variables

plantweb.render.WRAP_STR

Map between the name of the engine and the wrap string used in the @startXXX directive.

{'ditaa': 'ditaa', 'graphviz': 'dot', 'plantuml': 'uml'}

Plantweb

_images/logo.png

Plantweb is a project that provides a command line interface, Sphinx directives and an API that allows to render powerful plain text UML diagrams, ASCII diagrams and complex graphs.

It is a Python client for the PlantUML server and thus it can render PlantUML, Graphviz and Ditaa diagrams without the need to install them.

Check out the Examples Gallery.

Plantweb features a local cache that prevents requesting the server for previously rendered diagrams, speeding up building documentation with lots of diagrams.

Finally, being pure Python, non-local rendering, Plantweb is an excellent way to display and render PlantUML, Graphviz and Ditaa diagrams in ReadTheDocs published documentation.

In particular, Ditaa rendering is particularly usefull when using ASCII drawing tools like asciiflow.

Installation

sudo pip3 install plantweb

Usage

Command Line Interface

If the content of your file is wrapped by @startxxx, @endxxx then Plantweb is capable of determining the engine to use.

Options are:

Opening Closure Engine
@startuml @enduml plantuml
@startdot @enddot graphviz
@startditaa @endditaa ditaa

For example, the following Graphviz file mydotfile.dot:

@startdot
digraph one_node_graph {
   node1 -> node2 -> node3
}
@enddot

Can be rendered with:

user@host:~$ plantweb mydotfile.dot

Note

File extensions are irrelevant for Plantweb.

If for some reason your files lack the @startxxx/@endxxx wrapper you can still render the file by specifying the engine:

user@host:~$ plantweb --engine=graphviz unwrappeddotfile.dot

Complete options:

user@host:~$ plantweb --help
usage: plantweb [-h] [-v] [--version]
                [--engine {auto,plantuml,graphviz,ditaa}]
                [--format {auto,svg,png}] [--server SERVER] [--no-cache]
                [--cache-dir CACHE_DIR]
                sources [sources ...]

Python client for the PlantUML server

positional arguments:
  sources               source files to render

optional arguments:
  -h, --help            show this help message and exit
  -v, --verbose         increase verbosity level
  --version             show program's version number and exit
  --engine {auto,plantuml,graphviz,ditaa}
                        engine to use to render diagram
  --format {auto,svg,png}
                        diagram export format
  --server SERVER       server to use for rendering
  --no-cache            do not use cache
  --cache-dir CACHE_DIR
                        directory to store cached renders

Sphinx Directives

New in version 0.4.0.

Plantweb provides 3 Sphinx directives for rendering diagrams:

.. uml::

Allows to render the content using the PlantUML engine.

Warning

This directive overrides the one provided by sphinxcontrib.plantuml.

.. graph::

Allows to render the content using the Graphviz engine.

Warning

This directive overrides the one provided by sphinx.ext.graphviz.

.. diagram::
Allows to render the content using the Ditaa engine.

Note

When using the directives it is NOT recommended nor required to use the @startxxx / @endxxx tags.

For example:

.. uml::

   Alice -> Bob: Authentication Request
   Bob --> Alice: Authentication Response

   Alice -> Bob: Another authentication Request
   Alice <-- Bob: another authentication Response

The above will render:

_images/45d09d0a9c53ff7945fe6e95db2d28a9b54a460ea9c3057d70f466b4d50b774f.svg

See also

Check out the Examples Gallery.

New in version 1.0.0.

Directives also support specifying a path to a file to load the content.

For example:

.. uml:: my_uml_diagram.uml

The above will load the file my_uml_diagram.uml with the content to be rendered.

You may specify a relative path from the current document or you may specify an absolute path from where the conf.py like this:

.. uml:: /diagrams/my_uml_diagram.uml

The above will load the file from the Sphinx documentation root.

Options

alt: text
Alternate text: a short description of the image, displayed by applications that cannot display images, when the user over the image with the cursor or spoken by applications for visually impaired users.
align: “left”, “center”, or “right”

The alignment of the image. It control an image’s horizontal alignment, allowing the image to float and have the text flow around it.

Warning

This behavior could be changed by your theme.

target: text (URI or reference name)
Makes the image into a hyperlink reference (“clickable”). The option argument may be a URI (relative or absolute), or a reference name with underscore suffix (e.g. name_).

For example:

.. uml::
   :alt: This is a nice UML diagram. Indeed.
   :align: left
   :target: #options

   actor Foo1
   boundary Foo2
   control Foo3
   entity Foo4
   database Foo5
   Foo1 -> Foo2 : To boundary
   Foo1 -> Foo3 : To control
   Foo1 -> Foo4 : To entity
   Foo1 -> Foo5 : To database

Render as:

This is a nice UML diagram. Indeed.

Warning

Plantweb directives doesn’t have any height, width or scale options. In this age of responsive design there shouldn’t be the need to define presentational values in the content. Also, being diagrams, you should always maximize viewing space.

If your images overflow, override your theme or use a theme that already supports responsive images:

/* Responsive images */
object[type="image/svg+xml"], img {
    max-width: 100%;
    height: auto;
}

Sphinx Setup

To enable the directives add 'plantweb.directive' to your extensions in your Sphinx’s conf.py:

extensions = [
    # ... More extensions,
    'plantweb.directive'
]

If you want to configure the extension you can create the variable plantweb_defaults in your Sphinx’s conf.py:

# Plantweb configuration
plantweb_defaults = {
    'server': 'http://myserver.com/plantuml/'
}

Please note that the above configuration will have the higher priority as explained in Overriding Defaults. Nevertheless the defaults resolution mechanism is still considered, that is, the .plantwebrc files will still override other keys if present.

Python API

There are 2 main functions, both Python 2.7 and 3.5 compatible:

  1. render() allows to render content directly.

    from plantweb.render import render
    
    
    CONTENT = """
    actor Foo1
    boundary Foo2
    control Foo3
    entity Foo4
    database Foo5
    Foo1 -> Foo2 : To boundary
    Foo1 -> Foo3 : To control
    Foo1 -> Foo4 : To entity
    Foo1 -> Foo5 : To database
    """
    
    
    if __name__ == '__main__':
    
        print('==> INPUT:')
        print(CONTENT)
    
        output = render(
            CONTENT,
            engine='plantuml',
            format='svg',
            cacheopts={
                'use_cache': False
            }
        )
    
        print('==> OUTPUT:')
        print(output)
    
  2. render_file() allows to render files.

    from plantweb.render import render_file
    
    
    CONTENT = """
    digraph finite_state_machine {
        rankdir=LR;
        size="8,5"
        node [shape = doublecircle]; LR_0 LR_3 LR_4 LR_8;
        node [shape = circle];
        LR_0 -> LR_2 [ label = "SS(B)" ];
        LR_0 -> LR_1 [ label = "SS(S)" ];
        LR_1 -> LR_3 [ label = "S($end)" ];
        LR_2 -> LR_6 [ label = "SS(b)" ];
        LR_2 -> LR_5 [ label = "SS(a)" ];
        LR_2 -> LR_4 [ label = "S(A)" ];
        LR_5 -> LR_7 [ label = "S(b)" ];
        LR_5 -> LR_5 [ label = "S(a)" ];
        LR_6 -> LR_6 [ label = "S(b)" ];
        LR_6 -> LR_5 [ label = "S(a)" ];
        LR_7 -> LR_8 [ label = "S(b)" ];
        LR_7 -> LR_5 [ label = "S(a)" ];
        LR_8 -> LR_6 [ label = "S(b)" ];
        LR_8 -> LR_5 [ label = "S(a)" ];
    }
    """
    
    
    if __name__ == '__main__':
    
        infile = 'mygraph.dot'
        with open(infile, 'wb') as fd:
            fd.write(CONTENT.encode('utf-8'))
    
        print('==> INPUT FILE:')
        print(infile)
    
        outfile = render_file(
            infile,
            renderopts={
                'engine': 'graphviz',
                'format': 'png'
            },
            cacheopts={
                'use_cache': False
            }
        )
    
        print('==> OUTPUT FILE:')
        print(outfile)
    

Overriding Defaults

New in version 0.3.0.

The defaults defined in DEFAULT_CONFIG will be used unless overridden by the user.

To set a different default configuration create a JSON file .plantwebrc in your git repository root or in your home, as defined in DEFAULTS_PROVIDERS.

For example:

{
    "server": "http://mydomain.com/plantuml/",
    "cache_dir": "~/.cache/plantweb",
    "engine": "plantuml",
    "format": "svg",
    "use_cache": true
}

See also

PlantUML Server.

PlantUML Server

If you require:

  • Guaranteed uptime.
  • To render confidential diagrams.
  • To speed up rendering in your intranet.
  • Or you simply want to be nice and unload the public server.

Please consider running a PlantUML server in your local network or private server. The easiest way is to do it is using the official PlantUML Docker image:

docker pull plantuml/plantuml-server
docker run --detach --publish 8080:8080 plantuml/plantuml-server

For more information about the PlantUML server visit:

The public PlantUML server used by Plantweb by default is run by a group of volunteers for pure love.

Please consider donating to the project through Paypal, Patreon or Flattr.

TODO

  • We should be able to monkey patch sphinx.ext.inheritance_diagram that also uses Graphviz to use Plantweb.

License

Copyright (C) 2016-2017 Carlos Jenkins

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.

Logo derived from work by VisciousSpeed under Public Domain.