|
From: <aa-...@us...> - 2024-07-31 12:59:35
|
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.
|