SF.net SVN: docutils:[9805 ] trunk/docutils

aa-turner--- via Docutils-checkins <[email protected]>
Newsgroups gmane.text.docutils.cvs
Message-ID <[email protected]>
Revision: 9805
          http://sourceforge.net/p/docutils/code/9805
Author:   aa-turner
Date:     2024-07-31 12:59:29 +0000 (Wed, 31 Jul 2024)
Log Message:
-----------
Add type hints to ``docutils.frontend``

Modified Paths:
--------------
    trunk/docutils/docutils/frontend.py
    trunk/docutils/test/test_settings.py

Modified: trunk/docutils/docutils/frontend.py
===================================================================
--- trunk/docutils/docutils/frontend.py	2024-07-31 10:44:49 UTC (rev 9804)
+++ trunk/docutils/docutils/frontend.py	2024-07-31 12:59:29 UTC (rev 9805)
@@ -50,6 +50,8 @@
   `make_paths_absolute()`, `filter_settings_spec()`. Provisional.
 """
 
+from __future__ import annotations
+
 __docformat__ = 'reStructuredText'
 
 
@@ -56,18 +58,39 @@
 import codecs
 import configparser
 import optparse
-from optparse import SUPPRESS_HELP
 import os
 import os.path
-from pathlib import Path
 import sys
 import warnings
+from optparse import SUPPRESS_HELP
+from pathlib import Path
+from typing import TYPE_CHECKING
 
 import docutils
 from docutils import io, utils
 
+if TYPE_CHECKING:
+    from collections.abc import Iterable, Mapping, Sequence
+    from typing import Any, ClassVar, Literal, Protocol
 
-def store_multiple(option, opt, value, parser, *args, **kwargs):
+    from docutils import SettingsSpec, _OptionTuple, _SettingsSpecTuple
+
+    class _OptionValidator(Protocol):
+        def __call__(  # NoQA: E704
+            self,
+            setting: str,
+            value: str | None,
+            option_parser: OptionParser,
+            /,
+            config_parser: ConfigParser | None = None,
+            config_section: str | None = None,
+        ) -> Any: ...
+
+
+def store_multiple(
+    option: optparse.Option, opt: str, value: Any, parser: OptionParser,
+    *args: str, **kwargs: Any,
+) -> None:
     """
     Store multiple values in `parser.values`.  (Option callback.)
 
@@ -80,7 +103,9 @@
         setattr(parser.values, key, value)
 
 
-def read_config_file(option, opt, value, parser):
+def read_config_file(
+    option: optparse.Option, opt: str, value: Any, parser: OptionParser,
+) -> None:
     """
     Read a configuration file during option processing.  (Option callback.)
     """
@@ -91,8 +116,13 @@
     parser.values.update(new_settings, parser)
 
 
-def validate_encoding(setting, value=None, option_parser=None,
-                      config_parser=None, config_section=None):
+def validate_encoding(
+    setting: str,
+    value: str | None = None,
+    option_parser: OptionParser | None = None,
+    config_parser: ConfigParser | None = None,
+    config_section: str | None = None,
+) -> str | None:
     # All arguments except `value` are ignored
     # (kept for compatibility with "optparse" module).
     # If there is only one positional argument, it is interpreted as `value`.
@@ -110,8 +140,13 @@
     return value
 
 
-def validate_encoding_error_handler(setting, value=None, option_parser=None,
-                                    config_parser=None, config_section=None):
+def validate_encoding_error_handler(
+    setting: str,
+    value: str | None = None,
+    option_parser: OptionParser | None = None,
+    config_parser: ConfigParser | None = None,
+    config_section: str | None = None,
+) -> str:
     # All arguments except `value` are ignored
     # (kept for compatibility with "optparse" module).
     # If there is only one positional argument, it is interpreted as `value`.
