Skip to content

Commit

Permalink
Merge pull request #3 from dave-shawley/more-docs
Browse files Browse the repository at this point in the history
Add some more documents (and support for :options:)
  • Loading branch information
dave-shawley committed Jun 22, 2016
2 parents 9b3e673 + 8f9df93 commit acf7cef
Show file tree
Hide file tree
Showing 6 changed files with 338 additions and 17 deletions.
29 changes: 28 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
Sphinx JSON Domain
==================

.. image:: https://img.shields.io/pypi/v/sphinx-jsondomain.svg?maxAge=2592000
:target: https://pypi.python.org/sphinx-jsondomain
.. image:: https://readthedocs.org/projects/sphinx-jsondomain/badge/?version=latest
:target: http://sphinx-jsondomain.readthedocs.io/en/latest/?badge=latest
.. image:: https://travis-ci.org/dave-shawley/sphinx-jsondomain.svg?branch=master
:target: https://travis-ci.org/dave-shawley/sphinx-jsondomain

I was surprised that this didn't already exist somewhere when I wanted to
describe a JSON document outside of using `sphinxcontrib-httpdomain`_ to
document one of my APIs. This extension simplifies describing structured
Expand All @@ -19,7 +27,26 @@ JSON documents using a new `Sphinx domain`_.
or the empty string
This will format to something pretty and make references to
`:json:object:`Github User`` work as expected.
`:json:object:`Github User`` work as expected. See the `online examples`_
for a better idea of what is possible.

Quick Start
-----------
Install sphinx and the ``sphinx-jsondomain`` package::

$ python3 -mvenv env
$ env/bin/pip install -q sphinx sphinx-jsondomain

Set up the sphinx documentation root and build your documentation set::

$ env/bin/sphinx-quickstart -p my-project -r 0.0 -v 0.0.0 \
> -a 'Dave Shawley <daveshawley@gmail.com>' --quiet docs
$ env/bin/sphinx-build -b html docs build/sphinx/html

Now, find the ``extensions`` definition in *docs/conf.py* and add
``sphinxjsondomain`` to the end. Add a ``json:object`` directive to
*docs/index.rst* and run *sphinx-build* again to see the results.

.. _sphinxcontrib-httpdomain: https://pythonhosted.org/sphinxcontrib-httpdomain/
.. _sphinx domain: http://www.sphinx-doc.org/en/stable/domains.html#what-is-a-domain
.. _online examples: https://sphinx-jsondomain.readthedocs.io/en/latest/examples.html
68 changes: 67 additions & 1 deletion docs/examples.rst
Original file line number Diff line number Diff line change
@@ -1,13 +1,47 @@
Examples
========
This page contains additional examples without further elaboration.
Each example is preceded by it's ReStructuredText source.

-----

.. code-block:: rst
.. json:object:: Github Issue
:showexample:
Information about a Github issue.
:property id: Github assigned issue ID
:proptype id: integer
:options id: nullable, default=''
:property url url: direct link to this issue
:property url repository_url: direct link to the repository that
this issue lives in
:property url labels_url: retrieve and manipulate the labels
associated with this issue
:property url comments_url: retrieve and manipulate the comments
associated with this issue
:property url events_url: retrieve and manipulate the events associated
with this issue
:property html_url: HTML formatted information about this issue
:proptype html_url: url
:property integer number: raw issue number
:property string state: current state of the issue
:property string title: issue title
:property string body: issue body
:property user: embedded information about the user that created
the issue
:proptype user: :json:object:`Github User`
.. json:object:: Github Issue
:showexample:

Information about a Github issue.

:property integer id: Github assigned issue ID
:property id: Github assigned issue ID
:proptype id: integer
:options id: nullable, default=''
:property url url: direct link to this issue
:property url repository_url: direct link to the repository that
this issue lives in
Expand All @@ -27,6 +61,23 @@ Examples
the issue
:proptype user: :json:object:`Github User`

-----

.. code-block:: rst
.. json:object:: Error
:showexample: yaml
What a normal JSON error body looks like.
:property string type:
:property string title:
:property integer status:
:property string detail:
:property uri instance:
The semantics of this data type is described in :rfc:`7807`.
.. json:object:: Error
:showexample: yaml

Expand All @@ -40,6 +91,21 @@ Examples

The semantics of this data type is described in :rfc:`7807`.

-----

.. code-block:: rst
.. json:object:: Github User
:showexample:
What Github's API thinks a user looks like.
:property user_name login: the user's unique login
:property integer id: Github assigned unique user identifier
:property url avatar_url: url to user's selected avatar image
:property url gravatar_url: url to the user's gravatar image or
the empty string
.. json:object:: Github User
:showexample:

Expand Down
4 changes: 4 additions & 0 deletions docs/history.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
Release History
===============

`Next Release`_
---------------
- Add support for ``options`` parameter.

`0.0.1`_ (20-Jun-2016)
----------------------
- Initial implementation of ``:json:`` domain including support for
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
.. toctree::
:hidden:

usage
examples
contributing
history
177 changes: 177 additions & 0 deletions docs/usage.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
Usage
=====
Before you can use this extension, you need to install the
`sphinx-jsondomain <https://pypi.python.org/pypi/sphinx-jsondomain>`_
Python package and then add the :mod:`sphinxjsondomain` module to
:data:`extensions` list in your Sphinx configuration file (:file:`conf.py`)::

extensions = ['sphinxjsondomain']

