Skip to content

Commit

Permalink
Improve custom Zubbi directives
Browse files Browse the repository at this point in the history
The new Sphinx version broke our Zubbi directive implementation. The
reason is that the Sphinx log output changed and thus our custom
directives cannot parse the output properly anymore.

We use the Sphinx log to write (and later extract) the custom data from
our directives. This never felt like an appropriate solution but most
propably it was the easiest to do and we didn't find a better solution.

This change improves the Zubbi directives by storing the data in Sphinx'
domaindata dictionary which seems to be more appropriate for this use
case. This is also what other directives (including the "native" Sphinx
directives) do for storing and extracting data).
  • Loading branch information
felixedel committed Jan 5, 2024
1 parent fdc4880 commit 431a34e
Showing 1 changed file with 31 additions and 21 deletions.
52 changes: 31 additions & 21 deletions zubbi/doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,42 +20,57 @@
import sys
import tempfile

from docutils.parsers.rst import Directive
from readme_renderer import markdown
from sphinx.application import Sphinx
from sphinx.util import logging as sphinx_logging
from sphinx.util.console import nocolor
from sphinx.util.docutils import docutils_namespace, patch_docutils
from sphinx.util.docutils import docutils_namespace, patch_docutils, SphinxDirective


LOGGER = logging.getLogger(__name__)


class ZubbiDirective(Directive):
class ZubbiDirective(SphinxDirective):
has_content = True
required_arguments = 0
optional_arguments = 1
final_argument_whitespace = True
logger = sphinx_logging.getLogger("ZubbiDirective")

def run(self):

class SupportedOS(ZubbiDirective):
directive_name = "supported_os"

def run(self):
if len(self.arguments) > 0:
values = self.arguments[0].split(",")
for value in values:
# Log the value with directive_name for later extraction
self.logger.info("%s: %s", self.directive_name, value)
# Store the platforms in Sphinx' domain data, so we can extract
# them later on during the rendering process.
# NOTE (felix): The "correct" solution might be to define a own
# domain and let the domain create the initial domaindata, e.g.
# https://opendev.org/zuul/zuul-sphinx/src/branch/master/zuul_sphinx/zuul.py#L714
# However, as a simple solution, this should be sufficient.
zubbi_domain_data = self.env.domaindata.setdefault("zubbi", {})
zubbi_domain_data["platforms"] = [v.strip().lower() for v in values]
# We don't want to render anything, so we return an empty list of nodes
return []


class SupportedOS(ZubbiDirective):
directive_name = "supported_os"


class Reusable(ZubbiDirective):
directive_name = "reusable"

def run(self):
reusable = False
if len(self.arguments) > 0:
reusable = self.arguments[0].strip().lower() in ["true", "yes"]
# Store the platforms in Sphinx' domain data, so we can extract
# them later on during the rendering process.
zubbi_domain_data = self.env.domaindata.setdefault("zubbi", {})
zubbi_domain_data["reusable"] = reusable

# We don't want to render anything, so we return an empty list of nodes
return []


class SphinxBuildError(RuntimeError):
pass
Expand Down Expand Up @@ -103,16 +118,11 @@ def render_sphinx(content):
if app.statuscode:
raise SphinxBuildError

# Extract the platforms from the logger output
platforms = []
reusable = False
status_log.seek(0)
for line in status_log.readlines():
prefix, _, value = line.partition(":")
if prefix == SupportedOS.directive_name:
platforms.append(value.strip().lower())
elif prefix == Reusable.directive_name:
reusable = value.strip().lower() in ["true", "yes"]
# Extract the data from our custom directives from the domain data
zubbi_domain_data = app.env.domaindata.get("zubbi", {})
platforms = zubbi_domain_data.get("platforms", [])
reusable = zubbi_domain_data.get("reusable", False)

with build_path.open() as build:
html_parts = json.load(build)

Expand Down

0 comments on commit 431a34e

Please sign in to comment.