Skip to content

Sphinx extension for Data Dictionary and Database Diagram

License

Notifications You must be signed in to change notification settings

julot/sphinxcontrib-dd

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

86 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

sphinxcontrib.dd

Sphinx extension for Data Dictionary and Database Diagram.

The syntax is using extended Swagger format.

Database diagram will be generated by GraphViz. Because its dependency to GraphViz, please remember to properly setup GraphViz extension 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.

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 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.

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 will result in this.

https://image.ibb.co/cnZATQ/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-justified labels, respectively.

graph-labelloc

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

"t" and "b" for top- and bottom-justified 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.

node-style

Style of of the node. Default to "rounded"

More here.

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. 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. 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

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