Then you can use the :rst:dir:`json:object` directive to document
your JSON documents.

ReStructuredText Usage
----------------------

.. rst:directive:: .. json:object:: Object Name
Documents the structure of a JSON document using the name ``Object Name``.
The description is referenceable using the :rst:role:`json:object` role.
Each property of the JSON document is described using a separate

**:property** *[type]* *identifier* **:** *description*
Documents the property named *identifier*. The property's type can be
specified inline or as a separate ``:proptype:`` option. The type is
shown in the rendered output and linked if the type is something
recognizable. It is also used to generate sample data, if the
``:showexample:`` option is included.

**:proptype** *identifier* **:** *type*
Set's the type of the property named *identifier*. This is
necessary if you are setting the property type to a hyperlinked
value (e.g., :rst:role:`json:object` role instance).

**:showexample:**
If this option is specified, then the rendered output will contain
a generated example. The example data is generated using the
Python `fake-factory`_ library. See :ref:`recognized_types` for
more details.

**:noindex:**
Do not include this object in the general index.

**:options** *identifier* **:** *option-list*
Options are a comma-separated list of values that are rendered in
italics after the property's description. The extension does not
interpret the option values in any way.

.. note::

The ``:options:`` option will be used to in the near future
to enable additional functionality such as adding constraints
when generating a JSON Schema for types.

.. rst:role:: json:object
Links to the named :rst:dir:`json:object` directive.

.. _recognized_types:

Recognized Types
----------------
Types are used for two distinct purposes in this extension. First of all,
they are linked to appropriate documentation. Secondly, they are used to
generate example snippets if the *:showexample:* option is included.

**uri**, **url** links to the relevant IETF RFC that describes URL
syntax. Examples are generated using `faker.providers.internet`_.

**boolean** links to the definition for the Python :class:`bool` type.
Examples are generated using `faker.providers.python`_.

**string**, **str** links to the definition for the Python :class:`str`
type. Examples are generated using `faker.providers.python`_.

**integer**, **int** links to the definition for the Python :class:`int`
type. Examples are generated using `faker.providers.python`_.

**float**, **number** links to the definition for the Python :class:`float`
type. Examples are generated using `faker.providers.python`_.

**null** links to the definition for the Python :data:`None` value.

**email** links to :rfc:`2822` since it is the formal definition of an
email address. Examples are generated using `faker.providers.internet`_.

**iso8601** links to :rfc:`3339` since it is a good (and freely available)
description of the ISO-8601 format. Examples are generated using
`faker.providers.date_time`_.

**uuid4** links to :rfc:`4122` since it is the definitive specification
for UUIDv4 values. Examples are generated using `faker.providers.misc`_.

**md5** links to :rfc:`1321`. Examples are generated using
`faker.providers.misc`_.

**sha1** links to :rfc:`3174`. Examples are generated using
`faker.providers.misc`_.

**sha256** links to :rfc:`6234`. Examples are generated using
`faker.providers.misc`_.

**user_name** links to the defintion for the Python :class:`str` type.
Examples are generated using `faker.providers.internet`_.

Example Generation
------------------
As mentioned elsewhere, this extensions uses the `fake-factory`_ library
to generate sample data. If the "type" of the property is an attribute
of a ``faker.Factory`` instance, then the method is called to generate
the sample value. Otherwise, the extension will handle integer, float,
boolean, string, and :data:`None` values by calling the appropriate faker
methods.

The other interesting case is the one of embedded objects. If you set
the property type to a :rst:role:`json:object` reference, then the
documented object is included recursively. Let's look at a simple
example.

.. code-block:: rst
:linenos:
.. json:object:: Contact
:showexample:
:property name preferred_name: contact's preferred name in
correspondance
:property address: mailing address of contact
:proptype address: :json:object:`Address`
.. json:object:: Address
:showexample:
:property street_address street: street address for this
location
:property city city: city name
:property state_abbr state: abbreviated state name
:property postalcode zip: postal code for this address
And this is the rendered version. Pay particular attention to the
handling of the ``address`` property. The property type is specified
using the ``:proptype:`` option so that we can use a link to another
JSON object (e.g., ``:json:object`Address``` on line 7). The extension
recognizes linked objects and embeds an instance of them in the generated
example.

.. json:object:: Contact
:showexample:

:property name preferred_name: contact's preferred name in
correspondance
:property address: mailing address of contact
:proptype address: :json:object:`Address`

.. json:object:: Address
:showexample:

:property street_address street: street address for this
location
:property city city: city name
:property state_abbr state: abbreviated state name
:property postalcode zip: postal code for this address

Index Generation
----------------
:rst:dir:`json:object` directives are added to the general index as
children of the ``JSON Objects`` entry. You can inhibit this on a
directive-by-directive basis by including the ``:noindex:`` option.

.. _fake-factory: http://fake-factory.readthedocs.io/en/latest/
.. _faker.providers.date_time: http://fake-factory.readthedocs.io/en/latest
/providers/faker.providers.date_time.html
.. _faker.providers.internet: http://fake-factory.readthedocs.io/en/latest
/providers/faker.providers.internet.html
.. _faker.providers.misc: http://fake-factory.readthedocs.io/en/latest
/providers/faker.providers.misc.html
.. _faker.providers.python: http://fake-factory.readthedocs.io/en/latest
/providers/faker.providers.python.html

0 comments on commit acf7cef

Please sign in to comment.