@@ -129,7 +164,12 @@
 
 
 def validate_encoding_and_error_handler(
-    setting, value, option_parser, config_parser=None, config_section=None):
+    setting: str,
+    value: str | None = None,
+    option_parser: OptionParser | None = None,
+    config_parser: ConfigParser | None = None,
+    config_section: str | None = None,
+) -> str:
     """
     Side-effect: if an error handler is included in the value, it is inserted
     into the appropriate place as if it were a separate setting/option.
@@ -147,8 +187,13 @@
     return validate_encoding(encoding)
 
 
-def validate_boolean(setting, value=None, option_parser=None,
-                     config_parser=None, config_section=None):
+def validate_boolean(
+    setting: str | bool,
+    value: str | None = None,
+    option_parser: OptionParser | None = None,
+    config_parser: ConfigParser | None = None,
+    config_section: str | None = None,
+) -> bool:
     """Check/normalize boolean settings:
          True:  '1', 'on', 'yes', 'true'
          False: '0', 'off', 'no','false', ''
@@ -167,8 +212,13 @@
         raise LookupError('unknown boolean value: "%s"' % value)
 
 
-def validate_ternary(setting, value=None, option_parser=None,
-                     config_parser=None, config_section=None):
+def validate_ternary(
+    setting: str | bool,
+    value: str | None = None,
+    option_parser: OptionParser | None = None,
+    config_parser: ConfigParser | None = None,
+    config_section: str | None = None,
+) -> str | bool | None:
     """Check/normalize three-value settings:
          True:  '1', 'on', 'yes', 'true'
          False: '0', 'off', 'no','false', ''
@@ -188,8 +238,13 @@
         return value
 
 
-def validate_nonnegative_int(setting, value=None, option_parser=None,
-                             config_parser=None, config_section=None):
+def validate_nonnegative_int(
+    setting: str,
+    value: str | None = None,
+    option_parser: OptionParser | None = None,
+    config_parser: ConfigParser | None = None,
+    config_section: str | None = None,
+) -> int:
     # All arguments except `value` are ignored
     # (kept for compatibility with "optparse" module).
     # If there is only one positional argument, it is interpreted as `value`.
@@ -201,8 +256,13 @@
     return value
 
 
-def validate_threshold(setting, value=None, option_parser=None,
-                       config_parser=None, config_section=None):
+def validate_threshold(
+    setting: str,
+    value: str | None = None,
+    option_parser: OptionParser | None = None,
+    config_parser: ConfigParser | None = None,
+    config_section: str | None = None,
+) -> int:
     # All arguments except `value` are ignored
     # (kept for compatibility with "optparse" module).
     # If there is only one positional argument, it is interpreted as `value`.
@@ -218,8 +278,12 @@
 
 
 def validate_colon_separated_string_list(
-        setting, value=None, option_parser=None,
-        config_parser=None, config_section=None):
+    setting: str | list[str],
+    value: str | None = None,
+    option_parser: OptionParser | None = None,
+    config_parser: ConfigParser | None = None,
+    config_section: str | None = None,
+) -> list[str]:
     # All arguments except `value` are ignored
     # (kept for compatibility with "optparse" module).
     # If there is only one positional argument, it is interpreted as `value`.
@@ -233,8 +297,13 @@
     return value
 
 
-def validate_comma_separated_list(setting, value=None, option_parser=None,
-                                  config_parser=None, config_section=None):
+def validate_comma_separated_list(
+    setting: str | list[str] | list[str | tuple[str, str]],
+    value: str | None = None,
+    option_parser: OptionParser | None = None,
+    config_parser: ConfigParser | None = None,
+    config_section: str | None = None,
+) -> list[str]:
     """Check/normalize list arguments (split at "," and strip whitespace).
 
     All arguments except `value` are ignored
@@ -255,8 +324,13 @@
     return value
 
 
