Infra: Add new directives to point to PEP's canonical content (#2702)
As originally discussed in #2692 , this adds a three new custom directives intended to be used at the top of PEPs: * `pep-banner`, a generic admonition banner that can be subclassed with an arbitrary message, * `canonical-docs`, which renders a banner linking to a `Final` PEP's canonical documentation/specification. * `canonical-pypa-spec`, a banner for packaging interoperability PEPs linking to the canonical PyPA specs. Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
This commit is contained in:
parent
d31806fe1e
commit
f87de8284c
17
conf.py
17
conf.py
|
@ -10,7 +10,7 @@ sys.path.append(str(Path("pep_sphinx_extensions").absolute()))
|
|||
|
||||
# Add 'include_patterns' as a config variable
|
||||
from sphinx.config import Config
|
||||
Config.config_values['include_patterns'] = [], 'env', []
|
||||
Config.config_values["include_patterns"] = [], "env", []
|
||||
del Config
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
@ -21,7 +21,11 @@ master_doc = "contents"
|
|||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings.
|
||||
extensions = ["pep_sphinx_extensions", "sphinx.ext.githubpages"]
|
||||
extensions = [
|
||||
"pep_sphinx_extensions",
|
||||
"sphinx.ext.intersphinx",
|
||||
"sphinx.ext.githubpages",
|
||||
]
|
||||
|
||||
# The file extensions of source files. Sphinx uses these suffixes as sources.
|
||||
source_suffix = {
|
||||
|
@ -46,6 +50,13 @@ exclude_patterns = [
|
|||
"pep-0012/pep-NNNN.rst",
|
||||
]
|
||||
|
||||
# Intersphinx configuration
|
||||
intersphinx_mapping = {
|
||||
'python': ('https://docs.python.org/3/', None),
|
||||
'packaging': ('https://packaging.python.org/en/latest/', None),
|
||||
}
|
||||
intersphinx_disabled_reftypes = []
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# HTML output settings
|
||||
|
@ -60,4 +71,4 @@ html_permalinks = False # handled in the PEPContents transform
|
|||
html_baseurl = "https://peps.python.org" # to create the CNAME file
|
||||
gettext_auto_build = False # speed-ups
|
||||
|
||||
templates_path = ['pep_sphinx_extensions/pep_theme/templates'] # Theme template relative paths from `confdir`
|
||||
templates_path = ["pep_sphinx_extensions/pep_theme/templates"] # Theme template relative paths from `confdir`
|
||||
|
|
60
pep-0012.rst
60
pep-0012.rst
|
@ -649,6 +649,66 @@ If you find that you need to use a backslash in your text, consider
|
|||
using inline literals or a literal block instead.
|
||||
|
||||
|
||||
Canonical Documentation and Intersphinx
|
||||
---------------------------------------
|
||||
|
||||
As :pep:`PEP 1 describes <1#pep-maintenance>`,
|
||||
PEPs are considered historical documents once marked Final,
|
||||
and their canonical documentation/specification should be moved elsewhere.
|
||||
To indicate this, use the ``canonical-docs`` directive
|
||||
or an appropriate subclass
|
||||
(currently ``canonical-pypa-spec`` for packaging standards).
|
||||
|
||||
Furthermore, you can use
|
||||
`Intersphinx references
|
||||
<https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html>`_
|
||||
to other Sphinx sites,
|
||||
currently the `Python documentation <https://docs.python.org/>`_
|
||||
and `packaging.python.org <https://packaging.python.org/>`_,
|
||||
to easily cross-reference pages, sections and Python/C objects.
|
||||
This works with both the "canonical" directives and anywhere in your PEP.
|
||||
|
||||
Add the directive between the headers and the first section of the PEP
|
||||
(typically the Abstract)
|
||||
and pass as an argument an Intersphinx reference of the canonical doc/spec
|
||||
(or if the target is not on a Sphinx site, a `reST hyperlink <Hyperlinks_>`__).
|
||||
|
||||
For example,
|
||||
to create a banner pointing to the :mod:`python:sqlite3` docs,
|
||||
you would write the following::
|
||||
|
||||
.. canonical-doc:: :mod:`python:sqlite3`
|
||||
|
||||
which would generate the banner:
|
||||
|
||||
.. canonical-doc:: :mod:`python:sqlite3`
|
||||
|
||||
Or for a PyPA spec,
|
||||
such as the :ref:`packaging:core-metadata`,
|
||||
you would use::
|
||||
|
||||
.. canonical-pypa-spec:: :ref:`packaging:core-metadata`
|
||||
|
||||
which renders as:
|
||||
|
||||
.. canonical-pypa-spec:: :ref:`packaging:core-metadata`
|
||||
|
||||
The argument accepts arbitrary reST,
|
||||
so you can include multiple linked docs/specs and name them whatever you like,
|
||||
and you can also include directive content that will be inserted into the text.
|
||||
The following advanced example::
|
||||
|
||||
.. canonical-doc:: the :ref:`python:sqlite3-connection-objects` and :exc:`python:~sqlite3.DataError` docs
|
||||
|
||||
Also, see the :ref:`Data Persistence docs <persistence>` for other examples.
|
||||
|
||||
would render as:
|
||||
|
||||
.. canonical-doc:: the :ref:`python:sqlite3-connection-objects` and :exc:`python:sqlite3.DataError` docs
|
||||
|
||||
Also, see the :ref:`Data Persistence docs <persistence>` for other examples.
|
||||
|
||||
|
||||
Habits to Avoid
|
||||
===============
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ from sphinx import project
|
|||
|
||||
from pep_sphinx_extensions.pep_processor.html import pep_html_builder
|
||||
from pep_sphinx_extensions.pep_processor.html import pep_html_translator
|
||||
from pep_sphinx_extensions.pep_processor.parsing import pep_banner_directive
|
||||
from pep_sphinx_extensions.pep_processor.parsing import pep_parser
|
||||
from pep_sphinx_extensions.pep_processor.parsing import pep_role
|
||||
from pep_sphinx_extensions.pep_processor.transforms import pep_references
|
||||
|
@ -93,6 +94,14 @@ def setup(app: Sphinx) -> dict[str, bool]:
|
|||
|
||||
app.add_post_transform(pep_references.PEPReferenceRoleTitleText)
|
||||
|
||||
# Register custom directives
|
||||
app.add_directive(
|
||||
"pep-banner", pep_banner_directive.PEPBanner)
|
||||
app.add_directive(
|
||||
"canonical-doc", pep_banner_directive.CanonicalDocBanner)
|
||||
app.add_directive(
|
||||
"canonical-pypa-spec", pep_banner_directive.CanonicalPyPASpecBanner)
|
||||
|
||||
# Register event callbacks
|
||||
app.connect("builder-inited", _update_config_for_builder) # Update configuration values for builder used
|
||||
app.connect("env-before-read-docs", create_pep_zero) # PEP 0 hook
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
"""Roles to insert custom admonitions pointing readers to canonical content."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers import rst
|
||||
|
||||
|
||||
PYPA_SPEC_BASE_URL = "https://packaging.python.org/en/latest/specifications/"
|
||||
|
||||
|
||||
class PEPBanner(rst.Directive):
|
||||
"""Insert a special banner admonition in a PEP document."""
|
||||
|
||||
has_content = True
|
||||
required_arguments = 0
|
||||
optional_arguments = 1
|
||||
final_argument_whitespace = True
|
||||
option_spec = {}
|
||||
|
||||
admonition_pre_template = ""
|
||||
admonition_pre_text = ""
|
||||
admonition_post_text = ""
|
||||
|
||||
admonition_class = nodes.important
|
||||
css_classes = ["pep-banner"]
|
||||
|
||||
|
||||
def run(self) -> list[nodes.admonition]:
|
||||
|
||||
if self.arguments:
|
||||
link_content = self.arguments[0]
|
||||
pre_text = self.admonition_pre_template.format(
|
||||
link_content=link_content)
|
||||
else:
|
||||
pre_text = self.admonition_pre_text
|
||||
|
||||
pre_text_node = nodes.paragraph(pre_text)
|
||||
pre_text_node.line = self.lineno
|
||||
pre_node, pre_msg = self.state.inline_text(pre_text, self.lineno)
|
||||
pre_text_node.extend(pre_node + pre_msg)
|
||||
|
||||
post_text = self.admonition_post_text
|
||||
post_text_node = nodes.paragraph(post_text)
|
||||
post_text_node.line = self.lineno
|
||||
post_node, post_msg = self.state.inline_text(post_text, self.lineno)
|
||||
post_text_node.extend(post_node + post_msg)
|
||||
|
||||
source_lines = [pre_text] + list(self.content or []) + [post_text]
|
||||
admonition_node = self.admonition_class(
|
||||
"\n".join(source_lines), classes=self.css_classes)
|
||||
|
||||
admonition_node.append(pre_text_node)
|
||||
if self.content:
|
||||
self.state.nested_parse(
|
||||
self.content, self.content_offset, admonition_node)
|
||||
admonition_node.append(post_text_node)
|
||||
|
||||
return [admonition_node]
|
||||
|
||||
|
||||
class CanonicalDocBanner(PEPBanner):
|
||||
"""Insert an admonition pointing readers to a PEP's canonical docs."""
|
||||
|
||||
admonition_pre_template = (
|
||||
"This PEP is a historical document. "
|
||||
"The up-to-date, canonical documentation can now be found "
|
||||
"at {link_content}."
|
||||
)
|
||||
admonition_pre_text = (
|
||||
"This PEP is a historical document. "
|
||||
"The up-to-date, canonical documentation can now be found elsewhere."
|
||||
)
|
||||
admonition_post_text = (
|
||||
"See :pep:`1` for how to propose changes."
|
||||
)
|
||||
|
||||
css_classes = [*PEPBanner.css_classes, "canonical-doc"]
|
||||
|
||||
|
||||
|
||||
class CanonicalPyPASpecBanner(PEPBanner):
|
||||
"""Insert a specialized admonition for PyPA packaging specifications."""
|
||||
|
||||
admonition_pre_template = (
|
||||
"This PEP is a historical document. "
|
||||
"the up-to-date, canonical spec, {link_content}, is maintained on "
|
||||
f"the `PyPA specs page <{PYPA_SPEC_BASE_URL}>`__."
|
||||
)
|
||||
admonition_pre_text = (
|
||||
"This PEP is a historical document. "
|
||||
"The up-to-date, canonical specification is maintained on "
|
||||
f"the `PyPA specs page <{PYPA_SPEC_BASE_URL}>`__."
|
||||
)
|
||||
admonition_post_text = (
|
||||
"See the `PyPA specification update process "
|
||||
"<https://www.pypa.io/en/latest/specifications/#handling-fixes-and-other-minor-updates>`__ "
|
||||
"for how to propose changes."
|
||||
)
|
||||
|
||||
css_classes = [*PEPBanner.css_classes, "canonical-pypa-spec"]
|
Loading…
Reference in New Issue