sphinxcontrib-dd 0.1.7
Sphinx extension for Data Dictionary and Database Diagram
License: MIT
Keywords: sphinx sphinxcontrib data dictionary database diagram

################
sphinxcontrib.dd
################

Sphinx extension for Data Dictionary and Database Diagram.

The syntax is using extended `Swagger <http://swagger.io/specification>`__
format.

Database diagram will be generated by `GraphViz <http://www.graphviz.org/>`__.
Because its dependency to GraphViz,
please remember to properly setup
`GraphViz extension <http://www.sphinx-doc.org/en/stable/ext/graphviz.html>`__
first.


Installation
============

::

  > pip install sphinxcontrib-dd

Setup extension in ``conf.py`` file.

::

  extensions = ['sphinxcontrib.dd']


Schema
======

- definitions
- tables
- relationships


definitions
-----------

This is definitions as specified by Swagger
`here <http://swagger.io/specification/#definitionsObject>`__.

Example:

::

  definitions:
    Identity:
      type: integer
      format: int64
      minimum: 1

    User:
      properties:
        id:
          $ref: '#/definitions/Identity'
        name:
          type: nvarchar
          maxLength: 255

    Role:
      properties:
        id:
          $ref: '#/definitions/Identity'
        name:
          type: nvarchar
          maxLength: 255

    UserRole:
      properties:
        id:
          $ref: '#/definitions/Identity'
        user_id:
          $ref: '#/definitions/Identity'
        role_id:
          $ref: '#/definitions/Identity'


tables
------

===========  ====================================
Field Name   Description
===========  ====================================
name         Table name
description  Information about the table
columns      Should be simply $ref to definitions
===========  ====================================

Example:

::

  tables:
    User:
      name: users
      description: Table to stores user information.
      columns:
        $ref: '#/definitions/User'
    Role:
      name: roles
      description: Table to stores roles.
      columns:
        $ref: '#/definitions/Role'
    UserRole:
      name: users_roles
      description: Table to stores user roles.
      columns:
        $ref: '#/definitions/UserRole'


relationships
-------------

Determine the relationship between two entities.

=========  ===============================================
Symbol     Meaning
=========  ===============================================
\|         One
\|\|       One and only one
\|0 / 0\|  Zero or one
> / <      Many
>0 / 0<    Zero or many
>\| / \|<  One or many
=========  ===============================================

The syntax is ``<symbol>--<symbol>``.

Example:

::

  relationships:
    - User ||--0< UserRole
    - UserRole >0--|| Role


Usage
=====

This extension add two directives:

**.. database-diagram:: path [another_path]**
  Embed database diagram produced by GraphViz.

**.. data-dictionary:: path [another_path]**
  Embed data dictionary in table format.

path
  Path to yml file.

another_path
  Optional path to another yml file if split the spec.

  If you already have a swagger spec file used to define your REST API,
  you can reuse that file as is without modification by specifying it here.

  In the background I simply combine the two files into one.


Database Diagram
----------------

This extension is inspired by
`sphinx_erdiagram <https://pypi.python.org/pypi/sphinx_erdiagram>`__.

But unfortunately,
the extension has been heavily design for japanese language document.
So it looks rather ugly in english document due to the font it use.
And I also want to reuse the Swagger specification file used to define the REST
API.

Example:

::

  .. database-diagram:: example.yml

The ``example.yml`` file from
`here <https://github.com/julot/sphinxcontrib-dd/blob/master/example.yml>`__
will result in
`this <https://github.com/julot/sphinxcontrib-dd/blob/master/example.png>`__.

.. image:: https://image.ibb.co/ceDJMF/example.png

There are several options available to modify the look and feel of the diagram:

graph-fontname
  Set font family for graph label.
  Default to "Times-Roman" inherited from GraphViz.

graph-fontsize
  Point size or label.
  Default to 14 inherited from GraphViz.

graph-label
  Label of the graph.

graph-labeljust
  Alignment of graph label.
  Default to "centered" inherited from GraphViz.

  "l" and "r" for left- and right-justiﬁed labels, respectively.


graph-labelloc
  Location of graph label.
  Default to "top" inherited from GraphViz.

  "t" and "b" for top- and bottom-justiﬁed labels, respectively.


graph-margin
  Margin included in page, in inches.
  Default to 0.

graph-nodesep
  Separation between nodes, in inches.
  Default to 0.75 inch.

graph-ranksep
  Separation between ranks, in inches.
  Default to 0.75 inch.

node-fontname
  Set font family for graph label.
  Default to "Times-Roman" inherited from GraphViz.

node-fontsize
  Point size or label.
  Default to 14 inherited from GraphViz.

node-shape
  The shape of the node.
  Default to "box".

  More `here <http://www.graphviz.org/doc/info/shapes.html>`__.


node-style
  Style of of the node.
  Default to "rounded"

  More `here <http://www.graphviz.org/doc/info/shapes.html#d:style>`__.


