1# $Id$
2# Author: David Goodger <goodger@python.org>
3# Copyright: This module has been placed in the public domain.
4
5"""
6This is the Docutils (Python Documentation Utilities) package.
7
8Package Structure
9=================
10
11Modules:
12
13- __init__.py: Contains component base classes, exception classes, and
14 Docutils version information.
15
16- core.py: Contains the ``Publisher`` class and ``publish_*()`` convenience
17 functions.
18
19- frontend.py: Runtime settings (command-line interface, configuration files)
20 processing, for Docutils front-ends.
21
22- io.py: Provides a uniform API for low-level input and output.
23
24- nodes.py: Docutils document tree (doctree) node class library.
25
26- statemachine.py: A finite state machine specialized for
27 regular-expression-based text filters.
28
29Subpackages:
30
31- languages: Language-specific mappings of terms.
32
33- parsers: Syntax-specific input parser modules or packages.
34
35- readers: Context-specific input handlers which understand the data
36 source and manage a parser.
37
38- transforms: Modules used by readers and writers to modify
39 the Docutils document tree.
40
41- utils: Contains the ``Reporter`` system warning class and miscellaneous
42 utilities used by readers, writers, and transforms.
43
44 utils/urischemes.py: Contains a complete mapping of known URI addressing
45 scheme names to descriptions.
46
47- utils/math: Contains functions for conversion of mathematical notation
48 between different formats (LaTeX, MathML, text, ...).
49
50- writers: Format-specific output translators.
51"""
52
53from collections import namedtuple
54
55__docformat__ = 'reStructuredText'
56
57__version__ = '0.22b.dev'
58"""Docutils version identifier (complies with PEP 440)::
59
60 major.minor[.micro][releaselevel[serial]][.dev]
61
62For version comparison operations, use `__version_info__` (see, below)
63rather than parsing the text of `__version__`.
64
65https://docutils.sourceforge.io/docs/dev/policies.html#version-identification
66"""
67
68__version_details__ = ''
69"""Optional extra version details (e.g. 'snapshot 2005-05-29, r3410').
70
71For development and release status, use `__version__ and `__version_info__`.
72"""
73
74
75class VersionInfo(namedtuple('VersionInfo',
76 'major minor micro releaselevel serial release')):
77
78 def __new__(cls, major=0, minor=0, micro=0,
79 releaselevel='final', serial=0, release=True):
80 releaselevels = ('alpha', 'beta', 'candidate', 'final')
81 if releaselevel not in releaselevels:
82 raise ValueError('releaselevel must be one of %r.'
83 % (releaselevels, ))
84 if releaselevel == 'final':
85 if not release:
86 raise ValueError('releaselevel "final" must not be used '
87 'with development versions (leads to wrong '
88 'version ordering of the related __version__')
89 # cf. https://peps.python.org/pep-0440/#summary-of-permitted-suffixes-and-relative-ordering # noqa
90 if serial != 0:
91 raise ValueError('"serial" must be 0 for final releases')
92
93 return super().__new__(cls, major, minor, micro,
94 releaselevel, serial, release)
95
96 def __lt__(self, other):
97 if isinstance(other, tuple):
98 other = VersionInfo(*other)
99 return tuple.__lt__(self, other)
100
101 def __gt__(self, other):
102 if isinstance(other, tuple):
103 other = VersionInfo(*other)
104 return tuple.__gt__(self, other)
105
106 def __le__(self, other):
107 if isinstance(other, tuple):
108 other = VersionInfo(*other)
109 return tuple.__le__(self, other)
110
111 def __ge__(self, other):
112 if isinstance(other, tuple):
113 other = VersionInfo(*other)
114 return tuple.__ge__(self, other)
115
116
117__version_info__ = VersionInfo(
118 major=0,
119 minor=22,
120 micro=0,
121 releaselevel='beta', # one of 'alpha', 'beta', 'candidate', 'final'
122 serial=0, # pre-release number (0 for final releases and snapshots)
123 release=False # True for official releases and pre-releases
124 )
125"""Comprehensive version information tuple.
126
127https://docutils.sourceforge.io/docs/dev/policies.html#version-identification
128"""
129
130
131class ApplicationError(Exception): pass
132class DataError(ApplicationError): pass
133
134
135class SettingsSpec:
136
137 """
138 Runtime setting specification base class.
139
140 SettingsSpec subclass objects used by `docutils.frontend.OptionParser`.
141 """
142
143 # TODO: replace settings_specs with a new data structure
144 # Backwards compatiblity:
145 # Drop-in components:
146 # Sphinx supplies settings_spec in the current format in some places
147 # Myst parser provides a settings_spec tuple
148 #
149 # Sphinx reads a settings_spec in order to set a default value
150 # in writers/html.py:59
151 # https://github.com/sphinx-doc/sphinx/blob/4.x/sphinx/writers/html.py
152 # This should be changed (before retiring the old format)
153 # to use `settings_default_overrides` instead.
154 settings_spec = ()
155 """Runtime settings specification. Override in subclasses.
156
157 Defines runtime settings and associated command-line options, as used by
158 `docutils.frontend.OptionParser`. This is a tuple of:
159
160 - Option group title (string or `None` which implies no group, just a list
161 of single options).
162
163 - Description (string or `None`).
164
165 - A sequence of option tuples. Each consists of:
166
167 - Help text (string)
168
169 - List of option strings (e.g. ``['-Q', '--quux']``).
170
171 - Dictionary of keyword arguments sent to the OptionParser/OptionGroup
172 ``add_option`` method.
173
174 Runtime setting names are derived implicitly from long option names
175 ('--a-setting' becomes ``settings.a_setting``) or explicitly from the
176 'dest' keyword argument.
177
178 Most settings will also have a 'validator' keyword & function. The
179 validator function validates setting values (from configuration files
180 and command-line option arguments) and converts them to appropriate
181 types. For example, the ``docutils.frontend.validate_boolean``
182 function, **required by all boolean settings**, converts true values
183 ('1', 'on', 'yes', and 'true') to 1 and false values ('0', 'off',
184 'no', 'false', and '') to 0. Validators need only be set once per
185 setting. See the `docutils.frontend.validate_*` functions.
186
187 See the optparse docs for more details.
188
189 - More triples of group title, description, options, as many times as
190 needed. Thus, `settings_spec` tuples can be simply concatenated.
191 """
192
193 settings_defaults = None
194 """A dictionary of defaults for settings not in `settings_spec` (internal
195 settings, intended to be inaccessible by command-line and config file).
196 Override in subclasses."""
197
198 settings_default_overrides = None
199 """A dictionary of auxiliary defaults, to override defaults for settings
200 defined in other components' `setting_specs`. Override in subclasses."""
201
202 relative_path_settings = ()
203 """Settings containing filesystem paths. Override in subclasses.
204 Settings listed here are to be interpreted relative to the current working
205 directory."""
206
207 config_section = None
208 """The name of the config file section specific to this component
209 (lowercase, no brackets). Override in subclasses."""
210
211 config_section_dependencies = None
212 """A list of names of config file sections that are to be applied before
213 `config_section`, in order (from general to specific). In other words,
214 the settings in `config_section` are to be overlaid on top of the settings
215 from these sections. The "general" section is assumed implicitly.
216 Override in subclasses."""
217
218
219class TransformSpec:
220 """
221 Runtime transform specification base class.
222
223 Provides the interface to register "transforms" and helper functions
224 to resolve references with a `docutils.transforms.Transformer`.
225
226 https://docutils.sourceforge.io/docs/ref/transforms.html
227 """
228
229 def get_transforms(self):
230 """Transforms required by this class. Override in subclasses."""
231 if self.default_transforms != ():
232 import warnings
233 warnings.warn('TransformSpec: the "default_transforms" attribute '
234 'will be removed in Docutils 2.0.\n'
235 'Use get_transforms() method instead.',
236 DeprecationWarning)
237 return list(self.default_transforms)
238 return []
239
240 # Deprecated; for compatibility.
241 default_transforms = ()
242
243 unknown_reference_resolvers = ()
244 """List of functions to try to resolve unknown references.
245
246 Unknown references have a 'refname' attribute which doesn't correspond
247 to any target in the document. Called when the transforms in
248 `docutils.transforms.references` are unable to find a correct target.
249
250 The list should contain functions which will try to resolve unknown
251 references, with the following signature::
252
253 def reference_resolver(node):
254 '''Returns boolean: true if resolved, false if not.'''
255
256 If the function is able to resolve the reference, it should also remove
257 the 'refname' attribute and mark the node as resolved::
258
259 del node['refname']
260 node.resolved = 1
261
262 Each function must have a "priority" attribute which will affect the order
263 the unknown_reference_resolvers are run::
264
265 reference_resolver.priority = 100
266
267 This hook is provided for 3rd party extensions.
268 Example use case: the `MoinMoin - ReStructured Text Parser`
269 in ``sandbox/mmgilbe/rst.py``.
270 """
271
272
273class Component(SettingsSpec, TransformSpec):
274
275 """Base class for Docutils components."""
276
277 component_type = None
278 """Name of the component type ('reader', 'parser', 'writer'). Override in
279 subclasses."""
280
281 supported = ()
282 """Name and aliases for this component. Override in subclasses."""
283
284 def supports(self, format):
285 """
286 Is `format` supported by this component?
287
288 To be used by transforms to ask the dependent component if it supports
289 a certain input context or output format.
290 """
291 return format in self.supported