Merge "Enforce inclusion of pulic proxy methods in docs"

This commit is contained in:
Jenkins 2017-02-11 12:22:27 +00:00 committed by Gerrit Code Review
commit d4485de8f0
3 changed files with 119 additions and 0 deletions

View File

@ -18,6 +18,7 @@ import sys
import openstackdocstheme
sys.path.insert(0, os.path.abspath('../..'))
sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
@ -25,8 +26,12 @@ sys.path.insert(0, os.path.abspath('../..'))
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'enforcer'
]
# When True, this will raise an exception that kills sphinx-build.
enforcer_warnings_as_errors = False
# autodoc generation is a bit aggressive and a nuisance when doing heavy
# text edit cycles.
# execute "export SPHINX_DEBUG=1" in your terminal to disable

113
doc/source/enforcer.py Normal file
View File

@ -0,0 +1,113 @@
import importlib
import os
from bs4 import BeautifulSoup
from sphinx import errors
# NOTE: We do this because I can't find any way to pass "-v"
# into sphinx-build through pbr...
DEBUG = True if os.getenv("ENFORCER_DEBUG") else False
WRITTEN_METHODS = set()
class EnforcementError(errors.SphinxError):
"""A mismatch between what exists and what's documented"""
category = "Enforcer"
def get_proxy_methods():
"""Return a set of public names on all proxies"""
names = ["openstack.bare_metal.v1._proxy",
"openstack.block_store.v2._proxy",
"openstack.cluster.v1._proxy",
"openstack.compute.v2._proxy",
"openstack.database.v1._proxy",
"openstack.identity.v2._proxy",
"openstack.identity.v3._proxy",
"openstack.image.v1._proxy",
"openstack.image.v2._proxy",
"openstack.key_manager.v1._proxy",
"openstack.message.v1._proxy",
"openstack.message.v2._proxy",
"openstack.metric.v1._proxy",
"openstack.network.v2._proxy",
"openstack.object_store.v1._proxy",
"openstack.orchestration.v1._proxy",
"openstack.telemetry.v2._proxy",
"openstack.telemetry.alarm.v2._proxy",
"openstack.workflow.v2._proxy"]
modules = (importlib.import_module(name) for name in names)
methods = set()
for module in modules:
# We're not going to use the Proxy for anything other than a `dir`
# so just pass a dummy value so we can create the instance.
instance = module.Proxy("")
# We only document public names
names = [name for name in dir(instance) if not name.startswith("_")]
good_names = [module.__name__ + ".Proxy." + name for name in names]
methods.update(good_names)
return methods
def page_context(app, pagename, templatename, context, doctree):
"""Handle html-page-context-event
This event is emitted once the builder has the contents to create
an HTML page, but before the template is rendered. This is the point
where we'll know what documentation is going to be written, so
gather all of the method names that are about to be included
so we can check which ones were or were not processed earlier
by autodoc.
"""
if "users/proxies" in pagename:
soup = BeautifulSoup(context["body"], "html.parser")
dts = soup.find_all("dt")
ids = [dt.get("id") for dt in dts]
written = 0
for id in ids:
if id is not None and "_proxy.Proxy" in id:
WRITTEN_METHODS.add(id)
written += 1
if DEBUG:
app.info("ENFORCER: Wrote %d proxy methods for %s" % (
written, pagename))
def build_finished(app, exception):
"""Handle build-finished event
This event is emitted once the builder has written all of the output.
At this point we just compare what we know was written to what we know
exists within the modules and share the results.
When enforcer_warnings_as_errors=True in conf.py, this method
will raise EnforcementError on any failures in order to signal failure.
"""
all_methods = get_proxy_methods()
app.info("ENFORCER: %d proxy methods exist" % len(all_methods))
app.info("ENFORCER: %d proxy methods written" % len(WRITTEN_METHODS))
missing = all_methods - WRITTEN_METHODS
missing_count = len(missing)
app.info("ENFORCER: Found %d missing proxy methods "
"in the output" % missing_count)
for name in sorted(missing):
app.warn("ENFORCER: %s was not included in the output" % name)
if app.config.enforcer_warnings_as_errors:
raise EnforcementError(
"There are %d undocumented proxy methods" % missing_count)
def setup(app):
app.add_config_value("enforcer_warnings_as_errors", False, "env")
app.connect("html-page-context", page_context)
app.connect("build-finished", build_finished)

View File

@ -3,6 +3,7 @@
# process, which may cause wedges in the gate later.
hacking<0.11,>=0.10.0
beautifulsoup4 # MIT
coverage>=4.0 # Apache-2.0
fixtures>=3.0.0 # Apache-2.0/BSD
mock>=2.0 # BSD