-def validate_math_output(setting, value=None, option_parser=None,
-                         config_parser=None, config_section=None):
+def validate_math_output(
+    setting: str,
+    value: str | None = None,
+    option_parser: OptionParser | None = None,
+    config_parser: ConfigParser | None = None,
+    config_section: str | None = None,
+) -> tuple[()] | tuple[str, str]:
     """Check "math-output" setting, return list with "format" and "options".
 
     See also https://docutils.sourceforge.io/docs/user/config.html#math-output
@@ -272,7 +346,7 @@
     tex2mathml_converters = ('', 'latexml', 'ttm', 'blahtexml', 'pandoc')
 
     if not value:
-        return []
+        return ()
     values = value.split(maxsplit=1)
     format = values[0].lower()
     try:
@@ -288,11 +362,16 @@
             raise LookupError(f'MathML converter "{options}" not supported,\n'
                               f'    choose from {tex2mathml_converters}.')
         options = converter
-    return [format, options]
+    return format, options
 
 
-def validate_url_trailing_slash(setting, value=None, option_parser=None,
-                                config_parser=None, config_section=None):
+def validate_url_trailing_slash(
+    setting: str | None,
+    value: str | None = None,
+    option_parser: OptionParser | None = None,
+    config_parser: ConfigParser | None = None,
+    config_section: str | None = None,
+) -> str:
     # All arguments except `value` are ignored
     # (kept for compatibility with "optparse" module).
     # If there is only one positional argument, it is interpreted as `value`.
@@ -306,8 +385,13 @@
         return value + '/'
 
 
-def validate_dependency_file(setting, value=None, option_parser=None,
-                             config_parser=None, config_section=None):
+def validate_dependency_file(
+    setting: str | None,
+    value: str | None = None,
+    option_parser: OptionParser | None = None,
+    config_parser: ConfigParser | None = None,
+    config_section: str | None = None,
+) -> utils.DependencyList:
     # All arguments except `value` are ignored
     # (kept for compatibility with "optparse" module).
     # If there is only one positional argument, it is interpreted as `value`.
@@ -320,8 +404,13 @@
         return utils.DependencyList(None)
 
 
-def validate_strip_class(setting, value=None, option_parser=None,
-                         config_parser=None, config_section=None):
+def validate_strip_class(
+    setting: str,
+    value: str | None = None,
+    option_parser: OptionParser | None = None,
+    config_parser: ConfigParser | None = None,
+    config_section: str | None = None,
+) -> list[str]:
     # All arguments except `value` are ignored
     # (kept for compatibility with "optparse" module).
     # If there is only one positional argument, it is interpreted as `value`.
@@ -338,8 +427,13 @@
     return value
 
 
-def validate_smartquotes_locales(setting, value=None, option_parser=None,
-                                 config_parser=None, config_section=None):
+def validate_smartquotes_locales(
+    setting: str | list[str | tuple[str, str]],
+    value: str | None = None,
+    option_parser: OptionParser | None = None,
+    config_parser: ConfigParser | None = None,
+    config_section: str | None = None,
+) -> list[tuple[str, Sequence[str]]]:
     """Check/normalize a comma separated list of smart quote definitions.
 
     Return a list of (language-tag, quotes) string tuples.
@@ -379,7 +473,11 @@
     return lc_quotes
 
 
-def make_paths_absolute(pathdict, keys, base_path=None):
+def make_paths_absolute(
+    pathdict: dict[str, list[str | os.PathLike[str]] | str | os.PathLike[str]],
+    keys: list[str],
+    base_path: str | os.PathLike[str] | None = None,
+) -> None:
     """
     Interpret filesystem path settings relative to the `base_path` given.
 
@@ -402,7 +500,9 @@
             pathdict[key] = value
 
 
-def make_one_path_absolute(base_path, path):
+def make_one_path_absolute(
+    base_path: str | os.PathLike[str], path: str | os.PathLike[str],
+) -> str:
     # deprecated, will be removed
     warnings.warn('frontend.make_one_path_absolute() will be removed '
                   'in Docutils 0.23.', DeprecationWarning, stacklevel=2)
@@ -409,7 +509,11 @@
     return os.path.abspath(os.path.join(base_path, path))
 
 
-def filter_settings_spec(settings_spec, *exclude, **replace):
+def filter_settings_spec(
+    settings_spec: _SettingsSpecTuple,
+    *exclude: str,
+    **replace: _OptionTuple,
+) -> _SettingsSpecTuple:
     """Return a copy of `settings_spec` excluding/replacing some settings.
 
     `settings_spec` is a tuple of configuration settings