root-samerank
  This option tells GraphViz that some node should be in the same rank.

  This options is in comma separated value format.

  Before everything else, please remember that:

  - Rank direction is from left to right.
  - The placement of the nodes is heavily influence by how you define the
    relationship.
  - To completely understand this options,
    you must understand how GraphViz's DiGraph works.

  Example:

  Relationship ``A ||--0< B`` will produce:

  ::

    +---+          +---+
    | A | ||----0< | B |
    +---+          +---+

  If you understand dot syntax,
  the relationship above is translated into ``A -> B``.

  While relationship ``B >0--|| A`` will produce:

  ::

    +---+          +---+
    | B | >0----|| | A |
    +---+          +---+

  Remember that rank direction is from left to right.

  But for relationship ``A ||--0< B`` with ``root-samerank`` option in the
  directive like this:

  ::

    .. database-diagram:: external.yml
      :root-samerank: A B

  It will forced the nodes to be in the same rank:

  ::

    +---+
    | A |
    +---+
      =
      |
      |
      0
      ^
    +---+
    | B |
    +---+

  To illustrate how the option works in comma separated value,
  imagine you have relationship in yaml file like this:

  ::

    relationships:
      - A ||--0< B
      - B >0--|| C
      - C ||--0< D

  Without ``root-samerank`` option,
  the nodes will be placed right next to each other resulting in one row.
  But if you set the option like this:

  ::

    .. database-diagram:: external.yml
      :root-samerank: A B, C D

  It will produces diagram like this:

  ::

    +---+
    | A |
    +---+
      =
      |
      |
      0
      ^
    +---+          +---+
    | B | >0----|| | C |
    +---+          +---+
                     =
                     |
                     |
                     0
                     ^
                   +---+
                   | D |
                   +---+

  Let's see how this works.

  First remember that this option is in comma separated value format.
  This means that the option will produce to values: ``A B`` and ``C D``.

  These two values force A and B to be in the same rank
  and C and D to be in the same rank too.
  But because we didn't specify B and C to be in the same rank,
  C node is placed in the right of the B node.

  If you want D node placed at the top of C node,
  you can simply change the relationship into ``D >0--|| C``.

Now, if you understand dot language you may already realized that ``graph-*``
and ``node-*`` options is just a shameless rip-off from GrahpViz attribute.
That's completely correct.
I'm too lazy to define my own options and conversions.
Beside I strongly believe that we should not reinvent the wheel,
unless absolutely necessary.
I even too lazy to define all the attributes asides from the one I need.
So please let me know if you need a currently unavailable attributes.
Or simply ask a pull request.
But please remember that some attributes may unavailable for modification.

Complete options is available `here <http://www.graphviz.org/content/attrs>`__.
But you may find the pdf version is easier to read,
though the html version is more comprehensive.

If you prefer the pdf version you can download it
`here <http://www.graphviz.org/pdf/dotguide.pdf>`__.
The options for node is available in appendixes A, edge in appendixes B and
graph in appendixes C.

The options can also be set as config specified in ``conf.py`` by prefixing it
with ``database_diagram_`` and change the ``-`` into ``_`` character.
The value in ``conf.py`` is applied to all directives but will be override by
options in the directive.

For example you want to set ``node-fontname`` to "Calibri" for all diagram.

In ``conf.py``:

::

  database_diagram_node_fontname = "Calibri"

You may set all the config value as string even for numeric value.

Please note that this options is not available as config:

- root-samerank

.. note::

  To change the image format you should directly change GraphViz options.

  ``graphviz_output_format = 'svg'``

  I want to change this to ``database_diagram_output_format`` but for now I
  just didn't know how to do that.
  If you knows how to do that,
  please let me know or add a pull request.


Data Dictionary
---------------

Generate data dictionary:

::

  .. data-dictionary:: example.yml


Available options:

widths
  Space- or comma-separated list of integer.
  These values calculated into percent totaled to 100%.

  The default is ``1 1 1 4`` that will be calculated into 14%, 14%, 14% and
  57% respectively.


headers
  Space- or comma-separated list of string that will become table header.

  The default is ``Name Type Length Description``.

  .. note::

    If you want a column name that contains space,
    use comma-separated format instead.


columns
  Space- or comma-separated list attributes of a property.

  The default is ``name type maxLength description``.
  ``name`` is a special keyword that points to the property name.


The options can also be set as config specified in ``conf.py`` by prefixing it
with ``data_dictionary_``.
But set the value as list.
The value in ``conf.py`` is applied to all directives but will be override by
options in the directive.

In ``conf.py``:

::

  data_dictionary_widths = [1, 1, 1, 4]
  data_dictionary_headers = ['Name', 'Type', 'Length', 'Description']
  data_dictionary_columns = ['name', 'type', 'maxLength', 'description']


Changes
=======

0.1.7
-----

* Fix allOf bug.


0.1.6
-----

* Change ``sphinx.util.compat.Directive`` to
  ``docutils.parsers.rst.Directive`` because it will be removed in Sphinx 1.7.


0.1.5
-----

* Change table name in data dictionary into section.


0.1.4
-----

* Resolve allOff.


0.1.3
-----

* Change syntax for description from reStructuredText to Markdown because
  Swagger use Markdown.


0.1.2
-----

* Description may contains reStructuredText syntax.


0.1.1
-----

* Strange thing happens.
  After delete and re-upload version 0.1.0, pip is unable to install it.


0.1.0
-----

* First public release.


TODO
====

#. Change output format from ``graphviz_output_format = 'svg'`` to
   ``database_diagram_output_format = 'svg'`` so it's only affect
   database-diagram directive.