Various miscellaneous improvements (#12578)

This commit is contained in:
Adam Turner
2024-07-15 05:52:47 +01:00
committed by GitHub
parent b1ed87eb1c
commit f10f0b6fb5
3 changed files with 52 additions and 38 deletions

View File

@@ -969,26 +969,24 @@ class StandaloneHTMLBuilder(Builder):
# user sidebar settings # user sidebar settings
html_sidebars = self.get_builder_config('sidebars', 'html') html_sidebars = self.get_builder_config('sidebars', 'html')
for pattern, patsidebars in html_sidebars.items(): msg = __('page %s matches two patterns in html_sidebars: %r and %r')
for pattern, pat_sidebars in html_sidebars.items():
if patmatch(pagename, pattern): if patmatch(pagename, pattern):
if matched: if matched and has_wildcard(pattern):
if has_wildcard(pattern):
# warn if both patterns contain wildcards # warn if both patterns contain wildcards
if has_wildcard(matched): if has_wildcard(matched):
logger.warning(__('page %s matches two patterns in ' logger.warning(msg, pagename, matched)
'html_sidebars: %r and %r'),
pagename, matched, pattern)
# else the already matched pattern is more specific # else the already matched pattern is more specific
# than the present one, because it contains no wildcard # than the present one, because it contains no wildcard
continue continue
matched = pattern matched = pattern
sidebars = patsidebars sidebars = pat_sidebars
if len(sidebars) == 0: if len(sidebars) == 0:
# keep defaults # keep defaults
pass pass
ctx['sidebars'] = sidebars ctx['sidebars'] = list(sidebars)
# --------- these are overwritten by the serialization builder # --------- these are overwritten by the serialization builder

View File

@@ -89,6 +89,10 @@ class PyXrefMixin:
return result return result
_delimiters_re = re.compile(
r'(\s*[\[\]\(\),](?:\s*o[rf]\s)?\s*|\s+o[rf]\s+|\s*\|\s*|\.\.\.)'
)
def make_xrefs( def make_xrefs(
self, self,
rolename: str, rolename: str,
@@ -100,9 +104,7 @@ class PyXrefMixin:
inliner: Inliner | None = None, inliner: Inliner | None = None,
location: Node | None = None, location: Node | None = None,
) -> list[Node]: ) -> list[Node]:
delims = r'(\s*[\[\]\(\),](?:\s*o[rf]\s)?\s*|\s+o[rf]\s+|\s*\|\s*|\.\.\.)' sub_targets = self._delimiters_re.split(target)
delims_re = re.compile(delims)
sub_targets = re.split(delims, target)
split_contnode = bool(contnode and contnode.astext() == target) split_contnode = bool(contnode and contnode.astext() == target)
@@ -112,13 +114,13 @@ class PyXrefMixin:
if split_contnode: if split_contnode:
contnode = nodes.Text(sub_target) contnode = nodes.Text(sub_target)
if in_literal or delims_re.match(sub_target): if in_literal or self._delimiters_re.match(sub_target):
results.append(contnode or innernode(sub_target, sub_target)) # type: ignore[call-arg] results.append(contnode or innernode(sub_target, sub_target)) # type: ignore[call-arg]
else: else:
results.append(self.make_xref(rolename, domain, sub_target, results.append(self.make_xref(rolename, domain, sub_target,
innernode, contnode, env, inliner, location)) innernode, contnode, env, inliner, location))
if sub_target in ('Literal', 'typing.Literal', '~typing.Literal'): if sub_target in {'Literal', 'typing.Literal', '~typing.Literal'}:
in_literal = True in_literal = True
return results return results

View File

@@ -22,8 +22,10 @@ from sphinx.util.nodes import apply_source_workaround, is_smartquotable
if TYPE_CHECKING: if TYPE_CHECKING:
from collections.abc import Iterator from collections.abc import Iterator
from typing import Literal
from docutils.nodes import Node, Text from docutils.nodes import Node, Text
from typing_extensions import TypeAlias, TypeIs
from sphinx.application import Sphinx from sphinx.application import Sphinx
from sphinx.config import Config from sphinx.config import Config
@@ -31,15 +33,22 @@ if TYPE_CHECKING:
from sphinx.environment import BuildEnvironment from sphinx.environment import BuildEnvironment
from sphinx.util.typing import ExtensionMetadata from sphinx.util.typing import ExtensionMetadata
_DEFAULT_SUBSTITUTION_NAMES: TypeAlias = Literal[
logger = logging.getLogger(__name__)
default_substitutions = {
'version', 'version',
'release', 'release',
'today', 'today',
'translation progress', 'translation progress',
} ]
logger = logging.getLogger(__name__)
_DEFAULT_SUBSTITUTIONS = frozenset({
'version',
'release',
'today',
'translation progress',
})
class SphinxTransform(Transform): class SphinxTransform(Transform):
@@ -105,20 +114,25 @@ class DefaultSubstitutions(SphinxTransform):
def apply(self, **kwargs: Any) -> None: def apply(self, **kwargs: Any) -> None:
# only handle those not otherwise defined in the document # only handle those not otherwise defined in the document
to_handle = default_substitutions - set(self.document.substitution_defs) to_handle = _DEFAULT_SUBSTITUTIONS - set(self.document.substitution_defs)
for ref in self.document.findall(nodes.substitution_reference): for ref in self.document.findall(nodes.substitution_reference):
refname = ref['refname'] if (name := ref['refname']) in to_handle:
if refname in to_handle: ref.replace_self(self._handle_default_substitution(name))
if refname == 'translation progress':
def _handle_default_substitution(self, name: _DEFAULT_SUBSTITUTION_NAMES) -> nodes.Text:
if name == 'translation progress':
# special handling: calculate translation progress # special handling: calculate translation progress
text = _calculate_translation_progress(self.document) return nodes.Text(_calculate_translation_progress(self.document))
else: if name == 'today':
text = self.config[refname] if text := self.config.today:
if refname == 'today' and not text: return nodes.Text(text)
# special handling: can also specify a strftime format # special handling: can also specify a strftime format
text = format_date(self.config.today_fmt or _('%b %d, %Y'), return nodes.Text(format_date(
language=self.config.language) self.config.today_fmt or _('%b %d, %Y'),
ref.replace_self(nodes.Text(text)) language=self.config.language,
))
# config.version and config.release
return nodes.Text(getattr(self.config, name))
def _calculate_translation_progress(document: nodes.document) -> str: def _calculate_translation_progress(document: nodes.document) -> str:
@@ -263,15 +277,15 @@ class ExtraTranslatableNodes(SphinxTransform):
default_priority = 10 default_priority = 10
def apply(self, **kwargs: Any) -> None: def apply(self, **kwargs: Any) -> None:
targets = self.config.gettext_additional_targets targets = frozenset(self.config.gettext_additional_targets)
target_nodes = [v for k, v in TRANSLATABLE_NODES.items() if k in targets] target_nodes = tuple(v for k, v in TRANSLATABLE_NODES.items() if k in targets)
if not target_nodes: if not target_nodes:
return return
def is_translatable_node(node: Node) -> bool: def is_translatable_node(node: Node) -> TypeIs[nodes.Element]:
return isinstance(node, tuple(target_nodes)) return isinstance(node, target_nodes)
for node in self.document.findall(is_translatable_node): # type: nodes.Element for node in self.document.findall(is_translatable_node):
node['translatable'] = True node['translatable'] = True