diff options
Diffstat (limited to 'pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/options.py')
-rw-r--r-- | pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/options.py | 45 |
1 files changed, 41 insertions, 4 deletions
diff --git a/pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/options.py b/pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/options.py index 3cba36140bb..8282d749324 100644 --- a/pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/options.py +++ b/pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/options.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import argparse import json @@ -10,6 +12,7 @@ from xml.sax.saxutils import escape, quoteattr import markdown_it +from . import parallel from .docbook import DocBookRenderer, make_xml_id from .manpage import ManpageRenderer, man_escape from .md import Converter, md_escape @@ -148,15 +151,33 @@ class BaseConverter(Converter): return [ l for part in blocks for l in part ] + # this could return a TState parameter, but that does not allow dependent types and + # will cause headaches when using BaseConverter as a type bound anywhere. Any is the + # next best thing we can use, and since this is internal it will be mostly safe. + @abstractmethod + def _parallel_render_prepare(self) -> Any: raise NotImplementedError() + # this should return python 3.11's Self instead to ensure that a prepare+finish + # round-trip ends up with an object of the same type. for now we'll use BaseConverter + # since it's good enough so far. + @classmethod + @abstractmethod + def _parallel_render_init_worker(cls, a: Any) -> BaseConverter: raise NotImplementedError() + def _render_option(self, name: str, option: dict[str, Any]) -> RenderedOption: try: return RenderedOption(option['loc'], self._convert_one(option)) except Exception as e: raise Exception(f"Failed to render option {name}") from e + @classmethod + def _parallel_render_step(cls, s: BaseConverter, a: Any) -> RenderedOption: + return s._render_option(*a) + def add_options(self, options: dict[str, Any]) -> None: - for (name, option) in options.items(): - self._options[name] = self._render_option(name, option) + mapped = parallel.map(self._parallel_render_step, options.items(), 100, + self._parallel_render_init_worker, self._parallel_render_prepare()) + for (name, option) in zip(options.keys(), mapped): + self._options[name] = option @abstractmethod def finalize(self) -> str: raise NotImplementedError() @@ -194,6 +215,13 @@ class DocBookConverter(BaseConverter): self._varlist_id = varlist_id self._id_prefix = id_prefix + def _parallel_render_prepare(self) -> Any: + return (self._manpage_urls, self._revision, self._markdown_by_default, self._document_type, + self._varlist_id, self._id_prefix) + @classmethod + def _parallel_render_init_worker(cls, a: Any) -> DocBookConverter: + return cls(*a) + def _render_code(self, option: dict[str, Any], key: str) -> list[str]: if lit := option_is(option, key, 'literalDocBook'): return [ f"<para><emphasis>{key.capitalize()}:</emphasis> {lit['text']}</para>" ] @@ -283,10 +311,19 @@ class ManpageConverter(BaseConverter): _options_by_id: dict[str, str] _links_in_last_description: Optional[list[str]] = None - def __init__(self, revision: str, markdown_by_default: bool): - self._options_by_id = {} + def __init__(self, revision: str, markdown_by_default: bool, + *, + # only for parallel rendering + _options_by_id: Optional[dict[str, str]] = None): + self._options_by_id = _options_by_id or {} super().__init__({}, revision, markdown_by_default) + def _parallel_render_prepare(self) -> Any: + return ((self._revision, self._markdown_by_default), { '_options_by_id': self._options_by_id }) + @classmethod + def _parallel_render_init_worker(cls, a: Any) -> ManpageConverter: + return cls(*a[0], **a[1]) + def _render_option(self, name: str, option: dict[str, Any]) -> RenderedOption: assert isinstance(self._md.renderer, OptionsManpageRenderer) links = self._md.renderer.link_footnotes = [] |