A pyramid plugin that describes a pyramid application URL hierarchy via inspection.
Project description
A Pyramid plugin that makes a Pyramid application self-documenting via inspection/reflection to:
Describe the application URL structure,
Extract documentation from Python comments, and
Generate formal syntax using commenting conventions.
The resulting documentation can be served by the application to an HTTP request or displayed on the command line. It has built-in support for plain-text hierachies, reStructuredText, HTML, PDF, JSON, YAML, WADL, and XML, however other custom formats can be added easily.
Exposing an application’s structure via HTTP is useful to dynamically generate an API description (via WADL, JSON, or YAML) or to create documentation directly from source code.
On the command-line it is useful to get visibility into an application’s URL structure and hierarchy so that it can be understood and maintained.
Project Info
Project Page: https://github.com/cadithealth/pyramid_describe
Bug Tracking: https://github.com/cadithealth/pyramid_describe/issues
TL;DR
Install:
$ pip install pyramid-describe
Command-line example:
$ pdescribe example.ini --format txt
/ # The application root.
├── contact/ # Contact manager.
│ ├── <POST> # Creates a new 'contact' object.
│ └── {CONTACTID} # RESTful access to a specific contact.
│ ├── <DELETE> # Delete this contact.
│ ├── <GET> # Get this contact's details.
│ └── <PUT> # Update this contact's details.
├── login # Authenticate against the server.
└── logout # Remove authentication tokens.
Examples of the above application in all other formats with built-in support are available at: text (pure-ASCII), reStructuredText, HTML, PDF, JSON, YAML, WADL, and XML.
Enable the plugin:
def main(global_config, **settings):
# ...
config.include('pyramid_describe')
# ...
And make the documentation available publicly at “/describe”:
[app:main]
describe.attach = /describe
describe.formats = html pdf
describe.format.html.default.cssPath = myapp:style/doc-html.css
describe.format.html+pdf.default.cssPath = myapp:style/doc-pdf.css
describe.format.default.pdfkit.options = {page-size: Letter}
Note that there are many options to control how the resulting documentation is made available – see Options.
Installation
Install with the usual python mechanism, e.g. here with pip:
$ pip install pyramid-describe
Usage
There are three mechanisms to use pyramid-describe: via standard pyramid inclusion which will add routes to the current application, by explicitly embedding a pyramid_describe.DescribeController instance, or by directly calling the pyramid_describe.Describer object methods.
Pyramid Inclusion
Pyramid-describe can be added via standard pyramid inclusion, either in the INI file or directly in your main function. For example:
def main(global_config, **settings):
# ...
config.include('pyramid_describe')
When using pyramid inclusion, pyramid-describe expects to find configuration options in the application settings. See the Options section for a list of all supported options, with a short example here:
[app:main]
describe.attach = /doc
describe.formats = html json pdf
describe.format.default.title = My Application
describe.format.html.default.cssPath = myapp:static/doc.css
describe.entries.filters = myapp.describe.entry_filter
Note that multiple describers, each with different configurations, can be added via pyramid inclusion by using the describe.prefixes option.
DescribeController
Pyramid-describe can also be added to your application by embedding a DescribeController object. The DescribeController constructor takes the following parameters:
view:
An instance of pyramid.interfaces.IView, which is the view that should be inspected and reflected.
root:
The root path to the specified URL, so that host-relative URLs can be generated to the views found.
settings:
A dictionary of all the options to apply to this describer. Note that in this case, the options should not have any prefix.
Example:
from pyramid_describe import DescribeController
def main(global_config, **settings):
# ...
config.include('pyramid_controllers')
settings = {
'formats' : ['html', 'json', 'pdf'],
'format.default.title' : 'My Application',
'format.html.default.cssPath' : 'myapp:static/doc.css',
'entries.filters' : 'myapp.describe.entry_filter',
}
config.add_controller('MyAppDescriber', '/doc', DescribeController(settings))
Describer
Pyramid-describe can also be added to your application by directly calling the Describer’s functionality. This is an even lower-level approach than, but still quite similar to, embedding the DescribeController; the constructor takes the same settings parameter as the DescribeController, and then a call to the describe method actually generates the output. The describe method takes as parameters a context and a format, and returns a dictionary with the following attributes:
content_type:
The MIME content-type associated with the rendered output.
charset:
The character set that the output is encoded in.
content:
The actual rendering output.
Example:
from pyramid_describe import Describer
def my_describer(request):
settings = {
'formats' : ['html', 'json', 'pdf'],
'format.default.title' : 'My Application',
'format.html.default.cssPath' : 'myapp:static/doc.css',
'entries.filters' : 'myapp.describe.entry_filter',
}
describer = Describer(settings=settings)
context = dict(request=request)
result = describer.describe(context=context, format='pdf')
request.response.content_type = result['content_type']
request.response.charset = result['charset']
request.response.body = result['content']
return request.response
Documentation Conventions
By default, the documentation that is extracted from your handlers’ pydocs is parsed and converted using:
Docorator extraction
Common text-role definitions
Field-list aliasing of numpydoc sections
Numpydoc parsing
Inter-endpoint linking and referencing
This behavior can be disabled or extended by setting the entries.parsers setting (see Options). Here is an example that employs each of these functions (see below for an in-depth explanation):
class MyController(RestController):
@expose
def deactivate(self, request):
'''
@PUBLIC, @DEPRECATED(1.3.23)
The current object is deleted. Please note that this endpoint is
deprecated; please use the more RESTful :doc.link:`DELETE:..`
endpoint instead.
@INTERNAL: OOPS! This method was accidentally carried over from
the Java implementation. The `soap-to-rest` tool needs to be
analyzed to figure out why this happened.
:doc.copy:`DELETE:..`
'''
@expose
def get(self, request):
'''
:doc.import:`myapp:doc/mycontroller.rst`
'''
@expose
def delete(self, request):
'''
@PUBLIC, @FROZEN
The current object is deleted.
:Parameters:
recursive : bool, optional, default: false
If true, recursively deletes any dependent objects too.
permanent : bool, optional, default: false, @INTERNAL
If true, the objects and all records are permanently purged
from the network. Reserved for internal administrators.
:Returns:
HTTPOk
The object(s) were successfully deleted.
:Raises:
HTTPForbidden
The current user does not have sufficient privileges.
HTTPNotFound
The specified object does not exist.
'''
Docorator Extraction
Docorators are decorators for documentation. For example, you may decorate a particular endpoint with @BETA to declare that this endpoint is not finalized yet.
Pyramid-describe will inspect an entry’s .doc text and convert them to class names. The class names are applied to different element levels depending on where they are found:
Docorators on the first line apply to the entire entry.
Docorators at the beginning of a paragraph apply to that paragraph only.
Docorators at the beginning of a section title apply to that section.
Docorators in the numpydoc type specification apply to that parameter/return/raise or other formal numpydoc object.
Docorators must follow one of the following syntaxes:
Simple tag style: @TAG, where TAG can be any alphanumeric sequence.
Parameterized declaration style: @TAG(PARAMS), where TAG can be any alphanumeric sequence, and PARAMS can be anything except the closing parenthesis.
Docorators are converted to class names using the following rules:
Prefixed with doc-.
All letters are lowercased.
All non-alphanumeric characters are replaced with a dash (“-“).
Consecutive dashes are replaced with one dash.
Terminating dashes are dropped.
Thus the docorator @DEPRECATED(1.3.23) becomes doc-deprecated-1-3-23.
IMPORTANT: pyramid-describe does not apply any special processing to docorators beyond identifying them and applying the class names to the appropriate content. It is therefore up to the calling application to filter these in any way, for example hiding entries (or portions thereof) that have the doc-internal, i.e. that were marked with @INTERNAL.
Common Text-Role Definitions
The text-roles class, meth, and func are not by default defined by docutils. Pyramid-describe gives a very bare-bones implementation (it just aliases them as “literal” style nodes). If these text-roles are used by the calling application, a more thorough implementation (that actually performs linking to API documentation) is probably desirable. Pyramid-describe does not have access to this information and is therefore outside of its scope.