[Zope-Checkins] CVS: Zope/lib/python/docutils - __init__.py:1.2 core.py:1.2 frontend.py:1.2 io.py:1.2 nodes.py:1.2 optik.py:1.2 roman.py:1.2 statemachine.py:1.2 urischemes.py:1.2 utils.py:1.2
Andreas Jung
andreas@andreas-jung.com
Sat, 1 Feb 2003 04:26:35 -0500
Update of /cvs-repository/Zope/lib/python/docutils
In directory cvs.zope.org:/tmp/cvs-serv18056/docutils
Added Files:
__init__.py core.py frontend.py io.py nodes.py optik.py
roman.py statemachine.py urischemes.py utils.py
Log Message:
merge from ajung-restructuredtext-integration-branch
=== Zope/lib/python/docutils/__init__.py 1.1 => 1.2 ===
--- /dev/null Sat Feb 1 04:26:33 2003
+++ Zope/lib/python/docutils/__init__.py Sat Feb 1 04:26:00 2003
@@ -0,0 +1,130 @@
+# Author: David Goodger
+# Contact: goodger@users.sourceforge.net
+# Revision: $Revision$
+# Date: $Date$
+# Copyright: This module has been placed in the public domain.
+
+"""
+This is the Docutils (Python Documentation Utilities) package.
+
+Package Structure
+=================
+
+Modules:
+
+- __init__.py: Contains the package docstring only (this text).
+
+- core.py: Contains the ``Publisher`` class and ``publish()`` convenience
+ function.
+
+- frontend.py: Command-line and common processing for Docutils front-ends.
+
+- io.py: Provides a uniform API for low-level input and output.
+
+- nodes.py: Docutils document tree (doctree) node class library.
+
+- optik.py: Option parsing and command-line help; from Greg Ward's
+ http://optik.sf.net/ project, included for convenience.
+
+- roman.py: Conversion to and from Roman numerals. Courtesy of Mark
+ Pilgrim (http://diveintopython.org/).
+
+- statemachine.py: A finite state machine specialized for
+ regular-expression-based text filters.
+
+- urischemes.py: Contains a complete mapping of known URI addressing
+ scheme names to descriptions.
+
+- utils.py: Contains the ``Reporter`` system warning class and miscellaneous
+ utilities.
+
+Subpackages:
+
+- languages: Language-specific mappings of terms.
+
+- parsers: Syntax-specific input parser modules or packages.
+
+- readers: Context-specific input handlers which understand the data
+ source and manage a parser.
+
+- transforms: Modules used by readers and writers to modify DPS
+ doctrees.
+
+- writers: Format-specific output translators.
+"""
+
+__docformat__ = 'reStructuredText'
+
+__version__ = '0.2.8'
+"""``major.minor.micro`` version number. The micro number is bumped any time
+there's a change in the API incompatible with one of the front ends. The
+minor number is bumped whenever there is a project release. The major number
+will be bumped when the project is complete, and perhaps if there is a major
+change in the design."""
+
+
+class ApplicationError(StandardError): pass
+class DataError(ApplicationError): pass
+
+
+class SettingsSpec:
+
+ """
+ Runtime setting specification base class.
+
+ SettingsSpec subclass objects used by `docutils.frontend.OptionParser`.
+ """
+
+ settings_spec = ()
+ """Runtime settings specification. Override in subclasses.
+
+ Specifies runtime settings and associated command-line options, as used by
+ `docutils.frontend.OptionParser`. This tuple contains one or more sets of
+ option group title, description, and a list/tuple of tuples: ``('help
+ text', [list of option strings], {keyword arguments})``. Group title
+ and/or description may be `None`; no group title implies no group, just a
+ list of single options. Runtime settings names are derived implicitly
+ from long option names ("--a-setting" becomes ``settings.a_setting``) or
+ explicitly from the "destination" keyword argument."""
+
+ settings_default_overrides = None
+ """A dictionary of auxiliary defaults, to override defaults for settings
+ defined in other components. Override in subclasses."""
+
+ relative_path_settings = ()
+ """Settings containing filesystem paths. Override in subclasses.
+
+ Settings listed here are to be interpreted relative to the current working
+ directory."""
+
+
+class TransformSpec:
+
+ """
+ Runtime transform specification base class.
+
+ TransformSpec subclass objects used by `docutils.transforms.Transformer`.
+ """
+
+ default_transforms = ()
+ """Transforms required by this class. Override in subclasses."""
+
+
+class Component(SettingsSpec, TransformSpec):
+
+ """Base class for Docutils components."""
+
+ component_type = None
+ """Override in subclasses."""
+
+ supported = ()
+ """Names for this component. Override in subclasses."""
+
+ def supports(self, format):
+ """
+ Is `format` supported by this component?
+
+ To be used by transforms to ask the dependent component if it supports
+ a certain input context or output format.
+ """
+ return format in self.supported
=== Zope/lib/python/docutils/core.py 1.1 => 1.2 ===
--- /dev/null Sat Feb 1 04:26:33 2003
+++ Zope/lib/python/docutils/core.py Sat Feb 1 04:26:00 2003
@@ -0,0 +1,326 @@
+# Authors: David Goodger
+# Contact: goodger@users.sourceforge.net
+# Revision: $Revision$
+# Date: $Date$
+# Copyright: This module has been placed in the public domain.
+
+"""
+Calling the ``publish_*`` convenience functions (or instantiating a
+`Publisher` object) with component names will result in default
+behavior. For custom behavior (setting component options), create
+custom component objects first, and pass *them* to
+``publish_*``/`Publisher`.
+"""
+
+__docformat__ = 'reStructuredText'
+
+import sys
+from docutils import Component
+from docutils import frontend, io, readers, parsers, writers
+from docutils.frontend import OptionParser, ConfigParser
+
+
+class Publisher:
+
+ """
+ A facade encapsulating the high-level logic of a Docutils system.
+ """
+
+ def __init__(self, reader=None, parser=None, writer=None,
+ source=None, source_class=io.FileInput,
+ destination=None, destination_class=io.FileOutput,
+ settings=None):
+ """
+ Initial setup. If any of `reader`, `parser`, or `writer` are not
+ specified, the corresponding ``set_...`` method should be called with
+ a component name (`set_reader` sets the parser as well).
+ """
+
+ self.reader = reader
+ """A `readers.Reader` instance."""
+
+ self.parser = parser
+ """A `parsers.Parser` instance."""
+
+ self.writer = writer
+ """A `writers.Writer` instance."""
+
+ self.source = source
+ """The source of input data, an `io.Input` instance."""
+
+ self.source_class = source_class
+ """The class for dynamically created source objects."""
+
+ self.destination = destination
+ """The destination for docutils output, an `io.Output` instance."""
+
+ self.destination_class = destination_class
+ """The class for dynamically created destination objects."""
+
+ self.settings = settings
+ """An object containing Docutils settings as instance attributes.
+ Set by `self.process_command_line()` or `self.get_settings()`."""
+
+ def set_reader(self, reader_name, parser, parser_name):
+ """Set `self.reader` by name."""
+ reader_class = readers.get_reader_class(reader_name)
+ self.reader = reader_class(parser, parser_name)
+ self.parser = self.reader.parser
+
+ def set_writer(self, writer_name):
+ """Set `self.writer` by name."""
+ writer_class = writers.get_writer_class(writer_name)
+ self.writer = writer_class()
+
+ def set_components(self, reader_name, parser_name, writer_name):
+ if self.reader is None:
+ self.set_reader(reader_name, self.parser, parser_name)
+ if self.parser is None:
+ if self.reader.parser is None:
+ self.reader.set_parser(parser_name)
+ self.parser = self.reader.parser
+ if self.writer is None:
+ self.set_writer(writer_name)
+
+ def setup_option_parser(self, usage=None, description=None,
+ settings_spec=None, **defaults):
+ #@@@ Add self.source & self.destination to components in future?
+ option_parser = OptionParser(
+ components=(settings_spec, self.parser, self.reader, self.writer),
+ usage=usage, description=description)
+ config = ConfigParser()
+ config.read_standard_files()
+ config_settings = config.get_section('options')
+ frontend.make_paths_absolute(config_settings,
+ option_parser.relative_path_settings)
+ defaults.update(config_settings)
+ option_parser.set_defaults(**defaults)
+ return option_parser
+
+ def get_settings(self, usage=None, description=None,
+ settings_spec=None, **defaults):
+ """
+ Set and return default settings (overrides in `defaults` keyword
+ argument).
+
+ Set components first (`self.set_reader` & `self.set_writer`).
+ Explicitly setting `self.settings` disables command line option
+ processing from `self.publish()`.
+ """
+ option_parser = self.setup_option_parser(usage, description,
+ settings_spec, **defaults)
+ self.settings = option_parser.get_default_values()
+ return self.settings
+
+ def process_command_line(self, argv=None, usage=None, description=None,
+ settings_spec=None, **defaults):
+ """
+ Pass an empty list to `argv` to avoid reading `sys.argv` (the
+ default).
+
+ Set components first (`self.set_reader` & `self.set_writer`).
+ """
+ option_parser = self.setup_option_parser(usage, description,
+ settings_spec, **defaults)
+ if argv is None:
+ argv = sys.argv[1:]
+ self.settings = option_parser.parse_args(argv)
+
+ def set_io(self, source_path=None, destination_path=None):
+ if self.source is None:
+ self.set_source(source_path=source_path)
+ if self.destination is None:
+ self.set_destination(destination_path=destination_path)
+
+ def set_source(self, source=None, source_path=None):
+ if source_path is None:
+ source_path = self.settings._source
+ else:
+ self.settings._source = source_path
+ self.source = self.source_class(
+ source=source, source_path=source_path,
+ encoding=self.settings.input_encoding)
+
+ def set_destination(self, destination=None, destination_path=None):
+ if destination_path is None:
+ destination_path = self.settings._destination
+ else:
+ self.settings._destination = destination_path
+ self.destination = self.destination_class(
+ destination=destination, destination_path=destination_path,
+ encoding=self.settings.output_encoding)
+
+ def apply_transforms(self, document):
+ document.transformer.populate_from_components(
+ (self.source, self.reader, self.reader.parser, self.writer,
+ self.destination))
+ document.transformer.apply_transforms()
+
+ def publish(self, argv=None, usage=None, description=None,
+ settings_spec=None, settings_overrides=None):
+ """
+ Process command line options and arguments (if `self.settings` not
+ already set), run `self.reader` and then `self.writer`. Return
+ `self.writer`'s output.
+ """
+ if self.settings is None:
+ self.process_command_line(argv, usage, description, settings_spec,
+ **(settings_overrides or {}))
+ elif settings_overrides:
+ self.settings._update(settings_overrides, 'loose')
+ self.set_io()
+ document = self.reader.read(self.source, self.parser, self.settings)
+ self.apply_transforms(document)
+ output = self.writer.write(document, self.destination)
+ if self.settings.dump_settings:
+ from pprint import pformat
+ print >>sys.stderr, '\n::: Runtime settings:'
+ print >>sys.stderr, pformat(self.settings.__dict__)
+ if self.settings.dump_internals:
+ from pprint import pformat
+ print >>sys.stderr, '\n::: Document internals:'
+ print >>sys.stderr, pformat(document.__dict__)
+ if self.settings.dump_transforms:
+ from pprint import pformat
+ print >>sys.stderr, '\n::: Transforms applied:'
+ print >>sys.stderr, pformat(document.transformer.applied)
+ if self.settings.dump_pseudo_xml:
+ print >>sys.stderr, '\n::: Pseudo-XML:'
+ print >>sys.stderr, document.pformat().encode(
+ 'raw_unicode_escape')
+ return output
+
+
+default_usage = '%prog [options] [<source> [<destination>]]'
+default_description = ('Reads from <source> (default is stdin) and writes to '
+ '<destination> (default is stdout).')
+
+def publish_cmdline(reader=None, reader_name='standalone',
+ parser=None, parser_name='restructuredtext',
+ writer=None, writer_name='pseudoxml',
+ settings=None, settings_spec=None,
+ settings_overrides=None, argv=None,
+ usage=default_usage, description=default_description):
+ """
+ Set up & run a `Publisher`. For command-line front ends.
+
+ Parameters:
+
+ - `reader`: A `docutils.readers.Reader` object.
+ - `reader_name`: Name or alias of the Reader class to be instantiated if
+ no `reader` supplied.
+ - `parser`: A `docutils.parsers.Parser` object.
+ - `parser_name`: Name or alias of the Parser class to be instantiated if
+ no `parser` supplied.
+ - `writer`: A `docutils.writers.Writer` object.
+ - `writer_name`: Name or alias of the Writer class to be instantiated if
+ no `writer` supplied.
+ - `settings`: Runtime settings object.
+ - `settings_spec`: Extra settings specification; a `docutils.SettingsSpec`
+ subclass. Used only if no `settings` specified.
+ - `settings_overrides`: A dictionary containing program-specific overrides
+ of component settings.
+ - `argv`: Command-line argument list to use instead of ``sys.argv[1:]``.
+ - `usage`: Usage string, output if there's a problem parsing the command
+ line.
+ - `description`: Program description, output for the "--help" option
+ (along with command-line option descriptions).
+ """
+ pub = Publisher(reader, parser, writer, settings=settings)
+ pub.set_components(reader_name, parser_name, writer_name)
+ pub.publish(argv, usage, description, settings_spec, settings_overrides)
+
+def publish_file(source=None, source_path=None,
+ destination=None, destination_path=None,
+ reader=None, reader_name='standalone',
+ parser=None, parser_name='restructuredtext',
+ writer=None, writer_name='pseudoxml',
+ settings=None, settings_spec=None, settings_overrides=None):
+ """
+ Set up & run a `Publisher`. For programmatic use with file-like I/O.
+
+ Parameters:
+
+ - `source`: A file-like object (must have "read" and "close" methods).
+ - `source_path`: Path to the input file. Opened if no `source` supplied.
+ If neither `source` nor `source_path` are supplied, `sys.stdin` is used.
+ - `destination`: A file-like object (must have "write" and "close"
+ methods).
+ - `destination_path`: Path to the input file. Opened if no `destination`
+ supplied. If neither `destination` nor `destination_path` are supplied,
+ `sys.stdout` is used.
+ - `reader`: A `docutils.readers.Reader` object.
+ - `reader_name`: Name or alias of the Reader class to be instantiated if
+ no `reader` supplied.
+ - `parser`: A `docutils.parsers.Parser` object.
+ - `parser_name`: Name or alias of the Parser class to be instantiated if
+ no `parser` supplied.
+ - `writer`: A `docutils.writers.Writer` object.
+ - `writer_name`: Name or alias of the Writer class to be instantiated if
+ no `writer` supplied.
+ - `settings`: Runtime settings object.
+ - `settings_spec`: Extra settings specification; a `docutils.SettingsSpec`
+ subclass. Used only if no `settings` specified.
+ - `settings_overrides`: A dictionary containing program-specific overrides
+ of component settings.
+ """
+ pub = Publisher(reader, parser, writer, settings=settings)
+ pub.set_components(reader_name, parser_name, writer_name)
+ if settings is None:
+ settings = pub.get_settings(settings_spec=settings_spec)
+ if settings_overrides:
+ settings._update(settings_overrides, 'loose')
+ pub.set_source(source, source_path)
+ pub.set_destination(destination, destination_path)
+ pub.publish()
+
+def publish_string(source, source_path=None, destination_path=None,
+ reader=None, reader_name='standalone',
+ parser=None, parser_name='restructuredtext',
+ writer=None, writer_name='pseudoxml',
+ settings=None, settings_spec=None,
+ settings_overrides=None):
+ """
+ Set up & run a `Publisher`, and return the string output.
+ For programmatic use with string I/O.
+
+ For encoded string output, be sure to set the "output_encoding" setting to
+ the desired encoding. Set it to "unicode" for unencoded Unicode string
+ output.
+
+ Parameters:
+
+ - `source`: An input string; required. This can be an encoded 8-bit
+ string (set the "input_encoding" setting to the correct encoding) or a
+ Unicode string (set the "input_encoding" setting to "unicode").
+ - `source_path`: Path to the file or object that produced `source`;
+ optional. Only used for diagnostic output.
+ - `destination_path`: Path to the file or object which will receive the
+ output; optional. Used for determining relative paths (stylesheets,
+ source links, etc.).
+ - `reader`: A `docutils.readers.Reader` object.
+ - `reader_name`: Name or alias of the Reader class to be instantiated if
+ no `reader` supplied.
+ - `parser`: A `docutils.parsers.Parser` object.
+ - `parser_name`: Name or alias of the Parser class to be instantiated if
+ no `parser` supplied.
+ - `writer`: A `docutils.writers.Writer` object.
+ - `writer_name`: Name or alias of the Writer class to be instantiated if
+ no `writer` supplied.
+ - `settings`: Runtime settings object.
+ - `settings_spec`: Extra settings specification; a `docutils.SettingsSpec`
+ subclass. Used only if no `settings` specified.
+ - `settings_overrides`: A dictionary containing program-specific overrides
+ of component settings.
+ """
+ pub = Publisher(reader, parser, writer, settings=settings,
+ source_class=io.StringInput,
+ destination_class=io.StringOutput)
+ pub.set_components(reader_name, parser_name, writer_name)
+ if settings is None:
+ settings = pub.get_settings(settings_spec=settings_spec)
+ if settings_overrides:
+ settings._update(settings_overrides, 'loose')
+ pub.set_source(source, source_path)
+ pub.set_destination(destination_path=destination_path)
+ return pub.publish()
=== Zope/lib/python/docutils/frontend.py 1.1 => 1.2 ===
--- /dev/null Sat Feb 1 04:26:34 2003
+++ Zope/lib/python/docutils/frontend.py Sat Feb 1 04:26:00 2003
@@ -0,0 +1,310 @@
+# Author: David Goodger
+# Contact: goodger@users.sourceforge.net
+# Revision: $Revision$
+# Date: $Date$
+# Copyright: This module has been placed in the public domain.
+
+"""
+Command-line and common processing for Docutils front-end tools.
+
+Exports the following classes:
+
+- `OptionParser`: Standard Docutils command-line processing.
+- `Values`: Runtime settings; objects are simple structs
+ (``object.attribute``).
+- `ConfigParser`: Standard Docutils config file processing.
+"""
+
+__docformat__ = 'reStructuredText'
+
+import os
+import os.path
+import ConfigParser as CP
+import docutils
+from docutils import optik
+from docutils.optik import Values
+
+
+def store_multiple(option, opt, value, parser, *args, **kwargs):
+ """
+ Store multiple values in `parser.values`. (Option callback.)
+
+ Store `None` for each attribute named in `args`, and store the value for
+ each key (attribute name) in `kwargs`.
+ """
+ for attribute in args:
+ setattr(parser.values, attribute, None)
+ for key, value in kwargs.items():
+ setattr(parser.values, key, value)
+
+def read_config_file(option, opt, value, parser):
+ """
+ Read a configuration file during option processing. (Option callback.)
+ """
+ config_parser = ConfigParser()
+ config_parser.read(value)
+ settings = config_parser.get_section('options')
+ make_paths_absolute(settings, parser.relative_path_settings,
+ os.path.dirname(value))
+ parser.values.__dict__.update(settings)
+
+def make_paths_absolute(pathdict, keys, base_path=None):
+ """
+ Interpret filesystem path settings relative to the `base_path` given.
+
+ Paths are values in `pathdict` whose keys are in `keys`. Get `keys` from
+ `OptionParser.relative_path_settings`.
+ """
+ if base_path is None:
+ base_path = os.getcwd()
+ for key in keys:
+ if pathdict.has_key(key) and pathdict[key]:
+ pathdict[key] = os.path.normpath(
+ os.path.abspath(os.path.join(base_path, pathdict[key])))
+
+
+class OptionParser(optik.OptionParser, docutils.SettingsSpec):
+
+ """
+ Parser for command-line and library use. The `settings_spec`
+ specification here and in other Docutils components are merged to build
+ the set of command-line options and runtime settings for this process.
+
+ Common settings (defined below) and component-specific settings must not
+ conflict. Short options are reserved for common settings, and components
+ are restrict to using long options.
+ """
+
+ threshold_choices = 'info 1 warning 2 error 3 severe 4 none 5'.split()
+ """Possible inputs for for --report and --halt threshold values."""
+
+ thresholds = {'info': 1, 'warning': 2, 'error': 3, 'severe': 4, 'none': 5}
+ """Lookup table for --report and --halt threshold values."""
+
+ settings_spec = (
+ 'General Docutils Options',
+ None,
+ (('Include a "Generated by Docutils" credit and link at the end '
+ 'of the document.',
+ ['--generator', '-g'], {'action': 'store_true'}),
+ ('Do not include a generator credit.',
+ ['--no-generator'], {'action': 'store_false', 'dest': 'generator'}),
+ ('Include the date at the end of the document (UTC).',
+ ['--date', '-d'], {'action': 'store_const', 'const': '%Y-%m-%d',
+ 'dest': 'datestamp'}),
+ ('Include the time & date at the end of the document (UTC).',
+ ['--time', '-t'], {'action': 'store_const',
+ 'const': '%Y-%m-%d %H:%M UTC',
+ 'dest': 'datestamp'}),
+ ('Do not include a datestamp of any kind.',
+ ['--no-datestamp'], {'action': 'store_const', 'const': None,
+ 'dest': 'datestamp'}),
+ ('Include a "View document source" link (relative to destination).',
+ ['--source-link', '-s'], {'action': 'store_true'}),
+ ('Use the supplied <URL> verbatim for a "View document source" '
+ 'link; implies --source-link.',
+ ['--source-url'], {'metavar': '<URL>'}),
+ ('Do not include a "View document source" link.',
+ ['--no-source-link'],
+ {'action': 'callback', 'callback': store_multiple,
+ 'callback_args': ('source_link', 'source_url')}),
+ ('Enable backlinks from section headers to table of contents '
+ 'entries. This is the default.',
+ ['--toc-entry-backlinks'],
+ {'dest': 'toc_backlinks', 'action': 'store_const', 'const': 'entry',
+ 'default': 'entry'}),
+ ('Enable backlinks from section headers to the top of the table of '
+ 'contents.',
+ ['--toc-top-backlinks'],
+ {'dest': 'toc_backlinks', 'action': 'store_const', 'const': 'top'}),
+ ('Disable backlinks to the table of contents.',
+ ['--no-toc-backlinks'],
+ {'dest': 'toc_backlinks', 'action': 'store_false'}),
+ ('Enable backlinks from footnotes and citations to their '
+ 'references. This is the default.',
+ ['--footnote-backlinks'],
+ {'action': 'store_true', 'default': 1}),
+ ('Disable backlinks from footnotes and citations.',
+ ['--no-footnote-backlinks'],
+ {'dest': 'footnote_backlinks', 'action': 'store_false'}),
+ ('Set verbosity threshold; report system messages at or higher than '
+ '<level> (by name or number: "info" or "1", warning/2, error/3, '
+ 'severe/4; also, "none" or "5"). Default is 2 (warning).',
+ ['--report', '-r'], {'choices': threshold_choices, 'default': 2,
+ 'dest': 'report_level', 'metavar': '<level>'}),
+ ('Report all system messages, info-level and higher. (Same as '
+ '"--report=info".)',
+ ['--verbose', '-v'], {'action': 'store_const', 'const': 'info',
+ 'dest': 'report_level'}),
+ ('Do not report any system messages. (Same as "--report=none".)',
+ ['--quiet', '-q'], {'action': 'store_const', 'const': 'none',
+ 'dest': 'report_level'}),
+ ('Set the threshold (<level>) at or above which system messages are '
+ 'converted to exceptions, halting execution immediately. Levels '
+ 'as in --report. Default is 4 (severe).',
+ ['--halt'], {'choices': threshold_choices, 'dest': 'halt_level',
+ 'default': 4, 'metavar': '<level>'}),
+ ('Same as "--halt=info": halt processing at the slightest problem.',
+ ['--strict'], {'action': 'store_const', 'const': 'info',
+ 'dest': 'halt_level'}),
+ ('Report debug-level system messages.',
+ ['--debug'], {'action': 'store_true'}),
+ ('Do not report debug-level system messages.',
+ ['--no-debug'], {'action': 'store_false', 'dest': 'debug'}),
+ ('Send the output of system messages (warnings) to <file>.',
+ ['--warnings'], {'dest': 'warning_stream', 'metavar': '<file>'}),
+ ('Specify the encoding of input text. Default is locale-dependent.',
+ ['--input-encoding', '-i'], {'metavar': '<name>'}),
+ ('Specify the encoding for output. Default is UTF-8.',
+ ['--output-encoding', '-o'],
+ {'metavar': '<name>', 'default': 'utf-8'}),
+ ('Specify the language of input text (ISO 639 2-letter identifier).'
+ ' Default is "en" (English).',
+ ['--language', '-l'], {'dest': 'language_code', 'default': 'en',
+ 'metavar': '<name>'}),
+ ('Read configuration settings from <file>, if it exists.',
+ ['--config'], {'metavar': '<file>', 'type': 'string',
+ 'action': 'callback', 'callback': read_config_file}),
+ ("Show this program's version number and exit.",
+ ['--version', '-V'], {'action': 'version'}),
+ ('Show this help message and exit.',
+ ['--help', '-h'], {'action': 'help'}),
+ # Hidden options, for development use only:
+ (optik.SUPPRESS_HELP,
+ ['--dump-settings'],
+ {'action': 'store_true'}),
+ (optik.SUPPRESS_HELP,
+ ['--dump-internals'],
+ {'action': 'store_true'}),
+ (optik.SUPPRESS_HELP,
+ ['--dump-transforms'],
+ {'action': 'store_true'}),
+ (optik.SUPPRESS_HELP,
+ ['--dump-pseudo-xml'],
+ {'action': 'store_true'}),
+ (optik.SUPPRESS_HELP,
+ ['--expose-internal-attribute'],
+ {'action': 'append', 'dest': 'expose_internals'}),))
+ """Runtime settings and command-line options common to all Docutils front
+ ends. Setting specs specific to individual Docutils components are also
+ used (see `populate_from_components()`)."""
+
+ relative_path_settings = ('warning_stream',)
+
+ version_template = '%%prog (Docutils %s)' % docutils.__version__
+ """Default version message."""
+
+ def __init__(self, components=(), *args, **kwargs):
+ """
+ `components` is a list of Docutils components each containing a
+ ``.settings_spec`` attribute. `defaults` is a mapping of setting
+ default overrides.
+ """
+ optik.OptionParser.__init__(
+ self, help=None,
+ format=optik.Titled(),
+ # Needed when Optik is updated (replaces above 2 lines):
+ #self, add_help=None,
+ #formatter=optik.TitledHelpFormatter(width=78),
+ *args, **kwargs)
+ if not self.version:
+ self.version = self.version_template
+ # Internal settings with no defaults from settings specifications;
+ # initialize manually:
+ self.set_defaults(_source=None, _destination=None)
+ # Make an instance copy (it will be modified):
+ self.relative_path_settings = list(self.relative_path_settings)
+ self.populate_from_components(tuple(components) + (self,))
+
+ def populate_from_components(self, components):
+ for component in components:
+ if component is None:
+ continue
+ i = 0
+ settings_spec = component.settings_spec
+ self.relative_path_settings.extend(
+ component.relative_path_settings)
+ while i < len(settings_spec):
+ title, description, option_spec = settings_spec[i:i+3]
+ if title:
+ group = optik.OptionGroup(self, title, description)
+ self.add_option_group(group)
+ else:
+ group = self # single options
+ for (help_text, option_strings, kwargs) in option_spec:
+ group.add_option(help=help_text, *option_strings,
+ **kwargs)
+ i += 3
+ for component in components:
+ if component and component.settings_default_overrides:
+ self.defaults.update(component.settings_default_overrides)
+
+ def check_values(self, values, args):
+ if hasattr(values, 'report_level'):
+ values.report_level = self.check_threshold(values.report_level)
+ if hasattr(values, 'halt_level'):
+ values.halt_level = self.check_threshold(values.halt_level)
+ values._source, values._destination = self.check_args(args)
+ make_paths_absolute(values.__dict__, self.relative_path_settings,
+ os.getcwd())
+ return values
+
+ def check_threshold(self, level):
+ try:
+ return int(level)
+ except ValueError:
+ try:
+ return self.thresholds[level.lower()]
+ except (KeyError, AttributeError):
+ self.error('Unknown threshold: %r.' % level)
+
+ def check_args(self, args):
+ source = destination = None
+ if args:
+ source = args.pop(0)
+ if args:
+ destination = args.pop(0)
+ if args:
+ self.error('Maximum 2 arguments allowed.')
+ if source and source == destination:
+ self.error('Do not specify the same file for both source and '
+ 'destination. It will clobber the source file.')
+ return source, destination
+
+
+class ConfigParser(CP.ConfigParser):
+
+ standard_config_files = (
+ '/etc/docutils.conf', # system-wide
+ './docutils.conf', # project-specific
+ os.path.expanduser('~/.docutils')) # user-specific
+ """Docutils configuration files, using ConfigParser syntax (section
+ 'options'). Later files override earlier ones."""
+
+ def read_standard_files(self):
+ self.read(self.standard_config_files)
+
+ def optionxform(self, optionstr):
+ """
+ Transform '-' to '_' so the cmdline form of option names can be used.
+ """
+ return optionstr.lower().replace('-', '_')
+
+ def get_section(self, section, raw=0, vars=None):
+ """
+ Return a given section as a dictionary (empty if the section
+ doesn't exist).
+
+ All % interpolations are expanded in the return values, based on the
+ defaults passed into the constructor, unless the optional argument
+ `raw` is true. Additional substitutions may be provided using the
+ `vars` argument, which must be a dictionary whose contents overrides
+ any pre-existing defaults.
+
+ The section DEFAULT is special.
+ """
+ section_dict = {}
+ if self.has_section(section):
+ for option in self.options(section):
+ section_dict[option] = self.get(section, option, raw, vars)
+ return section_dict
=== Zope/lib/python/docutils/io.py 1.1 => 1.2 ===
--- /dev/null Sat Feb 1 04:26:34 2003
+++ Zope/lib/python/docutils/io.py Sat Feb 1 04:26:00 2003
@@ -0,0 +1,291 @@
+# Author: David Goodger
+# Contact: goodger@users.sourceforge.net
+# Revision: $Revision$
+# Date: $Date$
+# Copyright: This module has been placed in the public domain.
+
+"""
+I/O classes provide a uniform API for low-level input and output. Subclasses
+will exist for a variety of input/output mechanisms.
+"""
+
+__docformat__ = 'reStructuredText'
+
+import sys
+import locale
+from docutils import TransformSpec
+
+
+class Input(TransformSpec):
+
+ """
+ Abstract base class for input wrappers.
+ """
+
+ component_type = 'input'
+
+ default_source_path = None
+
+ def __init__(self, settings=None, source=None, source_path=None,
+ encoding=None):
+ self.encoding = encoding
+ """The character encoding for the input source."""
+
+ if settings:
+ if not encoding:
+ self.encoding = settings.input_encoding
+ import warnings, traceback
+ warnings.warn(
+ 'Setting input encoding via a "settings" struct is '
+ 'deprecated; send encoding directly instead.\n%s'
+ % ''.join(traceback.format_list(traceback.extract_stack()
+ [-3:-1])))
+
+ self.source = source
+ """The source of input data."""
+
+ self.source_path = source_path
+ """A text reference to the source."""
+
+ if not source_path:
+ self.source_path = self.default_source_path
+
+ def __repr__(self):
+ return '%s: source=%r, source_path=%r' % (self.__class__, self.source,
+ self.source_path)
+
+ def read(self):
+ raise NotImplementedError
+
+ def decode(self, data):
+ """
+ Decode a string, `data`, heuristically.
+ Raise UnicodeError if unsuccessful.
+
+ The client application should call ``locale.setlocale`` at the
+ beginning of processing::
+
+ locale.setlocale(locale.LC_ALL, '')
+ """
+ if self.encoding and self.encoding.lower() == 'unicode':
+ return unicode(data)
+ encodings = [self.encoding, 'utf-8']
+ try:
+ encodings.append(locale.nl_langinfo(locale.CODESET))
+ except:
+ pass
+ try:
+ encodings.append(locale.getlocale()[1])
+ except:
+ pass
+ try:
+ encodings.append(locale.getdefaultlocale()[1])
+ except:
+ pass
+ encodings.append('latin-1')
+ for enc in encodings:
+ if not enc:
+ continue
+ try:
+ decoded = unicode(data, enc)
+ return decoded
+ except (UnicodeError, LookupError):
+ pass
+ raise UnicodeError(
+ 'Unable to decode input data. Tried the following encodings: %s.'
+ % ', '.join([repr(enc) for enc in encodings if enc]))
+
+
+class Output(TransformSpec):
+
+ """
+ Abstract base class for output wrappers.
+ """
+
+ component_type = 'output'
+
+ default_destination_path = None
+
+ def __init__(self, settings=None, destination=None, destination_path=None,
+ encoding=None):
+ self.encoding = encoding
+ """The character encoding for the output destination."""
+
+ if settings:
+ if not encoding:
+ self.encoding = settings.output_encoding
+ import warnings, traceback
+ warnings.warn(
+ 'Setting output encoding via a "settings" struct is '
+ 'deprecated; send encoding directly instead.\n%s'
+ % ''.join(traceback.format_list(traceback.extract_stack()
+ [-3:-1])))
+
+ self.destination = destination
+ """The destination for output data."""
+
+ self.destination_path = destination_path
+ """A text reference to the destination."""
+
+ if not destination_path:
+ self.destination_path = self.default_destination_path
+
+ def __repr__(self):
+ return ('%s: destination=%r, destination_path=%r'
+ % (self.__class__, self.destination, self.destination_path))
+
+ def write(self, data):
+ raise NotImplementedError
+
+ def encode(self, data):
+ if self.encoding and self.encoding.lower() == 'unicode':
+ return data
+ else:
+ return data.encode(self.encoding or '')
+
+
+class FileInput(Input):
+
+ """
+ Input for single, simple file-like objects.
+ """
+
+ def __init__(self, settings=None, source=None, source_path=None,
+ encoding=None, autoclose=1):
+ """
+ :Parameters:
+ - `source`: either a file-like object (which is read directly), or
+ `None` (which implies `sys.stdin` if no `source_path` given).
+ - `source_path`: a path to a file, which is opened and then read.
+ - `autoclose`: close automatically after read (boolean); always
+ false if `sys.stdin` is the source.
+ """
+ Input.__init__(self, settings, source, source_path, encoding)
+ self.autoclose = autoclose
+ if source is None:
+ if source_path:
+ self.source = open(source_path)
+ else:
+ self.source = sys.stdin
+ self.autoclose = None
+ if not source_path:
+ try:
+ self.source_path = self.source.name
+ except AttributeError:
+ pass
+
+ def read(self):
+ """Read and decode a single file and return the data."""
+ data = self.source.read()
+ if self.autoclose:
+ self.close()
+ return self.decode(data)
+
+ def close(self):
+ self.source.close()
+
+
+class FileOutput(Output):
+
+ """
+ Output for single, simple file-like objects.
+ """
+
+ def __init__(self, settings=None, destination=None, destination_path=None,
+ encoding=None, autoclose=1):
+ """
+ :Parameters:
+ - `destination`: either a file-like object (which is written
+ directly) or `None` (which implies `sys.stdout` if no
+ `destination_path` given).
+ - `destination_path`: a path to a file, which is opened and then
+ written.
+ - `autoclose`: close automatically after write (boolean); always
+ false if `sys.stdout` is the destination.
+ """
+ Output.__init__(self, settings, destination, destination_path,
+ encoding)
+ self.opened = 1
+ self.autoclose = autoclose
+ if destination is None:
+ if destination_path:
+ self.opened = None
+ else:
+ self.destination = sys.stdout
+ self.autoclose = None
+ if not destination_path:
+ try:
+ self.destination_path = self.destination.name
+ except AttributeError:
+ pass
+
+ def open(self):
+ self.destination = open(self.destination_path, 'w')
+ self.opened = 1
+
+ def write(self, data):
+ """Encode `data`, write it to a single file, and return it."""
+ output = self.encode(data)
+ if not self.opened:
+ self.open()
+ self.destination.write(output)
+ if self.autoclose:
+ self.close()
+ return output
+
+ def close(self):
+ self.destination.close()
+ self.opened = None
+
+
+class StringInput(Input):
+
+ """
+ Direct string input.
+ """
+
+ default_source_path = '<string>'
+
+ def read(self):
+ """Decode and return the source string."""
+ return self.decode(self.source)
+
+
+class StringOutput(Output):
+
+ """
+ Direct string output.
+ """
+
+ default_destination_path = '<string>'
+
+ def write(self, data):
+ """Encode `data`, store it in `self.destination`, and return it."""
+ self.destination = self.encode(data)
+ return self.destination
+
+
+class NullInput(Input):
+
+ """
+ Degenerate input: read nothing.
+ """
+
+ default_source_path = 'null input'
+
+ def read(self):
+ """Return a null string."""
+ return u''
+
+
+class NullOutput(Output):
+
+ """
+ Degenerate output: write nothing.
+ """
+
+ default_destination_path = 'null output'
+
+ def write(self, data):
+ """Do nothing ([don't even] send data to the bit bucket)."""
+ pass
=== Zope/lib/python/docutils/nodes.py 1.1 => 1.2 === (1330/1430 lines abridged)
--- /dev/null Sat Feb 1 04:26:34 2003
+++ Zope/lib/python/docutils/nodes.py Sat Feb 1 04:26:00 2003
@@ -0,0 +1,1427 @@
+# Author: David Goodger
+# Contact: goodger@users.sourceforge.net
+# Revision: $Revision$
+# Date: $Date$
+# Copyright: This module has been placed in the public domain.
+
+"""
+Docutils document tree element class library.
+
+Classes in CamelCase are abstract base classes or auxiliary classes. The one
+exception is `Text`, for a text (PCDATA) node; uppercase is used to
+differentiate from element classes. Classes in lower_case_with_underscores
+are element classes, matching the XML element generic identifiers in the DTD_.
+
+The position of each node (the level at which it can occur) is significant and
+is represented by abstract base classes (`Root`, `Structural`, `Body`,
+`Inline`, etc.). Certain transformations will be easier because we can use
+``isinstance(node, base_class)`` to determine the position of the node in the
+hierarchy.
+
+.. _DTD: http://docutils.sourceforge.net/spec/docutils.dtd
+"""
+
+__docformat__ = 'reStructuredText'
+
+import sys
+import os
+import re
+import xml.dom.minidom
+from types import IntType, SliceType, StringType, UnicodeType, \
+ TupleType, ListType
+from UserString import UserString
+
+
+# ==============================
+# Functional Node Base Classes
+# ==============================
+
+class Node:
+
+ """Abstract base class of nodes in a document tree."""
+
+ parent = None
+ """Back-reference to the Node immediately containing this Node."""
+
+ document = None
+ """The `document` node at the root of the tree containing this Node."""
[-=- -=- -=- 1330 lines omitted -=- -=- -=-]
+ """
+
+ pass
+
+
+def make_id(string):
+ """
+ Convert `string` into an identifier and return it.
+
+ Docutils identifiers will conform to the regular expression
+ ``[a-z][-a-z0-9]*``. For CSS compatibility, identifiers (the "class" and
+ "id" attributes) should have no underscores, colons, or periods. Hyphens
+ may be used.
+
+ - The `HTML 4.01 spec`_ defines identifiers based on SGML tokens:
+
+ ID and NAME tokens must begin with a letter ([A-Za-z]) and may be
+ followed by any number of letters, digits ([0-9]), hyphens ("-"),
+ underscores ("_"), colons (":"), and periods (".").
+
+ - However the `CSS1 spec`_ defines identifiers based on the "name" token,
+ a tighter interpretation ("flex" tokenizer notation; "latin1" and
+ "escape" 8-bit characters have been replaced with entities)::
+
+ unicode \\[0-9a-f]{1,4}
+ latin1 [¡-ÿ]
+ escape {unicode}|\\[ -~¡-ÿ]
+ nmchar [-a-z0-9]|{latin1}|{escape}
+ name {nmchar}+
+
+ The CSS1 "nmchar" rule does not include underscores ("_"), colons (":"),
+ or periods ("."), therefore "class" and "id" attributes should not contain
+ these characters. They should be replaced with hyphens ("-"). Combined
+ with HTML's requirements (the first character must be a letter; no
+ "unicode", "latin1", or "escape" characters), this results in the
+ ``[a-z][-a-z0-9]*`` pattern.
+
+ .. _HTML 4.01 spec: http://www.w3.org/TR/html401
+ .. _CSS1 spec: http://www.w3.org/TR/REC-CSS1
+ """
+ id = _non_id_chars.sub('-', ' '.join(string.lower().split()))
+ id = _non_id_at_ends.sub('', id)
+ return str(id)
+
+_non_id_chars = re.compile('[^a-z0-9]+')
+_non_id_at_ends = re.compile('^[-0-9]+|-+$')
+
+def dupname(node):
+ node['dupname'] = node['name']
+ del node['name']
=== Zope/lib/python/docutils/optik.py 1.1 => 1.2 === (1257/1357 lines abridged)
--- /dev/null Sat Feb 1 04:26:34 2003
+++ Zope/lib/python/docutils/optik.py Sat Feb 1 04:26:00 2003
@@ -0,0 +1,1354 @@
+# This is *not* the official distribution of Optik. See
+# http://optik.sourceforge.net/ for the official distro.
+#
+# This combined module was converted from the "optik" package for Docutils use
+# by David Goodger (2002-06-12). Optik is slated for inclusion in the Python
+# standard library as OptionParser.py. Once Optik itself becomes a single
+# module, Docutils will include the official module and kill off this
+# temporary fork.
+
+"""optik
+
+A powerful, extensible, and easy-to-use command-line parser for Python.
+
+By Greg Ward <gward@python.net>
+
+See http://optik.sourceforge.net/
+"""
+
+# Copyright (c) 2001 Gregory P. Ward. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of the author nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
[-=- -=- -=- 1257 lines omitted -=- -=- -=-]
+
+ def format_usage(self, usage):
+ return "Usage: %s\n" % usage
+
+ def format_heading(self, heading):
+ return "%*s%s:\n" % (self.current_indent, "", heading)
+
+
+class Titled(HelpFormat):
+
+ """Formats help with underlined section headers."""
+
+ def __init__(self, indent_increment=0, max_help_position=24, width=78,
+ short_first=None):
+ HelpFormat.__init__(self, indent_increment, max_help_position, width,
+ short_first)
+
+ def format_usage(self, usage):
+ return "%s %s\n" % (self.format_heading("Usage"), usage)
+
+ def format_heading(self, heading):
+ return "%s\n%s\n" % (heading, "=-"[self.level] * len(heading))
+
+
+def _match_abbrev (s, wordmap):
+ """_match_abbrev(s : string, wordmap : {string : Option}) -> string
+
+ Return the string key in 'wordmap' for which 's' is an unambiguous
+ abbreviation. If 's' is found to be ambiguous or doesn't match any of
+ 'words', raise BadOptionError.
+ """
+ # Is there an exact match?
+ if wordmap.has_key(s):
+ return s
+ else:
+ # Isolate all words with s as a prefix.
+ possibilities = [word for word in wordmap.keys()
+ if word.startswith(s)]
+ # No exact match, so there had better be just one possibility.
+ if len(possibilities) == 1:
+ return possibilities[0]
+ elif not possibilities:
+ raise BadOptionError("no such option: %s" % s)
+ else:
+ # More than one possible completion: ambiguous prefix.
+ raise BadOptionError("ambiguous option: %s (%s?)"
+ % (s, ", ".join(possibilities)))
+
+def get_prog_name ():
+ return os.path.basename(sys.argv[0])
=== Zope/lib/python/docutils/roman.py 1.1 => 1.2 ===
--- /dev/null Sat Feb 1 04:26:34 2003
+++ Zope/lib/python/docutils/roman.py Sat Feb 1 04:26:00 2003
@@ -0,0 +1,81 @@
+"""Convert to and from Roman numerals"""
+
+__author__ = "Mark Pilgrim (f8dy@diveintopython.org)"
+__version__ = "1.4"
+__date__ = "8 August 2001"
+__copyright__ = """Copyright (c) 2001 Mark Pilgrim
+
+This program is part of "Dive Into Python", a free Python tutorial for
+experienced programmers. Visit http://diveintopython.org/ for the
+latest version.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the Python 2.1.1 license, available at
+http://www.python.org/2.1.1/license.html
+"""
+
+import re
+
+#Define exceptions
+class RomanError(Exception): pass
+class OutOfRangeError(RomanError): pass
+class NotIntegerError(RomanError): pass
+class InvalidRomanNumeralError(RomanError): pass
+
+#Define digit mapping
+romanNumeralMap = (('M', 1000),
+ ('CM', 900),
+ ('D', 500),
+ ('CD', 400),
+ ('C', 100),
+ ('XC', 90),
+ ('L', 50),
+ ('XL', 40),
+ ('X', 10),
+ ('IX', 9),
+ ('V', 5),
+ ('IV', 4),
+ ('I', 1))
+
+def toRoman(n):
+ """convert integer to Roman numeral"""
+ if not (0 < n < 5000):
+ raise OutOfRangeError, "number out of range (must be 1..4999)"
+ if int(n) <> n:
+ raise NotIntegerError, "decimals can not be converted"
+
+ result = ""
+ for numeral, integer in romanNumeralMap:
+ while n >= integer:
+ result += numeral
+ n -= integer
+ return result
+
+#Define pattern to detect valid Roman numerals
+romanNumeralPattern = re.compile('''
+ ^ # beginning of string
+ M{0,4} # thousands - 0 to 4 M's
+ (CM|CD|D?C{0,3}) # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
+ # or 500-800 (D, followed by 0 to 3 C's)
+ (XC|XL|L?X{0,3}) # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
+ # or 50-80 (L, followed by 0 to 3 X's)
+ (IX|IV|V?I{0,3}) # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
+ # or 5-8 (V, followed by 0 to 3 I's)
+ $ # end of string
+ ''' ,re.VERBOSE)
+
+def fromRoman(s):
+ """convert Roman numeral to integer"""
+ if not s:
+ raise InvalidRomanNumeralError, 'Input can not be blank'
+ if not romanNumeralPattern.search(s):
+ raise InvalidRomanNumeralError, 'Invalid Roman numeral: %s' % s
+
+ result = 0
+ index = 0
+ for numeral, integer in romanNumeralMap:
+ while s[index:index+len(numeral)] == numeral:
+ result += integer
+ index += len(numeral)
+ return result
+
=== Zope/lib/python/docutils/statemachine.py 1.1 => 1.2 === (1353/1453 lines abridged)
--- /dev/null Sat Feb 1 04:26:34 2003
+++ Zope/lib/python/docutils/statemachine.py Sat Feb 1 04:26:00 2003
@@ -0,0 +1,1450 @@
+# Author: David Goodger
+# Contact: goodger@users.sourceforge.net
+# Revision: $Revision$
+# Date: $Date$
+# Copyright: This module has been placed in the public domain.
+
+"""
+A finite state machine specialized for regular-expression-based text filters,
+this module defines the following classes:
+
+- `StateMachine`, a state machine
+- `State`, a state superclass
+- `StateMachineWS`, a whitespace-sensitive version of `StateMachine`
+- `StateWS`, a state superclass for use with `StateMachineWS`
+- `SearchStateMachine`, uses `re.search()` instead of `re.match()`
+- `SearchStateMachineWS`, uses `re.search()` instead of `re.match()`
+- `ViewList`, extends standard Python lists.
+- `StringList`, string-specific ViewList.
+
+Exception classes:
+
+- `StateMachineError`
+- `UnknownStateError`
+- `DuplicateStateError`
+- `UnknownTransitionError`
+- `DuplicateTransitionError`
+- `TransitionPatternNotFound`
+- `TransitionMethodNotFound`
+- `UnexpectedIndentationError`
+- `TransitionCorrection`: Raised to switch to another transition.
+- `StateCorrection`: Raised to switch to another state & transition.
+
+Functions:
+
+- `string2lines()`: split a multi-line string into a list of one-line strings
+
+
+How To Use This Module
+======================
+(See the individual classes, methods, and attributes for details.)
+
+1. Import it: ``import statemachine`` or ``from statemachine import ...``.
+ You will also need to ``import re``.
+
+2. Derive a subclass of `State` (or `StateWS`) for each state in your state
+ machine::
+
[-=- -=- -=- 1353 lines omitted -=- -=- -=-]
+ Raise from within a transition method to switch to another transition.
+
+ Raise with one argument, the new transition name.
+ """
+
+
+class StateCorrection(Exception):
+
+ """
+ Raise from within a transition method to switch to another state.
+
+ Raise with one or two arguments: new state name, and an optional new
+ transition name.
+ """
+
+
+def string2lines(astring, tab_width=8, convert_whitespace=0,
+ whitespace=re.compile('[\v\f]')):
+ """
+ Return a list of one-line strings with tabs expanded and no newlines.
+
+ Each tab is expanded with between 1 and `tab_width` spaces, so that the
+ next character's index becomes a multiple of `tab_width` (8 by default).
+
+ Parameters:
+
+ - `astring`: a multi-line string.
+ - `tab_width`: the number of columns between tab stops.
+ - `convert_whitespace`: convert form feeds and vertical tabs to spaces?
+ """
+ if convert_whitespace:
+ astring = whitespace.sub(' ', astring)
+ return [s.expandtabs(tab_width) for s in astring.splitlines()]
+
+def _exception_data():
+ """
+ Return exception information:
+
+ - the exception's class name;
+ - the exception object;
+ - the name of the file containing the offending code;
+ - the line number of the offending code;
+ - the function name of the offending code.
+ """
+ type, value, traceback = sys.exc_info()
+ while traceback.tb_next:
+ traceback = traceback.tb_next
+ code = traceback.tb_frame.f_code
+ return (type.__name__, value, code.co_filename, traceback.tb_lineno,
+ code.co_name)
=== Zope/lib/python/docutils/urischemes.py 1.1 => 1.2 ===
--- /dev/null Sat Feb 1 04:26:35 2003
+++ Zope/lib/python/docutils/urischemes.py Sat Feb 1 04:26:00 2003
@@ -0,0 +1,105 @@
+"""
+`schemes` is a dictionary with lowercase URI addressing schemes as
+keys and descriptions as values. It was compiled from the index at
+http://www.w3.org/Addressing/schemes.html (revised 2001-08-20).
+"""
+
+# Many values are blank and should be filled in with useful descriptions.
+
+schemes = {
+ 'about': 'provides information on Navigator',
+ 'acap': 'Application Configuration Access Protocol',
+ 'addbook': "To add vCard entries to Communicator's Address Book",
+ 'afp': 'Apple Filing Protocol',
+ 'afs': 'Andrew File System global file names',
+ 'aim': 'AOL Instant Messenger',
+ 'callto': 'for NetMeeting links',
+ 'castanet': 'Castanet Tuner URLs for Netcaster',
+ 'chttp': 'cached HTTP supported by RealPlayer',
+ 'cid': 'content identifier',
+ 'data': ('allows inclusion of small data items as "immediate" data; '
+ 'RFC 2397'),
+ 'dav': 'Distributed Authoring and Versioning Protocol; RFC 2518',
+ 'dns': 'Domain Name System resources',
+ 'eid': ('External ID; non-URL data; general escape mechanism to allow '
+ 'access to information for applications that are too '
+ 'specialized to justify their own schemes'),
+ 'fax': ('a connection to a terminal that can handle telefaxes '
+ '(facsimiles); RFC 2806'),
+ 'file': 'Host-specific file names',
+ 'finger': '',
+ 'freenet': '',
+ 'ftp': 'File Transfer Protocol',
+ 'gopher': 'The Gopher Protocol',
+ 'gsm-sms': ('Global System for Mobile Communications Short Message '
+ 'Service'),
+ 'h323': 'video (audiovisual) communication on local area networks',
+ 'h324': ('video and audio communications over low bitrate connections '
+ 'such as POTS modem connections'),
+ 'hdl': 'CNRI handle system',
+ 'hnews': 'an HTTP-tunneling variant of the NNTP news protocol',
+ 'http': 'Hypertext Transfer Protocol',
+ 'https': 'HTTP over SSL',
+ 'iioploc': 'Internet Inter-ORB Protocol Location?',
+ 'ilu': 'Inter-Language Unification',
+ 'imap': 'Internet Message Access Protocol',
+ 'ior': 'CORBA interoperable object reference',
+ 'ipp': 'Internet Printing Protocol',
+ 'irc': 'Internet Relay Chat',
+ 'jar': 'Java archive',
+ 'javascript': ('JavaScript code; evaluates the expression after the '
+ 'colon'),
+ 'jdbc': '',
+ 'ldap': 'Lightweight Directory Access Protocol',
+ 'lifn': '',
+ 'livescript': '',
+ 'lrq': '',
+ 'mailbox': 'Mail folder access',
+ 'mailserver': 'Access to data available from mail servers',
+ 'mailto': 'Electronic mail address',
+ 'md5': '',
+ 'mid': 'message identifier',
+ 'mocha': '',
+ 'modem': ('a connection to a terminal that can handle incoming data '
+ 'calls; RFC 2806'),
+ 'news': 'USENET news',
+ 'nfs': 'Network File System protocol',
+ 'nntp': 'USENET news using NNTP access',
+ 'opaquelocktoken': '',
+ 'phone': '',
+ 'pop': 'Post Office Protocol',
+ 'pop3': 'Post Office Protocol v3',
+ 'printer': '',
+ 'prospero': 'Prospero Directory Service',
+ 'res': '',
+ 'rtsp': 'real time streaming protocol',
+ 'rvp': '',
+ 'rwhois': '',
+ 'rx': 'Remote Execution',
+ 'sdp': '',
+ 'service': 'service location',
+ 'shttp': 'secure hypertext transfer protocol',
+ 'sip': 'Session Initiation Protocol',
+ 'smb': '',
+ 'snews': 'For NNTP postings via SSL',
+ 't120': 'real time data conferencing (audiographics)',
+ 'tcp': '',
+ 'tel': ('a connection to a terminal that handles normal voice '
+ 'telephone calls, a voice mailbox or another voice messaging '
+ 'system or a service that can be operated using DTMF tones; '
+ 'RFC 2806.'),
+ 'telephone': 'telephone',
+ 'telnet': 'Reference to interactive sessions',
+ 'tip': 'Transaction Internet Protocol',
+ 'tn3270': 'Interactive 3270 emulation sessions',
+ 'tv': '',
+ 'urn': 'Uniform Resource Name',
+ 'uuid': '',
+ 'vemmi': 'versatile multimedia interface',
+ 'videotex': '',
+ 'view-source': 'displays HTML code that was generated with JavaScript',
+ 'wais': 'Wide Area Information Servers',
+ 'whodp': '',
+ 'whois++': 'Distributed directory service.',
+ 'z39.50r': 'Z39.50 Retrieval',
+ 'z39.50s': 'Z39.50 Session',}
=== Zope/lib/python/docutils/utils.py 1.1 => 1.2 ===
--- /dev/null Sat Feb 1 04:26:35 2003
+++ Zope/lib/python/docutils/utils.py Sat Feb 1 04:26:00 2003
@@ -0,0 +1,435 @@
+# Author: David Goodger
+# Contact: goodger@users.sourceforge.net
+# Revision: $Revision$
+# Date: $Date$
+# Copyright: This module has been placed in the public domain.
+
+"""
+Miscellaneous utilities for the documentation utilities.
+"""
+
+__docformat__ = 'reStructuredText'
+
+import sys
+import os
+import os.path
+from types import StringType, UnicodeType
+from docutils import ApplicationError, DataError
+from docutils import frontend, nodes
+
+
+class SystemMessage(ApplicationError):
+
+ def __init__(self, system_message):
+ Exception.__init__(self, system_message.astext())
+
+
+class Reporter:
+
+ """
+ Info/warning/error reporter and ``system_message`` element generator.
+
+ Five levels of system messages are defined, along with corresponding
+ methods: `debug()`, `info()`, `warning()`, `error()`, and `severe()`.
+
+ There is typically one Reporter object per process. A Reporter object is
+ instantiated with thresholds for reporting (generating warnings) and
+ halting processing (raising exceptions), a switch to turn debug output on
+ or off, and an I/O stream for warnings. These are stored in the default
+ reporting category, '' (zero-length string).
+
+ Multiple reporting categories [#]_ may be set, each with its own reporting
+ and halting thresholds, debugging switch, and warning stream
+ (collectively a `ConditionSet`). Categories are hierarchical dotted-name
+ strings that look like attribute references: 'spam', 'spam.eggs',
+ 'neeeow.wum.ping'. The 'spam' category is the ancestor of
+ 'spam.bacon.eggs'. Unset categories inherit stored conditions from their
+ closest ancestor category that has been set.
+
+ When a system message is generated, the stored conditions from its
+ category (or ancestor if unset) are retrieved. The system message level
+ is compared to the thresholds stored in the category, and a warning or
+ error is generated as appropriate. Debug messages are produced iff the
+ stored debug switch is on. Message output is sent to the stored warning
+ stream.
+
+ The default category is '' (empty string). By convention, Writers should
+ retrieve reporting conditions from the 'writer' category (which, unless
+ explicitly set, defaults to the conditions of the default category).
+
+ The Reporter class also employs a modified form of the "Observer" pattern
+ [GoF95]_ to track system messages generated. The `attach_observer` method
+ should be called before parsing, with a bound method or function which
+ accepts system messages. The observer can be removed with
+ `detach_observer`, and another added in its place.
+
+ .. [#] The concept of "categories" was inspired by the log4j project:
+ http://jakarta.apache.org/log4j/.
+
+ .. [GoF95] Gamma, Helm, Johnson, Vlissides. *Design Patterns: Elements of
+ Reusable Object-Oriented Software*. Addison-Wesley, Reading, MA, USA,
+ 1995.
+ """
+
+ levels = 'DEBUG INFO WARNING ERROR SEVERE'.split()
+ """List of names for system message levels, indexed by level."""
+
+ def __init__(self, source, report_level, halt_level, stream=None,
+ debug=0):
+ """
+ Initialize the `ConditionSet` forthe `Reporter`'s default category.
+
+ :Parameters:
+
+ - `source`: The path to or description of the source data.
+ - `report_level`: The level at or above which warning output will
+ be sent to `stream`.
+ - `halt_level`: The level at or above which `SystemMessage`
+ exceptions will be raised, halting execution.
+ - `debug`: Show debug (level=0) system messages?
+ - `stream`: Where warning output is sent. Can be file-like (has a
+ ``.write`` method), a string (file name, opened for writing), or
+ `None` (implies `sys.stderr`; default).
+ """
+ self.source = source
+ """The path to or description of the source data."""
+
+ if stream is None:
+ stream = sys.stderr
+ elif type(stream) in (StringType, UnicodeType):
+ raise NotImplementedError('This should open a file for writing.')
+
+ self.categories = {'': ConditionSet(debug, report_level, halt_level,
+ stream)}
+ """Mapping of category names to conditions. Default category is ''."""
+
+ self.observers = []
+ """List of bound methods or functions to call with each system_message
+ created."""
+
+ def set_conditions(self, category, report_level, halt_level,
+ stream=None, debug=0):
+ if stream is None:
+ stream = sys.stderr
+ self.categories[category] = ConditionSet(debug, report_level,
+ halt_level, stream)
+
+ def unset_conditions(self, category):
+ if category and self.categories.has_key(category):
+ del self.categories[category]
+
+ __delitem__ = unset_conditions
+
+ def get_conditions(self, category):
+ while not self.categories.has_key(category):
+ category = category[:category.rfind('.') + 1][:-1]
+ return self.categories[category]
+
+ __getitem__ = get_conditions
+
+ def attach_observer(self, observer):
+ """
+ The `observer` parameter is a function or bound method which takes one
+ argument, a `nodes.system_message` instance.
+ """
+ self.observers.append(observer)
+
+ def detach_observer(self, observer):
+ self.observers.remove(observer)
+
+ def notify_observers(self, message):
+ for observer in self.observers:
+ observer(message)
+
+ def system_message(self, level, message, *children, **kwargs):
+ """
+ Return a system_message object.
+
+ Raise an exception or generate a warning if appropriate.
+ """
+ attributes = kwargs.copy()
+ category = kwargs.get('category', '')
+ if kwargs.has_key('category'):
+ del attributes['category']
+ if kwargs.has_key('base_node'):
+ source, line = get_source_line(kwargs['base_node'])
+ del attributes['base_node']
+ if source is not None:
+ attributes.setdefault('source', source)
+ if line is not None:
+ attributes.setdefault('line', line)
+ attributes.setdefault('source', self.source)
+ msg = nodes.system_message(message, level=level,
+ type=self.levels[level],
+ *children, **attributes)
+ debug, report_level, halt_level, stream = self[category].astuple()
+ if level >= report_level or debug and level == 0:
+ if category:
+ print >>stream, msg.astext(), '[%s]' % category
+ else:
+ print >>stream, msg.astext()
+ if level >= halt_level:
+ raise SystemMessage(msg)
+ if level > 0 or debug:
+ self.notify_observers(msg)
+ return msg
+
+ def debug(self, *args, **kwargs):
+ """
+ Level-0, "DEBUG": an internal reporting issue. Typically, there is no
+ effect on the processing. Level-0 system messages are handled
+ separately from the others.
+ """
+ return self.system_message(0, *args, **kwargs)
+
+ def info(self, *args, **kwargs):
+ """
+ Level-1, "INFO": a minor issue that can be ignored. Typically there is
+ no effect on processing, and level-1 system messages are not reported.
+ """
+ return self.system_message(1, *args, **kwargs)
+
+ def warning(self, *args, **kwargs):
+ """
+ Level-2, "WARNING": an issue that should be addressed. If ignored,
+ there may be unpredictable problems with the output.
+ """
+ return self.system_message(2, *args, **kwargs)
+
+ def error(self, *args, **kwargs):
+ """
+ Level-3, "ERROR": an error that should be addressed. If ignored, the
+ output will contain errors.
+ """
+ return self.system_message(3, *args, **kwargs)
+
+ def severe(self, *args, **kwargs):
+ """
+ Level-4, "SEVERE": a severe error that must be addressed. If ignored,
+ the output will contain severe errors. Typically level-4 system
+ messages are turned into exceptions which halt processing.
+ """
+ return self.system_message(4, *args, **kwargs)
+
+
+class ConditionSet:
+
+ """
+ A set of two thresholds (`report_level` & `halt_level`), a switch
+ (`debug`), and an I/O stream (`stream`), corresponding to one `Reporter`
+ category.
+ """
+
+ def __init__(self, debug, report_level, halt_level, stream):
+ self.debug = debug
+ self.report_level = report_level
+ self.halt_level = halt_level
+ self.stream = stream
+
+ def astuple(self):
+ return (self.debug, self.report_level, self.halt_level,
+ self.stream)
+
+
+class ExtensionOptionError(DataError): pass
+class BadOptionError(ExtensionOptionError): pass
+class BadOptionDataError(ExtensionOptionError): pass
+class DuplicateOptionError(ExtensionOptionError): pass
+
+
+def extract_extension_options(field_list, options_spec):
+ """
+ Return a dictionary mapping extension option names to converted values.
+
+ :Parameters:
+ - `field_list`: A flat field list without field arguments, where each
+ field body consists of a single paragraph only.
+ - `options_spec`: Dictionary mapping known option names to a
+ conversion function such as `int` or `float`.
+
+ :Exceptions:
+ - `KeyError` for unknown option names.
+ - `ValueError` for invalid option values (raised by the conversion
+ function).
+ - `DuplicateOptionError` for duplicate options.
+ - `BadOptionError` for invalid fields.
+ - `BadOptionDataError` for invalid option data (missing name,
+ missing data, bad quotes, etc.).
+ """
+ option_list = extract_options(field_list)
+ option_dict = assemble_option_dict(option_list, options_spec)
+ return option_dict
+
+def extract_options(field_list):
+ """
+ Return a list of option (name, value) pairs from field names & bodies.
+
+ :Parameter:
+ `field_list`: A flat field list, where each field name is a single
+ word and each field body consists of a single paragraph only.
+
+ :Exceptions:
+ - `BadOptionError` for invalid fields.
+ - `BadOptionDataError` for invalid option data (missing name,
+ missing data, bad quotes, etc.).
+ """
+ option_list = []
+ for field in field_list:
+ if len(field[0].astext().split()) != 1:
+ raise BadOptionError(
+ 'extension option field name may not contain multiple words')
+ name = str(field[0].astext().lower())
+ body = field[1]
+ if len(body) == 0:
+ data = None
+ elif len(body) > 1 or not isinstance(body[0], nodes.paragraph) \
+ or len(body[0]) != 1 or not isinstance(body[0][0], nodes.Text):
+ raise BadOptionDataError(
+ 'extension option field body may contain\n'
+ 'a single paragraph only (option "%s")' % name)
+ else:
+ data = body[0][0].astext()
+ option_list.append((name, data))
+ return option_list
+
+def assemble_option_dict(option_list, options_spec):
+ """
+ Return a mapping of option names to values.
+
+ :Parameters:
+ - `option_list`: A list of (name, value) pairs (the output of
+ `extract_options()`).
+ - `options_spec`: Dictionary mapping known option names to a
+ conversion function such as `int` or `float`.
+
+ :Exceptions:
+ - `KeyError` for unknown option names.
+ - `DuplicateOptionError` for duplicate options.
+ - `ValueError` for invalid option values (raised by conversion
+ function).
+ """
+ options = {}
+ for name, value in option_list:
+ convertor = options_spec[name] # raises KeyError if unknown
+ if options.has_key(name):
+ raise DuplicateOptionError('duplicate option "%s"' % name)
+ try:
+ options[name] = convertor(value)
+ except (ValueError, TypeError), detail:
+ raise detail.__class__('(option: "%s"; value: %r)\n%s'
+ % (name, value, detail))
+ return options
+
+
+class NameValueError(DataError): pass
+
+
+def extract_name_value(line):
+ """
+ Return a list of (name, value) from a line of the form "name=value ...".
+
+ :Exception:
+ `NameValueError` for invalid input (missing name, missing data, bad
+ quotes, etc.).
+ """
+ attlist = []
+ while line:
+ equals = line.find('=')
+ if equals == -1:
+ raise NameValueError('missing "="')
+ attname = line[:equals].strip()
+ if equals == 0 or not attname:
+ raise NameValueError(
+ 'missing attribute name before "="')
+ line = line[equals+1:].lstrip()
+ if not line:
+ raise NameValueError(
+ 'missing value after "%s="' % attname)
+ if line[0] in '\'"':
+ endquote = line.find(line[0], 1)
+ if endquote == -1:
+ raise NameValueError(
+ 'attribute "%s" missing end quote (%s)'
+ % (attname, line[0]))
+ if len(line) > endquote + 1 and line[endquote + 1].strip():
+ raise NameValueError(
+ 'attribute "%s" end quote (%s) not followed by '
+ 'whitespace' % (attname, line[0]))
+ data = line[1:endquote]
+ line = line[endquote+1:].lstrip()
+ else:
+ space = line.find(' ')
+ if space == -1:
+ data = line
+ line = ''
+ else:
+ data = line[:space]
+ line = line[space+1:].lstrip()
+ attlist.append((attname.lower(), data))
+ return attlist
+
+def normalize_name(name):
+ """Return a case- and whitespace-normalized name."""
+ return ' '.join(name.lower().split())
+
+def new_document(source, settings=None):
+ """
+ Return a new empty document object.
+
+ :Parameters:
+ `source` : string
+ The path to or description of the source text of the document.
+ `settings` : optparse.Values object
+ Runtime settings. If none provided, a default set will be used.
+ """
+ if settings is None:
+ settings = frontend.OptionParser().get_default_values()
+ reporter = Reporter(source, settings.report_level, settings.halt_level,
+ settings.warning_stream, settings.debug)
+ document = nodes.document(settings, reporter, source=source)
+ document.note_source(source, -1)
+ return document
+
+def clean_rcs_keywords(paragraph, keyword_substitutions):
+ if len(paragraph) == 1 and isinstance(paragraph[0], nodes.Text):
+ textnode = paragraph[0]
+ for pattern, substitution in keyword_substitutions:
+ match = pattern.match(textnode.data)
+ if match:
+ textnode.data = pattern.sub(substitution, textnode.data)
+ return
+
+def relative_path(source, target):
+ """
+ Build and return a path to `target`, relative to `source`.
+
+ If there is no common prefix, return the absolute path to `target`.
+ """
+ source_parts = os.path.abspath(source or 'dummy_file').split(os.sep)
+ target_parts = os.path.abspath(target).split(os.sep)
+ # Check first 2 parts because '/dir'.split('/') == ['', 'dir']:
+ if source_parts[:2] != target_parts[:2]:
+ # Nothing in common between paths.
+ # Return absolute path, using '/' for URLs:
+ return '/'.join(target_parts)
+ source_parts.reverse()
+ target_parts.reverse()
+ while (source_parts and target_parts
+ and source_parts[-1] == target_parts[-1]):
+ # Remove path components in common:
+ source_parts.pop()
+ target_parts.pop()
+ target_parts.reverse()
+ parts = ['..'] * (len(source_parts) - 1) + target_parts
+ return '/'.join(parts)
+
+def get_source_line(node):
+ """
+ Return the "source" and "line" attributes from the `node` given or from
+ it's closest ancestor.
+ """
+ while node:
+ if node.source or node.line:
+ return node.source, node.line
+ node = node.parent
+ return None, None