The textwrap module by default breaks hyphenated words across line wrapping boundaries, which Sphinx will then reinterpret as whitespace. Disable this behavior so that hyphenated words will be moved to the next line rather than broken at their hyphens. Also disable a related feature which would break lines longer than the target line length, allowing one-word lines longer than that. Change-Id: I2ce8dcd4d67b658817857167e218913c75df0bda
94 lines
2.6 KiB
Python
94 lines
2.6 KiB
Python
#!/usr/bin/env python
|
|
import glob
|
|
import os
|
|
import textwrap
|
|
|
|
from jinja2 import FileSystemLoader
|
|
from jinja2.environment import Environment
|
|
import yaml
|
|
|
|
from sphinx.util import logging
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
def to_snake_case(d):
|
|
for k in dict(d):
|
|
v = d[k]
|
|
del d[k]
|
|
d[k.replace('-', '_')] = v
|
|
if type(k) == dict:
|
|
to_snake_case(d)
|
|
|
|
|
|
def to_paragraphs(d, *args):
|
|
for k in args:
|
|
if k in d and isinstance(d[k], str):
|
|
d[k] = '\n'.join(textwrap.wrap(
|
|
d[k], break_long_words=False, break_on_hyphens=False))
|
|
|
|
|
|
def ossa_date_formatter(value):
|
|
return "{:%B %d, %Y}".format(value)
|
|
|
|
|
|
def csv_list_formatter(value):
|
|
return ", ".join(value)
|
|
|
|
|
|
def cve_formater(value):
|
|
if 'note' in value:
|
|
return "%s (%s)" % (value['cve-id'], value['note'])
|
|
return value['cve-id']
|
|
|
|
|
|
def cve_list_formatter(value):
|
|
return ',\n '.join([cve_formater(x) for x in value])
|
|
|
|
|
|
def render_template(template, data, **kwargs):
|
|
template_dir = kwargs.get('template_dir', os.getcwd())
|
|
loader = FileSystemLoader(template_dir)
|
|
env = Environment(trim_blocks=True, loader=loader)
|
|
env.filters["ossa_date"] = ossa_date_formatter
|
|
env.filters["csv_list"] = csv_list_formatter
|
|
env.filters["cve_list"] = cve_list_formatter
|
|
template = env.get_template(template)
|
|
return template.render(**data)
|
|
|
|
|
|
def render(source, template, **kwargs):
|
|
vals = yaml.safe_load(open(source).read())
|
|
to_snake_case(vals)
|
|
to_paragraphs(vals, 'description', 'errata')
|
|
return render_template(template, vals, **kwargs)
|
|
|
|
|
|
def build_advisories(app):
|
|
|
|
template_name = "rst.jinja"
|
|
template_files = os.path.join(".", "doc", "source", "_exts")
|
|
yaml_files = os.path.join(".", "ossa")
|
|
input_files = glob.glob(os.path.join(yaml_files, "*.yaml"))
|
|
output_files = [x.replace(".yaml", ".rst") for x in input_files]
|
|
for old, new in zip(input_files, output_files):
|
|
with open(new, "w") as out:
|
|
out.write(render(old, template_name, template_dir=template_files))
|
|
|
|
|
|
def reverse_toctree(app, doctree, docname):
|
|
"""Reverse the order of entries in the root toctree if 'glob' is used."""
|
|
if docname in ["index", "ossalist"]:
|
|
for node in doctree.traverse():
|
|
if node.tagname == "toctree" and node.get("glob"):
|
|
node["entries"].reverse()
|
|
if docname == "index":
|
|
node["entries"] = node["entries"][0:5]
|
|
break
|
|
|
|
|
|
def setup(app):
|
|
LOG.info('Loading the vmt extension')
|
|
app.connect('builder-inited', build_advisories)
|
|
app.connect("doctree-resolved", reverse_toctree)
|