@@ -422,7 +526,7 @@
     settings = list(settings_spec)
     # every third item is a sequence of option tuples
     for i in range(2, len(settings), 3):
-        newopts = []
+        newopts: list[_OptionTuple] = []
         for opt_spec in settings[i]:
             # opt_spec is ("<help>", [<option strings>], {<keyword args>})
             opt_name = [opt_string[2:].replace('-', '_')
@@ -447,16 +551,20 @@
     Deprecated. Will be removed.
     """
 
-    def __init__(self, *args, **kwargs):
+    def __init__(self, defaults: dict[str, Any] | None = None) -> None:
         warnings.warn('frontend.Values class will be removed '
                       'in Docutils 0.21 or later.',
                       DeprecationWarning, stacklevel=2)
-        super().__init__(*args, **kwargs)
+        super().__init__(defaults=defaults)
         if getattr(self, 'record_dependencies', None) is None:
             # Set up dummy dependency list.
             self.record_dependencies = utils.DependencyList()
 
-    def update(self, other_dict, option_parser):
+    def update(
+        self,
+        other_dict: Values | Mapping[str, Any],
+        option_parser: OptionParser,
+    ) -> None:
         if isinstance(other_dict, Values):
             other_dict = other_dict.__dict__
         other_dict = dict(other_dict)  # also works with ConfigParser sections
@@ -468,13 +576,13 @@
                     del other_dict[setting]
         self._update_loose(other_dict)
 
-    def copy(self):
+    def copy(self) -> Values:
         """Return a shallow copy of `self`."""
         with warnings.catch_warnings():
             warnings.filterwarnings('ignore', category=DeprecationWarning)
             return self.__class__(defaults=self.__dict__)
 
-    def setdefault(self, name, default):
+    def setdefault(self, name: str, default: Any) -> Any:
         """Return ``self.name`` or ``default``.
 
         If ``self.name`` is unset, set ``self.name = default``.
@@ -492,13 +600,18 @@
 
     ATTRS = optparse.Option.ATTRS + ['validator', 'overrides']
 
-    def __init__(self, *args, **kwargs):
+    validator: _OptionValidator
+    overrides: str | None
+
+    def __init__(self, *args: str | None, **kwargs: Any) -> None:
         warnings.warn('The frontend.Option class will be removed '
                       'in Docutils 0.21 or later.',
                       DeprecationWarning, stacklevel=2)
         super().__init__(*args, **kwargs)
 
-    def process(self, opt, value, values, parser):
+    def process(
+        self, opt: str, value: Any, values: Values, parser: OptionParser,
+    ) -> int:
         """
         Call the validator function on applicable settings and
         evaluate the 'overrides' option.
@@ -537,7 +650,7 @@
     Will be replaced by a subclass of `argparse.ArgumentParser`.
     """
 
-    standard_config_files = [
+    standard_config_files: ClassVar[list[str]] = [
         '/etc/docutils.conf',           # system-wide
         './docutils.conf',              # project-specific
         '~/.docutils']                  # user-specific
@@ -546,21 +659,29 @@
     Filenames will be tilde-expanded later. Later files override earlier ones.
     """
 
-    threshold_choices = 'info 1 warning 2 error 3 severe 4 none 5'.split()
+    threshold_choices: ClassVar[list[str]] = [
+        'info', '1', 'warning', '2', 'error', '3', 'severe', '4', 'none', '5',
+    ]
     """Possible inputs for for --report and --halt threshold values."""
 
-    thresholds = {'info': 1, 'warning': 2, 'error': 3, 'severe': 4, 'none': 5}
+    thresholds: ClassVar[dict[str, int]] = {
+        'info': 1, 'warning': 2, 'error': 3, 'severe': 4, 'none': 5,
+    }
     """Lookup table for --report and --halt threshold values."""
 
-    booleans = {'1': True, 'on': True, 'yes': True, 'true': True, '0': False,
-                'off': False, 'no': False, 'false': False, '': False}
+    booleans: ClassVar[dict[str, bool]] = {
+        '1': True, 'on': True, 'yes': True, 'true': True,
+        '0': False, 'off': False, 'no': False, 'false': False, '': False,
+    }
     """Lookup table for boolean configuration file settings."""
 
-    default_error_encoding = (getattr(sys.stderr, 'encoding', None)
-                              or io._locale_encoding  # noqa
-                              or 'ascii')
+    default_error_encoding: ClassVar[str] = (
+        getattr(sys.stderr, 'encoding', None)
+        or io._locale_encoding  # noqa
+        or 'ascii'
+    )
 
-    default_error_encoding_error_handler = 'backslashreplace'
+    default_error_encoding_error_handler: ClassVar[str] = 'backslashreplace'
 
     settings_spec = (
         'General Docutils Options',
@@ -748,17 +869,26 @@
     See https://docutils.sourceforge.io/docs/user/config.html#internal-settings
     """
 
+    relative_path_settings: tuple[str, ...] = ()  # will be modified
+
     config_section = 'general'
 
-    version_template = ('%%prog (Docutils %s%s, Python %s, on %s)'
-                        % (docutils.__version__,
-                           docutils.__version_details__
-                           and ' [%s]'%docutils.__version_details__ or '',
-                           sys.version.split()[0], sys.platform))
+    version_template: ClassVar[str] = '%%prog (Docutils %s%s, Python %s, on %s)' % (  # NoQA: E501
+        docutils.__version__,
+        (details := docutils.__version_details__) and f' [{details}]' or '',
+        sys.version.split()[0],
+        sys.platform,
+    )
     """Default version message."""
 
-    def __init__(self, components=(), defaults=None, read_config_files=False,
-                 *args, **kwargs):
+    def __init__(
+        self,
+        components: Iterable[SettingsSpec] = (),
+        defaults: Mapping[str, Any] | None = None,
+        read_config_files: bool | None = False,
+        *args,
+        **kwargs,
+    ) -> None:
         """Set up OptionParser instance.
 
         `components` is a list of Docutils components each containing a
@@ -766,24 +896,24 @@
         `defaults` is a mapping of setting default overrides.
         """
 
-        self.lists = {}
+        self.lists: dict[str, Literal[True]] = {}
         """Set of list-type settings."""
 
-        self.config_files = []
+        self.config_files: list[str] = []
         """List of paths of applied configuration files."""
 
-        self.relative_path_settings = ['warning_stream']  # will be modified
+        self.relative_path_settings = ('warning_stream',)  # will be modified
 
         warnings.warn('The frontend.OptionParser class will be replaced '
                       'by a subclass of argparse.ArgumentParser '
                       'in Docutils 0.21 or later.',
                       DeprecationWarning, stacklevel=2)
-        super().__init__(option_class=Option, add_help_option=None,
+        super().__init__(option_class=Option, add_help_option=False,
                          formatter=optparse.TitledHelpFormatter(width=78),
                          *args, **kwargs)
         if not self.version:
             self.version = self.version_template
-        self.components = (self, *components)
+        self.components: tuple[SettingsSpec, ...] = (self, *components)
         self.populate_from_components(self.components)
         self.defaults.update(defaults or {})
         if read_config_files and not self.defaults['_disable_config']:
@@ -790,10 +920,12 @@
             try:
                 config_settings = self.get_standard_config_settings()
             except ValueError as err:
-                self.error(err)
+                self.error(str(err))
             self.defaults.update(config_settings.__dict__)
 
-    def populate_from_components(self, components):
+    def populate_from_components(
+        self, components: Iterable[SettingsSpec],
+    ) -> None:
         """Collect settings specification from components.
 
         For each component, populate from the `SettingsSpec.settings_spec`
@@ -805,8 +937,7 @@
             if component is None:
                 continue
             settings_spec = component.settings_spec
-            self.relative_path_settings.extend(
-                component.relative_path_settings)
+            self.relative_path_settings += component.relative_path_settings
             for i in range(0, len(settings_spec), 3):
                 title, description, option_spec = settings_spec[i:i+3]
                 if title:
@@ -826,7 +957,7 @@
                 self.defaults.update(component.settings_default_overrides)
 
     @classmethod
-    def get_standard_config_files(cls):
+    def get_standard_config_files(cls) -> Sequence[str | os.PathLike[str]]:
         """Return list of config files, from environment or standard."""
         if 'DOCUTILSCONFIG' in os.environ:
             config_files = os.environ['DOCUTILSCONFIG'].split(os.pathsep)
@@ -834,7 +965,7 @@
             config_files = cls.standard_config_files
         return [os.path.expanduser(f) for f in config_files if f.strip()]
 
-    def get_standard_config_settings(self):
+    def get_standard_config_settings(self) -> Values:
         with warnings.catch_warnings():
             warnings.filterwarnings('ignore', category=DeprecationWarning)
             settings = Values()
@@ -842,7 +973,7 @@
             settings.update(self.get_config_file_settings(filename), self)
         return settings
 
-    def get_config_file_settings(self, config_file):
+    def get_config_file_settings(self, config_file: str) -> dict[str, Any]:
         """Returns a dictionary containing appropriate config file settings."""
         config_parser = ConfigParser()
         # parse config file, add filename if found and successfully read.
@@ -862,18 +993,18 @@
                 if config_parser.has_section(section):
                     settings.update(config_parser[section], self)
         make_paths_absolute(settings.__dict__,
-                            self.relative_path_settings,
+                            list(self.relative_path_settings),
                             os.path.dirname(config_file))
         return settings.__dict__
 
-    def check_values(self, values, args):
+    def check_values(self, values: Values, args: list[str]) -> Values:
         """Store positional arguments as runtime settings."""
         values._source, values._destination = self.check_args(args)
-        make_paths_absolute(values.__dict__, self.relative_path_settings)
+        make_paths_absolute(values.__dict__, list(self.relative_path_settings))
         values._config_files = self.config_files
         return values
 
-    def check_args(self, args):
+    def check_args(self, args: list[str]) -> tuple[str | None, str | None]:
         source = destination = None
         if args:
             source = args.pop(0)
@@ -890,7 +1021,7 @@
                        'destination.  It will clobber the source file.')
         return source, destination
 
-    def set_defaults_from_dict(self, defaults):
+    def set_defaults_from_dict(self, defaults: dict[str, Any]) -> None:
         # deprecated, will be removed
         warnings.warn('OptionParser.set_defaults_from_dict() will be removed '
                       'in Docutils 0.22 or with the switch to ArgumentParser.',
@@ -897,7 +1028,7 @@
                       DeprecationWarning, stacklevel=2)
         self.defaults.update(defaults)
 
-    def get_default_values(self):
+    def get_default_values(self) -> Values:
         """Needed to get custom `Values` instances."""
         with warnings.catch_warnings():
             warnings.filterwarnings('ignore', category=DeprecationWarning)
@@ -905,7 +1036,7 @@
         defaults._config_files = self.config_files
         return defaults
 
-    def get_option_by_dest(self, dest):
+    def get_option_by_dest(self, dest: str) -> Option:
         """
         Get an option by its dest.
 
@@ -935,7 +1066,7 @@
     This class is provisional and will change in future versions.
     """
 
-    old_settings = {
+    old_settings: ClassVar[dict[str, tuple[str, str]]] = {
         'pep_stylesheet': ('pep_html writer', 'stylesheet'),
         'pep_stylesheet_path': ('pep_html writer', 'stylesheet_path'),
         'pep_template': ('pep_html writer', 'template')}
@@ -943,7 +1074,7 @@
     `handle_old_config`, to convert settings from the old [options] section.
     """
 
-    old_warning = (
+    old_warning: ClassVar[str] = (
         'The "[option]" section is deprecated.\n'
         'Support for old-format configuration files will be removed in '
         'Docutils 2.0.  Please revise your configuration files.  '
@@ -950,12 +1081,16 @@
         'See <https://docutils.sourceforge.io/docs/user/config.html>, '
         'section "Old-Format Configuration Files".')
 
-    not_utf8_error = """\
+    not_utf8_error: ClassVar[str] = """\
 Unable to read configuration file "%s": content not encoded as UTF-8.
 Skipping "%s" configuration file.
 """
 
-    def read(self, filenames, option_parser=None):
+    def read(
+        self,
+        filenames: str | Sequence[str],
+        option_parser: OptionParser | None = None,
+    ) -> list[str]:
         # Currently, if a `docutils.frontend.OptionParser` instance is
         # supplied, setting values are validated.
         if option_parser is not None:
@@ -979,7 +1114,7 @@
                 self.validate_settings(filename, option_parser)
         return read_ok
 
-    def handle_old_config(self, filename):
+    def handle_old_config(self, filename: str) -> None:
         warnings.warn_explicit(self.old_warning, ConfigDeprecationWarning,
                                filename, 0)
         options = self.get_section('options')
@@ -997,7 +1132,9 @@
                 self.set(section, setting, value)
         self.remove_section('options')
 
-    def validate_settings(self, filename, option_parser):
+    def validate_settings(
+        self, filename: str, option_parser: OptionParser,
+    ) -> None:
         """
         Call the validator function and implement overrides on all applicable
         settings.
@@ -1023,7 +1160,7 @@
                 if option.overrides:
                     self.set(section, option.overrides, None)
 
-    def optionxform(self, optionstr):
+    def optionxform(self, optionstr: str) -> str:
         """
         Lowercase and transform '-' to '_'.
 
@@ -1031,7 +1168,7 @@
         """
         return optionstr.lower().replace('-', '_')
 
-    def get_section(self, section):
+    def get_section(self, section: str) -> dict[str, str]:
         """
         Return a given section as a dictionary.
 
@@ -1053,7 +1190,7 @@
     """Warning for deprecated configuration file features."""
 
 
-def get_default_settings(*components):
+def get_default_settings(*components: SettingsSpec) -> Values:
     """Return default runtime settings for `components`.
 
     Return a `frontend.Values` instance with defaults for generic Docutils

Modified: trunk/docutils/test/test_settings.py
===================================================================
--- trunk/docutils/test/test_settings.py	2024-07-31 10:44:49 UTC (rev 9804)
+++ trunk/docutils/test/test_settings.py	2024-07-31 12:59:29 UTC (rev 9805)
@@ -332,12 +332,12 @@
             self.assertEqual(frontend.validate_comma_separated_list(v), result)
 
     def test_validate_math_output(self):
-        tests = (('', []),
-                 ('LaTeX ', ['latex', '']),
-                 ('MathML', ['mathml', '']),
-                 ('MathML  PanDoc', ['mathml', 'pandoc']),
-                 ('HTML  math.css, X.css', ['html', 'math.css, X.css']),
-                 ('MathJax  /MathJax.js', ['mathjax', '/MathJax.js']),
+        tests = (('', ()),
+                 ('LaTeX ', ('latex', '')),
+                 ('MathML', ('mathml', '')),
+                 ('MathML  PanDoc', ('mathml', 'pandoc')),
+                 ('HTML  math.css, X.css', ('html', 'math.css, X.css')),
+                 ('MathJax  /MathJax.js', ('mathjax', '/MathJax.js')),
                  )
         for v, result in tests:
             self.assertEqual(frontend.validate_math_output(v), result)

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.



_______________________________________________
Docutils-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/docutils-checkins
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.