Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

adding sphinx and south

  • Loading branch information...
commit 9b0c80f6742625e47b7525a51dc5a769700a3c8c 1 parent 6026ed7
@camd camd authored
Showing with 33,142 additions and 0 deletions.
  1. +214 −0 lib/python/docutils/__init__.py
  2. +37 −0 lib/python/docutils/_compat.py
  3. +133 −0 lib/python/docutils/_string_template_compat.py
  4. +667 −0 lib/python/docutils/core.py
  5. +207 −0 lib/python/docutils/error_reporting.py
  6. +97 −0 lib/python/docutils/examples.py
  7. +788 −0 lib/python/docutils/frontend.py
  8. +497 −0 lib/python/docutils/io.py
  9. +40 −0 lib/python/docutils/languages/__init__.py
  10. +58 −0 lib/python/docutils/languages/af.py
  11. +60 −0 lib/python/docutils/languages/ca.py
  12. +60 −0 lib/python/docutils/languages/cs.py
  13. +58 −0 lib/python/docutils/languages/de.py
  14. +60 −0 lib/python/docutils/languages/en.py
  15. +61 −0 lib/python/docutils/languages/eo.py
  16. +59 −0 lib/python/docutils/languages/es.py
  17. +60 −0 lib/python/docutils/languages/fi.py
  18. +58 −0 lib/python/docutils/languages/fr.py
  19. +63 −0 lib/python/docutils/languages/gl.py
  20. +60 −0 lib/python/docutils/languages/he.py
  21. +58 −0 lib/python/docutils/languages/it.py
  22. +61 −0 lib/python/docutils/languages/ja.py
  23. +122 −0 lib/python/docutils/languages/lt.py
  24. +60 −0 lib/python/docutils/languages/nl.py
  25. +62 −0 lib/python/docutils/languages/pl.py
  26. +60 −0 lib/python/docutils/languages/pt_br.py
  27. +59 −0 lib/python/docutils/languages/ru.py
  28. +58 −0 lib/python/docutils/languages/sk.py
  29. +59 −0 lib/python/docutils/languages/sv.py
  30. +67 −0 lib/python/docutils/languages/zh_cn.py
  31. +66 −0 lib/python/docutils/languages/zh_tw.py
  32. +47 −0 lib/python/docutils/math/__init__.py
  33. +560 −0 lib/python/docutils/math/latex2mathml.py
  34. +5,254 −0 lib/python/docutils/math/math2html.py
  35. +662 −0 lib/python/docutils/math/tex2unichar.py
  36. +788 −0 lib/python/docutils/math/unichar2tex.py
  37. +1,933 −0 lib/python/docutils/nodes.py
  38. +47 −0 lib/python/docutils/parsers/__init__.py
  39. +20 −0 lib/python/docutils/parsers/null.py
  40. +390 −0 lib/python/docutils/parsers/rst/__init__.py
  41. +397 −0 lib/python/docutils/parsers/rst/directives/__init__.py
  42. +96 −0 lib/python/docutils/parsers/rst/directives/admonitions.py
  43. +289 −0 lib/python/docutils/parsers/rst/directives/body.py
  44. +86 −0 lib/python/docutils/parsers/rst/directives/html.py
  45. +162 −0 lib/python/docutils/parsers/rst/directives/images.py
  46. +522 −0 lib/python/docutils/parsers/rst/directives/misc.py
  47. +126 −0 lib/python/docutils/parsers/rst/directives/parts.py
  48. +29 −0 lib/python/docutils/parsers/rst/directives/references.py
  49. +454 −0 lib/python/docutils/parsers/rst/directives/tables.py
  50. +17 −0 lib/python/docutils/parsers/rst/include/README.txt
  51. +162 −0 lib/python/docutils/parsers/rst/include/isoamsa.txt
  52. +126 −0 lib/python/docutils/parsers/rst/include/isoamsb.txt
  53. +29 −0 lib/python/docutils/parsers/rst/include/isoamsc.txt
  54. +96 −0 lib/python/docutils/parsers/rst/include/isoamsn.txt
  55. +62 −0 lib/python/docutils/parsers/rst/include/isoamso.txt
  56. +191 −0 lib/python/docutils/parsers/rst/include/isoamsr.txt
  57. +46 −0 lib/python/docutils/parsers/rst/include/isobox.txt
  58. +73 −0 lib/python/docutils/parsers/rst/include/isocyr1.txt
  59. +32 −0 lib/python/docutils/parsers/rst/include/isocyr2.txt
  60. +20 −0 lib/python/docutils/parsers/rst/include/isodia.txt
  61. +55 −0 lib/python/docutils/parsers/rst/include/isogrk1.txt
  62. +26 −0 lib/python/docutils/parsers/rst/include/isogrk2.txt
  63. +52 −0 lib/python/docutils/parsers/rst/include/isogrk3.txt
  64. +49 −0 lib/python/docutils/parsers/rst/include/isogrk4-wide.txt
  65. +8 −0 lib/python/docutils/parsers/rst/include/isogrk4.txt
  66. +68 −0 lib/python/docutils/parsers/rst/include/isolat1.txt
  67. +128 −0 lib/python/docutils/parsers/rst/include/isolat2.txt
  68. +58 −0 lib/python/docutils/parsers/rst/include/isomfrk-wide.txt
  69. +11 −0 lib/python/docutils/parsers/rst/include/isomfrk.txt
  70. +32 −0 lib/python/docutils/parsers/rst/include/isomopf-wide.txt
  71. +13 −0 lib/python/docutils/parsers/rst/include/isomopf.txt
  72. +58 −0 lib/python/docutils/parsers/rst/include/isomscr-wide.txt
  73. +17 −0 lib/python/docutils/parsers/rst/include/isomscr.txt
  74. +82 −0 lib/python/docutils/parsers/rst/include/isonum.txt
  75. +90 −0 lib/python/docutils/parsers/rst/include/isopub.txt
  76. +168 −0 lib/python/docutils/parsers/rst/include/isotech.txt
  77. +554 −0 lib/python/docutils/parsers/rst/include/mmlalias.txt
  78. +113 −0 lib/python/docutils/parsers/rst/include/mmlextra-wide.txt
  79. +87 −0 lib/python/docutils/parsers/rst/include/mmlextra.txt
  80. +68 −0 lib/python/docutils/parsers/rst/include/s5defs.txt
  81. +102 −0 lib/python/docutils/parsers/rst/include/xhtml1-lat1.txt
  82. +37 −0 lib/python/docutils/parsers/rst/include/xhtml1-special.txt
  83. +130 −0 lib/python/docutils/parsers/rst/include/xhtml1-symbol.txt
  84. +29 −0 lib/python/docutils/parsers/rst/languages/__init__.py
  85. +106 −0 lib/python/docutils/parsers/rst/languages/af.py
  86. +125 −0 lib/python/docutils/parsers/rst/languages/ca.py
  87. +108 −0 lib/python/docutils/parsers/rst/languages/cs.py
  88. +103 −0 lib/python/docutils/parsers/rst/languages/de.py
  89. +110 −0 lib/python/docutils/parsers/rst/languages/en.py
  90. +118 −0 lib/python/docutils/parsers/rst/languages/eo.py
  91. +125 −0 lib/python/docutils/parsers/rst/languages/es.py
  92. +98 −0 lib/python/docutils/parsers/rst/languages/fi.py
  93. +103 −0 lib/python/docutils/parsers/rst/languages/fr.py
  94. +111 −0 lib/python/docutils/parsers/rst/languages/gl.py
  95. +108 −0 lib/python/docutils/parsers/rst/languages/he.py
  96. +97 −0 lib/python/docutils/parsers/rst/languages/it.py
  97. +119 −0 lib/python/docutils/parsers/rst/languages/ja.py
  98. +109 −0 lib/python/docutils/parsers/rst/languages/lt.py
  99. +112 −0 lib/python/docutils/parsers/rst/languages/nl.py
  100. +102 −0 lib/python/docutils/parsers/rst/languages/pl.py
  101. +108 −0 lib/python/docutils/parsers/rst/languages/pt_br.py
  102. +89 −0 lib/python/docutils/parsers/rst/languages/ru.py
  103. +95 −0 lib/python/docutils/parsers/rst/languages/sk.py
  104. +94 −0 lib/python/docutils/parsers/rst/languages/sv.py
  105. +104 −0 lib/python/docutils/parsers/rst/languages/zh_cn.py
  106. +109 −0 lib/python/docutils/parsers/rst/languages/zh_tw.py
  107. +394 −0 lib/python/docutils/parsers/rst/roles.py
  108. +3,049 −0 lib/python/docutils/parsers/rst/states.py
  109. +544 −0 lib/python/docutils/parsers/rst/tableparser.py
  110. +107 −0 lib/python/docutils/readers/__init__.py
  111. +46 −0 lib/python/docutils/readers/doctree.py
  112. +48 −0 lib/python/docutils/readers/pep.py
  113. +66 −0 lib/python/docutils/readers/standalone.py
  114. +1,538 −0 lib/python/docutils/statemachine.py
  115. +172 −0 lib/python/docutils/transforms/__init__.py
  116. +52 −0 lib/python/docutils/transforms/components.py
  117. +512 −0 lib/python/docutils/transforms/frontmatter.py
  118. +144 −0 lib/python/docutils/transforms/misc.py
  119. +180 −0 lib/python/docutils/transforms/parts.py
  120. +305 −0 lib/python/docutils/transforms/peps.py
  121. +903 −0 lib/python/docutils/transforms/references.py
  122. +203 −0 lib/python/docutils/transforms/universal.py
  123. +88 −0 lib/python/docutils/transforms/writer_aux.py
  124. +136 −0 lib/python/docutils/urischemes.py
  125. +731 −0 lib/python/docutils/utils/__init__.py
  126. +134 −0 lib/python/docutils/utils/code_analyzer.py
  127. +212 −0 lib/python/docutils/utils/punctuation_chars.py
  128. +81 −0 lib/python/docutils/utils/roman.py
  129. +134 −0 lib/python/docutils/writers/__init__.py
  130. +179 −0 lib/python/docutils/writers/docutils_xml.py
  131. +1,692 −0 lib/python/docutils/writers/html4css1/__init__.py
  132. +311 −0 lib/python/docutils/writers/html4css1/html4css1.css
  133. +8 −0 lib/python/docutils/writers/html4css1/template.txt
Sorry, we could not display the entire diff because too many files (614) changed.
View
214 lib/python/docutils/__init__.py
@@ -0,0 +1,214 @@
+# $Id: __init__.py 7446 2012-06-17 20:47:10Z grubert $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+This is the Docutils (Python Documentation Utilities) package.
+
+Package Structure
+=================
+
+Modules:
+
+- __init__.py: Contains component base classes, exception classes, and
+ Docutils version information.
+
+- core.py: Contains the ``Publisher`` class and ``publish_*()`` convenience
+ functions.
+
+- frontend.py: Runtime settings (command-line interface, configuration files)
+ 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.
+
+- 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.
+
+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.
+
+- utils: Contains the ``Reporter`` system warning class and miscellaneous
+ utilities used by readers, writers, and transforms.
+
+- writers: Format-specific output translators.
+"""
+
+__docformat__ = 'reStructuredText'
+
+__version__ = '0.9.1'
+"""``major.minor.micro`` version number. The micro number is bumped for API
+changes, for new functionality, and for interim project releases. The minor
+number is bumped whenever there is a significant project release. The major
+number will be bumped when the project is feature-complete, and perhaps if
+there is a major change in the design."""
+
+__version_details__ = 'release'
+"""Extra version details (e.g. 'snapshot 2005-05-29, r3410', 'repository',
+'release'), modified automatically & manually."""
+
+import sys
+
+class ApplicationError(StandardError):
+ # Workaround:
+ # In Python < 2.6, unicode(<exception instance>) calls `str` on the
+ # arg and therefore, e.g., unicode(StandardError(u'\u234')) fails
+ # with UnicodeDecodeError.
+ if sys.version_info < (2,6):
+ def __unicode__(self):
+ return u', '.join(self.args)
+
+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.
+
+ Defines runtime settings and associated command-line options, as used by
+ `docutils.frontend.OptionParser`. This is a tuple of:
+
+ - Option group title (string or `None` which implies no group, just a list
+ of single options).
+
+ - Description (string or `None`).
+
+ - A sequence of option tuples. Each consists of:
+
+ - Help text (string)
+
+ - List of option strings (e.g. ``['-Q', '--quux']``).
+
+ - Dictionary of keyword arguments sent to the OptionParser/OptionGroup
+ ``add_option`` method.
+
+ Runtime setting names are derived implicitly from long option names
+ ('--a-setting' becomes ``settings.a_setting``) or explicitly from the
+ 'dest' keyword argument.
+
+ Most settings will also have a 'validator' keyword & function. The
+ validator function validates setting values (from configuration files
+ and command-line option arguments) and converts them to appropriate
+ types. For example, the ``docutils.frontend.validate_boolean``
+ function, **required by all boolean settings**, converts true values
+ ('1', 'on', 'yes', and 'true') to 1 and false values ('0', 'off',
+ 'no', 'false', and '') to 0. Validators need only be set once per
+ setting. See the `docutils.frontend.validate_*` functions.
+
+ See the optparse docs for more details.
+
+ - More triples of group title, description, options, as many times as
+ needed. Thus, `settings_spec` tuples can be simply concatenated.
+ """
+
+ settings_defaults = None
+ """A dictionary of defaults for settings not in `settings_spec` (internal
+ settings, intended to be inaccessible by command-line and config file).
+ Override in subclasses."""
+
+ 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."""
+
+ config_section = None
+ """The name of the config file section specific to this component
+ (lowercase, no brackets). Override in subclasses."""
+
+ config_section_dependencies = None
+ """A list of names of config file sections that are to be applied before
+ `config_section`, in order (from general to specific). In other words,
+ the settings in `config_section` are to be overlaid on top of the settings
+ from these sections. The "general" section is assumed implicitly.
+ Override in subclasses."""
+
+
+class TransformSpec:
+
+ """
+ Runtime transform specification base class.
+
+ TransformSpec subclass objects used by `docutils.transforms.Transformer`.
+ """
+
+ def get_transforms(self):
+ """Transforms required by this class. Override in subclasses."""
+ if self.default_transforms != ():
+ import warnings
+ warnings.warn('default_transforms attribute deprecated.\n'
+ 'Use get_transforms() method instead.',
+ DeprecationWarning)
+ return list(self.default_transforms)
+ return []
+
+ # Deprecated; for compatibility.
+ default_transforms = ()
+
+ unknown_reference_resolvers = ()
+ """List of functions to try to resolve unknown references. Unknown
+ references have a 'refname' attribute which doesn't correspond to any
+ target in the document. Called when the transforms in
+ `docutils.tranforms.references` are unable to find a correct target. The
+ list should contain functions which will try to resolve unknown
+ references, with the following signature::
+
+ def reference_resolver(node):
+ '''Returns boolean: true if resolved, false if not.'''
+
+ If the function is able to resolve the reference, it should also remove
+ the 'refname' attribute and mark the node as resolved::
+
+ del node['refname']
+ node.resolved = 1
+
+ Each function must have a "priority" attribute which will affect the order
+ the unknown_reference_resolvers are run::
+
+ reference_resolver.priority = 100
+
+ Override in subclasses."""
+
+
+class Component(SettingsSpec, TransformSpec):
+
+ """Base class for Docutils components."""
+
+ component_type = None
+ """Name of the component type ('reader', 'parser', 'writer'). 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
View
37 lib/python/docutils/_compat.py
@@ -0,0 +1,37 @@
+# $Id: _compat.py 7316 2012-01-19 11:31:58Z milde $
+# Author: Georg Brandl <georg@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+Python 2/3 compatibility definitions.
+
+This module currently provides the following helper symbols:
+
+* bytes (name of byte string type; str in 2.x, bytes in 3.x)
+* b (function converting a string literal to an ASCII byte string;
+ can be also used to convert a Unicode string into a byte string)
+* u_prefix (unicode repr prefix: 'u' in 2.x, '' in 3.x)
+ (Required in docutils/test/test_publisher.py)
+* BytesIO (a StringIO class that works with bytestrings)
+"""
+
+import sys
+
+if sys.version_info < (3,0):
+ b = bytes = str
+ u_prefix = 'u'
+ from StringIO import StringIO as BytesIO
+else:
+ import builtins
+ bytes = builtins.bytes
+ u_prefix = ''
+ def b(s):
+ if isinstance(s, str):
+ return s.encode('latin1')
+ elif isinstance(s, bytes):
+ return s
+ else:
+ raise TypeError("Invalid argument %r for b()" % (s,))
+ # using this hack since 2to3 "fixes" the relative import
+ # when using ``from io import BytesIO``
+ BytesIO = __import__('io').BytesIO
View
133 lib/python/docutils/_string_template_compat.py
@@ -0,0 +1,133 @@
+#!/usr/bin/env python
+# -*- coding: utf8 -*-
+
+# string_template_compat.py: string.Template for Python <= 2.4
+# =====================================================
+
+# This is just an excerpt of the standard string module to provide backwards
+# compatibility.
+
+import re as _re
+
+class _multimap:
+ """Helper class for combining multiple mappings.
+
+ Used by .{safe_,}substitute() to combine the mapping and keyword
+ arguments.
+ """
+ def __init__(self, primary, secondary):
+ self._primary = primary
+ self._secondary = secondary
+
+ def __getitem__(self, key):
+ try:
+ return self._primary[key]
+ except KeyError:
+ return self._secondary[key]
+
+
+class _TemplateMetaclass(type):
+ pattern = r"""
+ %(delim)s(?:
+ (?P<escaped>%(delim)s) | # Escape sequence of two delimiters
+ (?P<named>%(id)s) | # delimiter and a Python identifier
+ {(?P<braced>%(id)s)} | # delimiter and a braced identifier
+ (?P<invalid>) # Other ill-formed delimiter exprs
+ )
+ """
+
+ def __init__(cls, name, bases, dct):
+ super(_TemplateMetaclass, cls).__init__(name, bases, dct)
+ if 'pattern' in dct:
+ pattern = cls.pattern
+ else:
+ pattern = _TemplateMetaclass.pattern % {
+ 'delim' : _re.escape(cls.delimiter),
+ 'id' : cls.idpattern,
+ }
+ cls.pattern = _re.compile(pattern, _re.IGNORECASE | _re.VERBOSE)
+
+
+class Template:
+ """A string class for supporting $-substitutions."""
+ __metaclass__ = _TemplateMetaclass
+
+ delimiter = '$'
+ idpattern = r'[_a-z][_a-z0-9]*'
+
+ def __init__(self, template):
+ self.template = template
+
+ # Search for $$, $identifier, ${identifier}, and any bare $'s
+
+ def _invalid(self, mo):
+ i = mo.start('invalid')
+ lines = self.template[:i].splitlines(True)
+ if not lines:
+ colno = 1
+ lineno = 1
+ else:
+ colno = i - len(''.join(lines[:-1]))
+ lineno = len(lines)
+ raise ValueError('Invalid placeholder in string: line %d, col %d' %
+ (lineno, colno))
+
+ def substitute(self, *args, **kws):
+ if len(args) > 1:
+ raise TypeError('Too many positional arguments')
+ if not args:
+ mapping = kws
+ elif kws:
+ mapping = _multimap(kws, args[0])
+ else:
+ mapping = args[0]
+ # Helper function for .sub()
+ def convert(mo):
+ # Check the most common path first.
+ named = mo.group('named') or mo.group('braced')
+ if named is not None:
+ val = mapping[named]
+ # We use this idiom instead of str() because the latter will
+ # fail if val is a Unicode containing non-ASCII characters.
+ return '%s' % (val,)
+ if mo.group('escaped') is not None:
+ return self.delimiter
+ if mo.group('invalid') is not None:
+ self._invalid(mo)
+ raise ValueError('Unrecognized named group in pattern',
+ self.pattern)
+ return self.pattern.sub(convert, self.template)
+
+ def safe_substitute(self, *args, **kws):
+ if len(args) > 1:
+ raise TypeError('Too many positional arguments')
+ if not args:
+ mapping = kws
+ elif kws:
+ mapping = _multimap(kws, args[0])
+ else:
+ mapping = args[0]
+ # Helper function for .sub()
+ def convert(mo):
+ named = mo.group('named')
+ if named is not None:
+ try:
+ # We use this idiom instead of str() because the latter
+ # will fail if val is a Unicode containing non-ASCII
+ return '%s' % (mapping[named],)
+ except KeyError:
+ return self.delimiter + named
+ braced = mo.group('braced')
+ if braced is not None:
+ try:
+ return '%s' % (mapping[braced],)
+ except KeyError:
+ return self.delimiter + '{' + braced + '}'
+ if mo.group('escaped') is not None:
+ return self.delimiter
+ if mo.group('invalid') is not None:
+ return self.delimiter
+ raise ValueError('Unrecognized named group in pattern',
+ self.pattern)
+ return self.pattern.sub(convert, self.template)
+
View
667 lib/python/docutils/core.py
@@ -0,0 +1,667 @@
+# $Id: core.py 7384 2012-03-19 22:59:09Z milde $
+# Author: David Goodger <goodger@python.org>
+# 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`. See `The Docutils Publisher`_.
+
+.. _The Docutils Publisher: http://docutils.sf.net/docs/api/publisher.html
+"""
+
+__docformat__ = 'reStructuredText'
+
+import sys
+import pprint
+from docutils import __version__, __version_details__, SettingsSpec
+from docutils import frontend, io, utils, readers, writers
+from docutils.frontend import OptionParser
+from docutils.transforms import Transformer
+from docutils.error_reporting import ErrorOutput, ErrorString
+import docutils.readers.doctree
+
+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.document = None
+ """The document tree (`docutils.nodes` objects)."""
+
+ self.reader = reader
+ """A `docutils.readers.Reader` instance."""
+
+ self.parser = parser
+ """A `docutils.parsers.Parser` instance."""
+
+ self.writer = writer
+ """A `docutils.writers.Writer` instance."""
+
+ for component in 'reader', 'parser', 'writer':
+ assert not isinstance(getattr(self, component), str), (
+ 'passed string "%s" as "%s" parameter; pass an instance, '
+ 'or use the "%s_name" parameter instead (in '
+ 'docutils.core.publish_* convenience functions).'
+ % (getattr(self, component), component, component))
+
+ self.source = source
+ """The source of input data, a `docutils.io.Input` instance."""
+
+ self.source_class = source_class
+ """The class for dynamically created source objects."""
+
+ self.destination = destination
+ """The destination for docutils output, a `docutils.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()`."""
+
+ self._stderr = ErrorOutput()
+
+ 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, config_section=None,
+ **defaults):
+ if config_section:
+ if not settings_spec:
+ settings_spec = SettingsSpec()
+ settings_spec.config_section = config_section
+ parts = config_section.split()
+ if len(parts) > 1 and parts[-1] == 'application':
+ settings_spec.config_section_dependencies = ['applications']
+ #@@@ Add self.source & self.destination to components in future?
+ option_parser = OptionParser(
+ components=(self.parser, self.reader, self.writer, settings_spec),
+ defaults=defaults, read_config_files=True,
+ usage=usage, description=description)
+ return option_parser
+
+ def get_settings(self, usage=None, description=None,
+ settings_spec=None, config_section=None, **defaults):
+ """
+ Set and return default settings (overrides in `defaults` dict).
+
+ 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, config_section, **defaults)
+ self.settings = option_parser.get_default_values()
+ return self.settings
+
+ def process_programmatic_settings(self, settings_spec,
+ settings_overrides,
+ config_section):
+ if self.settings is None:
+ defaults = (settings_overrides or {}).copy()
+ # Propagate exceptions by default when used programmatically:
+ defaults.setdefault('traceback', True)
+ self.get_settings(settings_spec=settings_spec,
+ config_section=config_section,
+ **defaults)
+
+ def process_command_line(self, argv=None, usage=None, description=None,
+ settings_spec=None, config_section=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, config_section, **defaults)
+ if argv is None:
+ argv = sys.argv[1:]
+ # converting to Unicode (Python 3 does this automatically):
+ if sys.version_info < (3,0):
+ # TODO: make this failsafe and reversible?
+ argv_encoding = (frontend.locale_encoding or 'ascii')
+ argv = [a.decode(argv_encoding) for a in argv]
+ 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
+ # Raise IOError instead of system exit with `tracback == True`
+ # TODO: change io.FileInput's default behaviour and remove this hack
+ try:
+ self.source = self.source_class(
+ source=source, source_path=source_path,
+ encoding=self.settings.input_encoding,
+ handle_io_errors=False)
+ except TypeError:
+ 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,
+ error_handler=self.settings.output_encoding_error_handler)
+ # Raise IOError instead of system exit with `tracback == True`
+ # TODO: change io.FileInput's default behaviour and remove this hack
+ self.destination.handle_io_errors=False
+
+ def apply_transforms(self):
+ self.document.transformer.populate_from_components(
+ (self.source, self.reader, self.reader.parser, self.writer,
+ self.destination))
+ self.document.transformer.apply_transforms()
+
+ def publish(self, argv=None, usage=None, description=None,
+ settings_spec=None, settings_overrides=None,
+ config_section=None, enable_exit_status=False):
+ """
+ Process command line options and arguments (if `self.settings` not
+ already set), run `self.reader` and then `self.writer`. Return
+ `self.writer`'s output.
+ """
+ exit = None
+ try:
+ if self.settings is None:
+ self.process_command_line(
+ argv, usage, description, settings_spec, config_section,
+ **(settings_overrides or {}))
+ self.set_io()
+ self.document = self.reader.read(self.source, self.parser,
+ self.settings)
+ self.apply_transforms()
+ output = self.writer.write(self.document, self.destination)
+ self.writer.assemble_parts()
+ except SystemExit, error:
+ exit = 1
+ exit_status = error.code
+ except Exception, error:
+ if not self.settings: # exception too early to report nicely
+ raise
+ if self.settings.traceback: # Propagate exceptions?
+ self.debugging_dumps()
+ raise
+ self.report_Exception(error)
+ exit = True
+ exit_status = 1
+ self.debugging_dumps()
+ if (enable_exit_status and self.document
+ and (self.document.reporter.max_level
+ >= self.settings.exit_status_level)):
+ sys.exit(self.document.reporter.max_level + 10)
+ elif exit:
+ sys.exit(exit_status)
+ return output
+
+ def debugging_dumps(self):
+ if not self.document:
+ return
+ if self.settings.dump_settings:
+ print >>self._stderr, '\n::: Runtime settings:'
+ print >>self._stderr, pprint.pformat(self.settings.__dict__)
+ if self.settings.dump_internals:
+ print >>self._stderr, '\n::: Document internals:'
+ print >>self._stderr, pprint.pformat(self.document.__dict__)
+ if self.settings.dump_transforms:
+ print >>self._stderr, '\n::: Transforms applied:'
+ print >>self._stderr, (' (priority, transform class, '
+ 'pending node details, keyword args)')
+ print >>self._stderr, pprint.pformat(
+ [(priority, '%s.%s' % (xclass.__module__, xclass.__name__),
+ pending and pending.details, kwargs)
+ for priority, xclass, pending, kwargs
+ in self.document.transformer.applied])
+ if self.settings.dump_pseudo_xml:
+ print >>self._stderr, '\n::: Pseudo-XML:'
+ print >>self._stderr, self.document.pformat().encode(
+ 'raw_unicode_escape')
+
+ def report_Exception(self, error):
+ if isinstance(error, utils.SystemMessage):
+ self.report_SystemMessage(error)
+ elif isinstance(error, UnicodeEncodeError):
+ self.report_UnicodeError(error)
+ elif isinstance(error, io.InputError):
+ self._stderr.write(u'Unable to open source file for reading:\n'
+ u' %s\n' % ErrorString(error))
+ elif isinstance(error, io.OutputError):
+ self._stderr.write(
+ u'Unable to open destination file for writing:\n'
+ u' %s\n' % ErrorString(error))
+ else:
+ print >>self._stderr, u'%s' % ErrorString(error)
+ print >>self._stderr, ("""\
+Exiting due to error. Use "--traceback" to diagnose.
+Please report errors to <docutils-users@lists.sf.net>.
+Include "--traceback" output, Docutils version (%s [%s]),
+Python version (%s), your OS type & version, and the
+command line used.""" % (__version__, __version_details__,
+ sys.version.split()[0]))
+
+ def report_SystemMessage(self, error):
+ print >>self._stderr, ('Exiting due to level-%s (%s) system message.'
+ % (error.level,
+ utils.Reporter.levels[error.level]))
+
+ def report_UnicodeError(self, error):
+ data = error.object[error.start:error.end]
+ self._stderr.write(
+ '%s\n'
+ '\n'
+ 'The specified output encoding (%s) cannot\n'
+ 'handle all of the output.\n'
+ 'Try setting "--output-encoding-error-handler" to\n'
+ '\n'
+ '* "xmlcharrefreplace" (for HTML & XML output);\n'
+ ' the output will contain "%s" and should be usable.\n'
+ '* "backslashreplace" (for other output formats);\n'
+ ' look for "%s" in the output.\n'
+ '* "replace"; look for "?" in the output.\n'
+ '\n'
+ '"--output-encoding-error-handler" is currently set to "%s".\n'
+ '\n'
+ 'Exiting due to error. Use "--traceback" to diagnose.\n'
+ 'If the advice above doesn\'t eliminate the error,\n'
+ 'please report it to <docutils-users@lists.sf.net>.\n'
+ 'Include "--traceback" output, Docutils version (%s),\n'
+ 'Python version (%s), your OS type & version, and the\n'
+ 'command line used.\n'
+ % (ErrorString(error),
+ self.settings.output_encoding,
+ data.encode('ascii', 'xmlcharrefreplace'),
+ data.encode('ascii', 'backslashreplace'),
+ self.settings.output_encoding_error_handler,
+ __version__, sys.version.split()[0]))
+
+default_usage = '%prog [options] [<source> [<destination>]]'
+default_description = ('Reads from <source> (default is stdin) and writes to '
+ '<destination> (default is stdout). See '
+ '<http://docutils.sf.net/docs/user/config.html> for '
+ 'the full reference.')
+
+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, config_section=None,
+ enable_exit_status=True, argv=None,
+ usage=default_usage, description=default_description):
+ """
+ Set up & run a `Publisher` for command-line-based file I/O (input and
+ output file paths taken automatically from the command line). Return the
+ encoded string output also.
+
+ Parameters: see `publish_programmatically` for the remainder.
+
+ - `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)
+ output = pub.publish(
+ argv, usage, description, settings_spec, settings_overrides,
+ config_section=config_section, enable_exit_status=enable_exit_status)
+ return output
+
+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,
+ config_section=None, enable_exit_status=False):
+ """
+ Set up & run a `Publisher` for programmatic use with file-like I/O.
+ Return the encoded string output also.
+
+ Parameters: see `publish_programmatically`.
+ """
+ output, pub = publish_programmatically(
+ source_class=io.FileInput, source=source, source_path=source_path,
+ destination_class=io.FileOutput,
+ destination=destination, destination_path=destination_path,
+ reader=reader, reader_name=reader_name,
+ parser=parser, parser_name=parser_name,
+ writer=writer, writer_name=writer_name,
+ settings=settings, settings_spec=settings_spec,
+ settings_overrides=settings_overrides,
+ config_section=config_section,
+ enable_exit_status=enable_exit_status)
+ return output
+
+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, config_section=None,
+ enable_exit_status=False):
+ """
+ Set up & run a `Publisher` for programmatic use with string I/O. Return
+ the encoded string or Unicode string output.
+
+ 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. Here's one way::
+
+ publish_string(..., settings_overrides={'output_encoding': 'unicode'})
+
+ Similarly for Unicode string input (`source`)::
+
+ publish_string(..., settings_overrides={'input_encoding': 'unicode'})
+
+ Parameters: see `publish_programmatically`.
+ """
+ output, pub = publish_programmatically(
+ source_class=io.StringInput, source=source, source_path=source_path,
+ destination_class=io.StringOutput,
+ destination=None, destination_path=destination_path,
+ reader=reader, reader_name=reader_name,
+ parser=parser, parser_name=parser_name,
+ writer=writer, writer_name=writer_name,
+ settings=settings, settings_spec=settings_spec,
+ settings_overrides=settings_overrides,
+ config_section=config_section,
+ enable_exit_status=enable_exit_status)
+ return output
+
+def publish_parts(source, source_path=None, source_class=io.StringInput,
+ 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, config_section=None,
+ enable_exit_status=False):
+ """
+ Set up & run a `Publisher`, and return a dictionary of document parts.
+ Dictionary keys are the names of parts, and values are Unicode strings;
+ encoding is up to the client. For programmatic use with string I/O.
+
+ For encoded string input, be sure to set the 'input_encoding' setting to
+ the desired encoding. Set it to 'unicode' for unencoded Unicode string
+ input. Here's how::
+
+ publish_parts(..., settings_overrides={'input_encoding': 'unicode'})
+
+ Parameters: see `publish_programmatically`.
+ """
+ output, pub = publish_programmatically(
+ source=source, source_path=source_path, source_class=source_class,
+ destination_class=io.StringOutput,
+ destination=None, destination_path=destination_path,
+ reader=reader, reader_name=reader_name,
+ parser=parser, parser_name=parser_name,
+ writer=writer, writer_name=writer_name,
+ settings=settings, settings_spec=settings_spec,
+ settings_overrides=settings_overrides,
+ config_section=config_section,
+ enable_exit_status=enable_exit_status)
+ return pub.writer.parts
+
+def publish_doctree(source, source_path=None,
+ source_class=io.StringInput,
+ reader=None, reader_name='standalone',
+ parser=None, parser_name='restructuredtext',
+ settings=None, settings_spec=None,
+ settings_overrides=None, config_section=None,
+ enable_exit_status=False):
+ """
+ Set up & run a `Publisher` for programmatic use with string I/O.
+ Return the document tree.
+
+ For encoded string input, be sure to set the 'input_encoding' setting to
+ the desired encoding. Set it to 'unicode' for unencoded Unicode string
+ input. Here's one way::
+
+ publish_doctree(..., settings_overrides={'input_encoding': 'unicode'})
+
+ Parameters: see `publish_programmatically`.
+ """
+ pub = Publisher(reader=reader, parser=parser, writer=None,
+ settings=settings,
+ source_class=source_class,
+ destination_class=io.NullOutput)
+ pub.set_components(reader_name, parser_name, 'null')
+ pub.process_programmatic_settings(
+ settings_spec, settings_overrides, config_section)
+ pub.set_source(source, source_path)
+ pub.set_destination(None, None)
+ output = pub.publish(enable_exit_status=enable_exit_status)
+ return pub.document
+
+def publish_from_doctree(document, destination_path=None,
+ writer=None, writer_name='pseudoxml',
+ settings=None, settings_spec=None,
+ settings_overrides=None, config_section=None,
+ enable_exit_status=False):
+ """
+ Set up & run a `Publisher` to render from an existing document
+ tree data structure, for programmatic use with string I/O. Return
+ the encoded string output.
+
+ Note that document.settings is overridden; if you want to use the settings
+ of the original `document`, pass settings=document.settings.
+
+ Also, new document.transformer and document.reporter objects are
+ generated.
+
+ 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. Here's one way::
+
+ publish_from_doctree(
+ ..., settings_overrides={'output_encoding': 'unicode'})
+
+ Parameters: `document` is a `docutils.nodes.document` object, an existing
+ document tree.
+
+ Other parameters: see `publish_programmatically`.
+ """
+ reader = docutils.readers.doctree.Reader(parser_name='null')
+ pub = Publisher(reader, None, writer,
+ source=io.DocTreeInput(document),
+ destination_class=io.StringOutput, settings=settings)
+ if not writer and writer_name:
+ pub.set_writer(writer_name)
+ pub.process_programmatic_settings(
+ settings_spec, settings_overrides, config_section)
+ pub.set_destination(None, destination_path)
+ return pub.publish(enable_exit_status=enable_exit_status)
+
+def publish_cmdline_to_binary(reader=None, reader_name='standalone',
+ parser=None, parser_name='restructuredtext',
+ writer=None, writer_name='pseudoxml',
+ settings=None, settings_spec=None,
+ settings_overrides=None, config_section=None,
+ enable_exit_status=True, argv=None,
+ usage=default_usage, description=default_description,
+ destination=None, destination_class=io.BinaryFileOutput
+ ):
+ """
+ Set up & run a `Publisher` for command-line-based file I/O (input and
+ output file paths taken automatically from the command line). Return the
+ encoded string output also.
+
+ This is just like publish_cmdline, except that it uses
+ io.BinaryFileOutput instead of io.FileOutput.
+
+ Parameters: see `publish_programmatically` for the remainder.
+
+ - `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,
+ destination_class=destination_class)
+ pub.set_components(reader_name, parser_name, writer_name)
+ output = pub.publish(
+ argv, usage, description, settings_spec, settings_overrides,
+ config_section=config_section, enable_exit_status=enable_exit_status)
+ return output
+
+def publish_programmatically(source_class, source, source_path,
+ destination_class, destination, destination_path,
+ reader, reader_name,
+ parser, parser_name,
+ writer, writer_name,
+ settings, settings_spec,
+ settings_overrides, config_section,
+ enable_exit_status):
+ """
+ Set up & run a `Publisher` for custom programmatic use. Return the
+ encoded string output and the Publisher object.
+
+ Applications should not need to call this function directly. If it does
+ seem to be necessary to call this function directly, please write to the
+ Docutils-develop mailing list
+ <http://docutils.sf.net/docs/user/mailing-lists.html#docutils-develop>.
+
+ Parameters:
+
+ * `source_class` **required**: The class for dynamically created source
+ objects. Typically `io.FileInput` or `io.StringInput`.
+
+ * `source`: Type depends on `source_class`:
+
+ - If `source_class` is `io.FileInput`: Either a file-like object
+ (must have 'read' and 'close' methods), or ``None``
+ (`source_path` is opened). If neither `source` nor
+ `source_path` are supplied, `sys.stdin` is used.
+
+ - If `source_class` is `io.StringInput` **required**: The input
+ string, either 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`: Type depends on `source_class`:
+
+ - `io.FileInput`: Path to the input file, opened if no `source`
+ supplied.
+
+ - `io.StringInput`: Optional. Path to the file or object that produced
+ `source`. Only used for diagnostic output.
+
+ * `destination_class` **required**: The class for dynamically created
+ destination objects. Typically `io.FileOutput` or `io.StringOutput`.
+
+ * `destination`: Type depends on `destination_class`:
+
+ - `io.FileOutput`: Either a file-like object (must have 'write' and
+ 'close' methods), or ``None`` (`destination_path` is opened). If
+ neither `destination` nor `destination_path` are supplied,
+ `sys.stdout` is used.
+
+ - `io.StringOutput`: Not used; pass ``None``.
+
+ * `destination_path`: Type depends on `destination_class`:
+
+ - `io.FileOutput`: Path to the output file. Opened if no `destination`
+ supplied.
+
+ - `io.StringOutput`: 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`: A runtime settings (`docutils.frontend.Values`) object, for
+ dotted-attribute access to runtime settings. It's the end result of the
+ `SettingsSpec`, config file, and option processing. If `settings` is
+ passed, it's assumed to be complete and no further setting/config/option
+ processing is done.
+
+ * `settings_spec`: A `docutils.SettingsSpec` subclass or object. Provides
+ extra application-specific settings definitions independently of
+ components. In other words, the application becomes a component, and
+ its settings data is processed along with that of the other components.
+ Used only if no `settings` specified.
+
+ * `settings_overrides`: A dictionary containing application-specific
+ settings defaults that override the defaults of other components.
+ Used only if no `settings` specified.
+
+ * `config_section`: A string, the name of the configuration file section
+ for this application. Overrides the ``config_section`` attribute
+ defined by `settings_spec`. Used only if no `settings` specified.
+
+ * `enable_exit_status`: Boolean; enable exit status at end of processing?
+ """
+ pub = Publisher(reader, parser, writer, settings=settings,
+ source_class=source_class,
+ destination_class=destination_class)
+ pub.set_components(reader_name, parser_name, writer_name)
+ pub.process_programmatic_settings(
+ settings_spec, settings_overrides, config_section)
+ pub.set_source(source, source_path)
+ pub.set_destination(destination, destination_path)
+ output = pub.publish(enable_exit_status=enable_exit_status)
+ return output, pub
View
207 lib/python/docutils/error_reporting.py
@@ -0,0 +1,207 @@
+#!/usr/bin/env python
+# -*- coding: utf8 -*-
+
+# :Id: $Id: error_reporting.py 7423 2012-05-03 11:01:54Z milde $
+# :Copyright: © 2011 Günter Milde.
+# :License: Released under the terms of the `2-Clause BSD license`_, in short:
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+# This file is offered as-is, without any warranty.
+#
+# .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause
+
+"""
+Error reporting should be safe from encoding/decoding errors.
+However, implicit conversions of strings and exceptions like
+
+>>> u'%s world: %s' % ('H\xe4llo', Exception(u'H\xe4llo')
+
+fail in some Python versions:
+
+* In Python <= 2.6, ``unicode(<exception instance>)`` uses
+ `__str__` and fails with non-ASCII chars in`unicode` arguments.
+ (work around http://bugs.python.org/issue2517):
+
+* In Python 2, unicode(<exception instance>) fails, with non-ASCII
+ chars in arguments. (Use case: in some locales, the errstr
+ argument of IOError contains non-ASCII chars.)
+
+* In Python 2, str(<exception instance>) fails, with non-ASCII chars
+ in `unicode` arguments.
+
+The `SafeString`, `ErrorString` and `ErrorOutput` classes handle
+common exceptions.
+"""
+
+import sys, codecs
+
+# Guess the locale's encoding.
+# If no valid guess can be made, locale_encoding is set to `None`:
+try:
+ import locale # module missing in Jython
+except ImportError:
+ locale_encoding = None
+else:
+ locale_encoding = locale.getlocale()[1] or locale.getdefaultlocale()[1]
+ # locale.getpreferredencoding([do_setlocale=True|False])
+ # has side-effects | might return a wrong guess.
+ # (cf. Update 1 in http://stackoverflow.com/questions/4082645/using-python-2-xs-locale-module-to-format-numbers-and-currency)
+ try:
+ codecs.lookup(locale_encoding or '') # None -> ''
+ except LookupError:
+ locale_encoding = None
+
+
+
+class SafeString(object):
+ """
+ A wrapper providing robust conversion to `str` and `unicode`.
+ """
+
+ def __init__(self, data, encoding=None, encoding_errors='backslashreplace',
+ decoding_errors='replace'):
+ self.data = data
+ self.encoding = (encoding or getattr(data, 'encoding', None) or
+ locale_encoding or 'ascii')
+ self.encoding_errors = encoding_errors
+ self.decoding_errors = decoding_errors
+
+
+ def __str__(self):
+ try:
+ return str(self.data)
+ except UnicodeEncodeError, err:
+ if isinstance(self.data, Exception):
+ args = [str(SafeString(arg, self.encoding,
+ self.encoding_errors))
+ for arg in self.data.args]
+ return ', '.join(args)
+ if isinstance(self.data, unicode):
+ return self.data.encode(self.encoding, self.encoding_errors)
+ raise
+
+ def __unicode__(self):
+ """
+ Return unicode representation of `self.data`.
+
+ Try ``unicode(self.data)``, catch `UnicodeError` and
+
+ * if `self.data` is an Exception instance, work around
+ http://bugs.python.org/issue2517 with an emulation of
+ Exception.__unicode__,
+
+ * else decode with `self.encoding` and `self.decoding_errors`.
+ """
+ try:
+ u = unicode(self.data)
+ if isinstance(self.data, EnvironmentError):
+ u = u.replace(": u'", ": '") # normalize filename quoting
+ return u
+ except UnicodeError, error: # catch ..Encode.. and ..Decode.. errors
+ if isinstance(self.data, EnvironmentError):
+ return u"[Errno %s] %s: '%s'" % (self.data.errno,
+ SafeString(self.data.strerror, self.encoding,
+ self.decoding_errors),
+ SafeString(self.data.filename, self.encoding,
+ self.decoding_errors))
+ if isinstance(self.data, Exception):
+ args = [unicode(SafeString(arg, self.encoding,
+ decoding_errors=self.decoding_errors))
+ for arg in self.data.args]
+ return u', '.join(args)
+ if isinstance(error, UnicodeDecodeError):
+ return unicode(self.data, self.encoding, self.decoding_errors)
+ raise
+
+class ErrorString(SafeString):
+ """
+ Safely report exception type and message.
+ """
+ def __str__(self):
+ return '%s: %s' % (self.data.__class__.__name__,
+ super(ErrorString, self).__str__())
+
+ def __unicode__(self):
+ return u'%s: %s' % (self.data.__class__.__name__,
+ super(ErrorString, self).__unicode__())
+
+
+class ErrorOutput(object):
+ """
+ Wrapper class for file-like error streams with
+ failsave de- and encoding of `str`, `bytes`, `unicode` and
+ `Exception` instances.
+ """
+
+ def __init__(self, stream=None, encoding=None,
+ encoding_errors='backslashreplace',
+ decoding_errors='replace'):
+ """
+ :Parameters:
+ - `stream`: a file-like object,
+ a string (path to a file),
+ `None` (write to `sys.stderr`, default), or
+ evaluating to `False` (write() requests are ignored).
+ - `encoding`: `stream` text encoding. Guessed if None.
+ - `encoding_errors`: how to treat encoding errors.
+ """
+ if stream is None:
+ stream = sys.stderr
+ elif not(stream):
+ stream = False
+ # if `stream` is a file name, open it
+ elif isinstance(stream, str):
+ stream = open(stream, 'w')
+ elif isinstance(stream, unicode):
+ stream = open(stream.encode(sys.getfilesystemencoding()), 'w')
+
+ self.stream = stream
+ """Where warning output is sent."""
+
+ self.encoding = (encoding or getattr(stream, 'encoding', None) or
+ locale_encoding or 'ascii')
+ """The output character encoding."""
+
+ self.encoding_errors = encoding_errors
+ """Encoding error handler."""
+
+ self.decoding_errors = decoding_errors
+ """Decoding error handler."""
+
+ def write(self, data):
+ """
+ Write `data` to self.stream. Ignore, if self.stream is False.
+
+ `data` can be a `string`, `unicode`, or `Exception` instance.
+ """
+ if self.stream is False:
+ return
+ if isinstance(data, Exception):
+ data = unicode(SafeString(data, self.encoding,
+ self.encoding_errors, self.decoding_errors))
+ try:
+ self.stream.write(data)
+ except UnicodeEncodeError:
+ self.stream.write(data.encode(self.encoding, self.encoding_errors))
+ except TypeError: # in Python 3, stderr expects unicode
+ if self.stream in (sys.stderr, sys.stdout):
+ self.stream.buffer.write(data) # write bytes to raw stream
+ else:
+ self.stream.write(unicode(data, self.encoding,
+ self.decoding_errors))
+
+ def close(self):
+ """
+ Close the error-output stream.
+
+ Ignored if the stream is` sys.stderr` or `sys.stdout` or has no
+ close() method.
+ """
+ if self.stream in (sys.stdout, sys.stderr):
+ return
+ try:
+ self.stream.close()
+ except AttributeError:
+ pass
View
97 lib/python/docutils/examples.py
@@ -0,0 +1,97 @@
+# $Id: examples.py 7320 2012-01-19 22:33:02Z milde $
+# Author: David Goodger <goodger@python.org>
+# Copyright: This module has been placed in the public domain.
+
+"""
+This module contains practical examples of Docutils client code.
+
+Importing this module from client code is not recommended; its contents are
+subject to change in future Docutils releases. Instead, it is recommended
+that you copy and paste the parts you need into your own code, modifying as
+necessary.
+"""
+
+from docutils import core, io
+
+
+def html_parts(input_string, source_path=None, destination_path=None,
+ input_encoding='unicode', doctitle=True,
+ initial_header_level=1):
+ """
+ Given an input string, returns a dictionary of HTML document parts.
+
+ Dictionary keys are the names of parts, and values are Unicode strings;
+ encoding is up to the client.
+
+ Parameters:
+
+ - `input_string`: A multi-line text string; required.
+ - `source_path`: Path to the source file or object. Optional, but useful
+ for diagnostic output (system messages).
+ - `destination_path`: Path to the file or object which will receive the
+ output; optional. Used for determining relative paths (stylesheets,
+ source links, etc.).
+ - `input_encoding`: The encoding of `input_string`. If it is an encoded
+ 8-bit string, provide the correct encoding. If it is a Unicode string,
+ use "unicode", the default.
+ - `doctitle`: Disable the promotion of a lone top-level section title to
+ document title (and subsequent section title to document subtitle
+ promotion); enabled by default.
+ - `initial_header_level`: The initial level for header elements (e.g. 1
+ for "<h1>").
+ """
+ overrides = {'input_encoding': input_encoding,
+ 'doctitle_xform': doctitle,
+ 'initial_header_level': initial_header_level}
+ parts = core.publish_parts(
+ source=input_string, source_path=source_path,
+ destination_path=destination_path,
+ writer_name='html', settings_overrides=overrides)
+ return parts
+
+def html_body(input_string, source_path=None, destination_path=None,
+ input_encoding='unicode', output_encoding='unicode',
+ doctitle=True, initial_header_level=1):
+ """
+ Given an input string, returns an HTML fragment as a string.
+
+ The return value is the contents of the <body> element.
+
+ Parameters (see `html_parts()` for the remainder):
+
+ - `output_encoding`: The desired encoding of the output. If a Unicode
+ string is desired, use the default value of "unicode" .
+ """
+ parts = html_parts(
+ input_string=input_string, source_path=source_path,
+ destination_path=destination_path,
+ input_encoding=input_encoding, doctitle=doctitle,
+ initial_header_level=initial_header_level)
+ fragment = parts['html_body']
+ if output_encoding != 'unicode':
+ fragment = fragment.encode(output_encoding)
+ return fragment
+
+def internals(input_string, source_path=None, destination_path=None,
+ input_encoding='unicode', settings_overrides=None):
+ """
+ Return the document tree and publisher, for exploring Docutils internals.
+
+ Parameters: see `html_parts()`.
+ """
+ if settings_overrides:
+ overrides = settings_overrides.copy()
+ else:
+ overrides = {}
+ overrides['input_encoding'] = input_encoding
+ output, pub = core.publish_programmatically(
+ source_class=io.StringInput, source=input_string,
+ source_path=source_path,
+ destination_class=io.NullOutput, destination=None,
+ destination_path=destination_path,
+ reader=None, reader_name='standalone',
+ parser=None, parser_name='restructuredtext',
+ writer=None, writer_name='null',
+ settings=None, settings_spec=None, settings_overrides=overrides,
+ config_section=None, enable_exit_status=None)
+ return pub.writer.document, pub
View
788 lib/python/docutils/frontend.py
@@ -0,0 +1,788 @@
+# $Id: frontend.py 7339 2012-02-03 12:23:27Z milde $
+# Author: David Goodger <goodger@python.org>
+# 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.
+* `Option`: Customized version of `optparse.Option`; validation support.
+* `Values`: Runtime settings; objects are simple structs
+ (``object.attribute``). Supports cumulative list settings (attributes).
+* `ConfigParser`: Standard Docutils config file processing.
+
+Also exports the following functions:
+
+* Option callbacks: `store_multiple`, `read_config_file`.
+* Setting validators: `validate_encoding`,
+ `validate_encoding_error_handler`,
+ `validate_encoding_and_error_handler`, `validate_boolean`,
+ `validate_threshold`, `validate_colon_separated_string_list`,
+ `validate_dependency_file`.
+* `make_paths_absolute`.
+* SettingSpec manipulation: `filter_settings_spec`.
+"""
+
+__docformat__ = 'reStructuredText'
+
+import os
+import os.path
+import sys
+import warnings
+import ConfigParser as CP
+import codecs
+import optparse
+from optparse import SUPPRESS_HELP
+import docutils
+import docutils.utils
+import docutils.nodes
+from docutils.error_reporting import locale_encoding, ErrorOutput, ErrorString
+
+
+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.)
+ """
+ try:
+ new_settings = parser.get_config_file_settings(value)
+ except ValueError, error:
+ parser.error(error)
+ parser.values.update(new_settings, parser)
+
+def validate_encoding(setting, value, option_parser,
+ config_parser=None, config_section=None):
+ try:
+ codecs.lookup(value)
+ except LookupError:
+ raise (LookupError('setting "%s": unknown encoding: "%s"'
+ % (setting, value)),
+ None, sys.exc_info()[2])
+ return value
+
+def validate_encoding_error_handler(setting, value, option_parser,
+ config_parser=None, config_section=None):
+ try:
+ codecs.lookup_error(value)
+ except LookupError:
+ raise (LookupError(
+ 'unknown encoding error handler: "%s" (choices: '
+ '"strict", "ignore", "replace", "backslashreplace", '
+ '"xmlcharrefreplace", and possibly others; see documentation for '
+ 'the Python ``codecs`` module)' % value),
+ None, sys.exc_info()[2])
+ return value
+
+def validate_encoding_and_error_handler(
+ setting, value, option_parser, config_parser=None, config_section=None):
+ """
+ Side-effect: if an error handler is included in the value, it is inserted
+ into the appropriate place as if it was a separate setting/option.
+ """
+ if ':' in value:
+ encoding, handler = value.split(':')
+ validate_encoding_error_handler(
+ setting + '_error_handler', handler, option_parser,
+ config_parser, config_section)
+ if config_parser:
+ config_parser.set(config_section, setting + '_error_handler',
+ handler)
+ else:
+ setattr(option_parser.values, setting + '_error_handler', handler)
+ else:
+ encoding = value
+ validate_encoding(setting, encoding, option_parser,
+ config_parser, config_section)
+ return encoding
+
+def validate_boolean(setting, value, option_parser,
+ config_parser=None, config_section=None):
+ if isinstance(value, unicode):
+ try:
+ return option_parser.booleans[value.strip().lower()]
+ except KeyError:
+ raise (LookupError('unknown boolean value: "%s"' % value),
+ None, sys.exc_info()[2])
+ return value
+
+def validate_nonnegative_int(setting, value, option_parser,
+ config_parser=None, config_section=None):
+ value = int(value)
+ if value < 0:
+ raise ValueError('negative value; must be positive or zero')
+ return value
+
+def validate_threshold(setting, value, option_parser,
+ config_parser=None, config_section=None):
+ try:
+ return int(value)
+ except ValueError:
+ try:
+ return option_parser.thresholds[value.lower()]
+ except (KeyError, AttributeError):
+ raise (LookupError('unknown threshold: %r.' % value),
+ None, sys.exc_info[2])
+
+def validate_colon_separated_string_list(
+ setting, value, option_parser, config_parser=None, config_section=None):
+ if isinstance(value, unicode):
+ value = value.split(':')
+ else:
+ last = value.pop()
+ value.extend(last.split(':'))
+ return value
+
+def validate_url_trailing_slash(
+ setting, value, option_parser, config_parser=None, config_section=None):
+ if not value:
+ return './'
+ elif value.endswith('/'):
+ return value
+ else:
+ return value + '/'
+
+def validate_dependency_file(setting, value, option_parser,
+ config_parser=None, config_section=None):
+ try:
+ return docutils.utils.DependencyList(value)
+ except IOError:
+ return docutils.utils.DependencyList(None)
+
+def validate_strip_class(setting, value, option_parser,
+ config_parser=None, config_section=None):
+ # convert to list:
+ if isinstance(value, unicode):
+ value = [value]
+ class_values = filter(None, [v.strip() for v in value.pop().split(',')])
+ # validate:
+ for class_value in class_values:
+ normalized = docutils.nodes.make_id(class_value)
+ if class_value != normalized:
+ raise ValueError('invalid class value %r (perhaps %r?)'
+ % (class_value, normalized))
+ value.extend(class_values)
+ return value
+
+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.getcwdu() # type(base_path) == unicode
+ # to allow combining non-ASCII cwd with unicode values in `pathdict`
+ for key in keys:
+ if key in pathdict:
+ value = pathdict[key]
+ if isinstance(value, list):
+ value = [make_one_path_absolute(base_path, path)
+ for path in value]
+ elif value:
+ value = make_one_path_absolute(base_path, value)
+ pathdict[key] = value
+
+def make_one_path_absolute(base_path, path):
+ return os.path.abspath(os.path.join(base_path, path))
+
+def filter_settings_spec(settings_spec, *exclude, **replace):
+ """Return a copy of `settings_spec` excluding/replacing some settings.
+
+ `settings_spec` is a tuple of configuration settings with a structure
+ described for docutils.SettingsSpec.settings_spec.
+
+ Optional positional arguments are names of to-be-excluded settings.
+ Keyword arguments are option specification replacements.
+ (See the html4strict writer for an example.)
+ """
+ settings = list(settings_spec)
+ # every third item is a sequence of option tuples
+ for i in range(2, len(settings), 3):
+ newopts = []
+ for opt_spec in settings[i]:
+ # opt_spec is ("<help>", [<option strings>], {<keyword args>})
+ opt_name = [opt_string[2:].replace('-', '_')
+ for opt_string in opt_spec[1]
+ if opt_string.startswith('--')
+ ][0]
+ if opt_name in exclude:
+ continue
+ if opt_name in replace.keys():
+ newopts.append(replace[opt_name])
+ else:
+ newopts.append(opt_spec)
+ settings[i] = tuple(newopts)
+ return tuple(settings)
+
+
+class Values(optparse.Values):
+
+ """
+ Updates list attributes by extension rather than by replacement.
+ Works in conjunction with the `OptionParser.lists` instance attribute.
+ """
+
+ def __init__(self, *args, **kwargs):
+ optparse.Values.__init__(self, *args, **kwargs)
+ if (not hasattr(self, 'record_dependencies')
+ or self.record_dependencies is None):
+ # Set up dependency list, in case it is needed.
+ self.record_dependencies = docutils.utils.DependencyList()
+
+ def update(self, other_dict, option_parser):
+ if isinstance(other_dict, Values):
+ other_dict = other_dict.__dict__
+ other_dict = other_dict.copy()
+ for setting in option_parser.lists.keys():
+ if (hasattr(self, setting) and setting in other_dict):
+ value = getattr(self, setting)
+ if value:
+ value += other_dict[setting]
+ del other_dict[setting]
+ self._update_loose(other_dict)
+
+ def copy(self):
+ """Return a shallow copy of `self`."""
+ return self.__class__(defaults=self.__dict__)
+
+
+class Option(optparse.Option):
+
+ ATTRS = optparse.Option.ATTRS + ['validator', 'overrides']
+
+ def process(self, opt, value, values, parser):
+ """
+ Call the validator function on applicable settings and
+ evaluate the 'overrides' option.
+ Extends `optparse.Option.process`.
+ """
+ result = optparse.Option.process(self, opt, value, values, parser)
+ setting = self.dest
+ if setting:
+ if self.validator:
+ value = getattr(values, setting)
+ try:
+ new_value = self.validator(setting, value, parser)
+ except Exception, error:
+ raise (optparse.OptionValueError(
+ 'Error in option "%s":\n %s'
+ % (opt, ErrorString(error))),
+ None, sys.exc_info()[2])
+ setattr(values, setting, new_value)
+ if self.overrides:
+ setattr(values, self.overrides, None)
+ return result
+
+
+class OptionParser(optparse.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.
+ """
+
+ standard_config_files = [
+ '/etc/docutils.conf', # system-wide
+ './docutils.conf', # project-specific
+ '~/.docutils'] # user-specific
+ """Docutils configuration files, using ConfigParser syntax. Filenames
+ will be tilde-expanded later. Later files override earlier ones."""
+
+ 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."""
+
+ booleans={'1': 1, 'on': 1, 'yes': 1, 'true': 1,
+ '0': 0, 'off': 0, 'no': 0, 'false': 0, '': 0}
+ """Lookup table for boolean configuration file settings."""
+
+ default_error_encoding = getattr(sys.stderr, 'encoding',
+ None) or locale_encoding or 'ascii'
+
+ default_error_encoding_error_handler = 'backslashreplace'
+
+ settings_spec = (
+ 'General Docutils Options',
+ None,
+ (('Specify the document title as metadata.',
+ ['--title'], {}),
+ ('Include a "Generated by Docutils" credit and link.',
+ ['--generator', '-g'], {'action': 'store_true',
+ 'validator': validate_boolean}),
+ ('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 (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.',
+ ['--source-link', '-s'], {'action': 'store_true',
+ 'validator': validate_boolean}),
+ ('Use <URL> for a 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')}),
+ ('Link from section headers to TOC entries. (default)',
+ ['--toc-entry-backlinks'],
+ {'dest': 'toc_backlinks', 'action': 'store_const', 'const': 'entry',
+ 'default': 'entry'}),
+ ('Link from section headers to the top of the TOC.',
+ ['--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'}),
+ ('Link from footnotes/citations to references. (default)',
+ ['--footnote-backlinks'],
+ {'action': 'store_true', 'default': 1,
+ 'validator': validate_boolean}),
+ ('Disable backlinks from footnotes and citations.',
+ ['--no-footnote-backlinks'],
+ {'dest': 'footnote_backlinks', 'action': 'store_false'}),
+ ('Enable section numbering by Docutils. (default)',
+ ['--section-numbering'],
+ {'action': 'store_true', 'dest': 'sectnum_xform',
+ 'default': 1, 'validator': validate_boolean}),
+ ('Disable section numbering by Docutils.',
+ ['--no-section-numbering'],
+ {'action': 'store_false', 'dest': 'sectnum_xform'}),
+ ('Remove comment elements from the document tree.',
+ ['--strip-comments'],
+ {'action': 'store_true', 'validator': validate_boolean}),
+ ('Leave comment elements in the document tree. (default)',
+ ['--leave-comments'],
+ {'action': 'store_false', 'dest': 'strip_comments'}),
+ ('Remove all elements with classes="<class>" from the document tree. '
+ 'Warning: potentially dangerous; use with caution. '
+ '(Multiple-use option.)',
+ ['--strip-elements-with-class'],
+ {'action': 'append', 'dest': 'strip_elements_with_classes',
+ 'metavar': '<class>', 'validator': validate_strip_class}),
+ ('Remove all classes="<class>" attributes from elements in the '
+ 'document tree. Warning: potentially dangerous; use with caution. '
+ '(Multiple-use option.)',
+ ['--strip-class'],
+ {'action': 'append', 'dest': 'strip_classes',
+ 'metavar': '<class>', 'validator': validate_strip_class}),
+ ('Report system messages at or higher than <level>: "info" or "1", '
+ '"warning"/"2" (default), "error"/"3", "severe"/"4", "none"/"5"',
+ ['--report', '-r'], {'choices': threshold_choices, 'default': 2,
+ 'dest': 'report_level', 'metavar': '<level>',
+ 'validator': validate_threshold}),
+ ('Report all system messages. (Same as "--report=1".)',
+ ['--verbose', '-v'], {'action': 'store_const', 'const': 1,
+ 'dest': 'report_level'}),
+ ('Report no system messages. (Same as "--report=5".)',
+ ['--quiet', '-q'], {'action': 'store_const', 'const': 5,
+ 'dest': 'report_level'}),
+ ('Halt execution at system messages at or above <level>. '
+ 'Levels as in --report. Default: 4 (severe).',
+ ['--halt'], {'choices': threshold_choices, 'dest': 'halt_level',
+ 'default': 4, 'metavar': '<level>',
+ 'validator': validate_threshold}),
+ ('Halt at the slightest problem. Same as "--halt=info".',
+ ['--strict'], {'action': 'store_const', 'const': 1,
+ 'dest': 'halt_level'}),
+ ('Enable a non-zero exit status for non-halting system messages at '
+ 'or above <level>. Default: 5 (disabled).',
+ ['--exit-status'], {'choices': threshold_choices,
+ 'dest': 'exit_status_level',
+ 'default': 5, 'metavar': '<level>',
+ 'validator': validate_threshold}),
+ ('Enable debug-level system messages and diagnostics.',
+ ['--debug'], {'action': 'store_true', 'validator': validate_boolean}),
+ ('Disable debug output. (default)',
+ ['--no-debug'], {'action': 'store_false', 'dest': 'debug'}),
+ ('Send the output of system messages to <file>.',
+ ['--warnings'], {'dest': 'warning_stream', 'metavar': '<file>'}),
+ ('Enable Python tracebacks when Docutils is halted.',
+ ['--traceback'], {'action': 'store_true', 'default': None,
+ 'validator': validate_boolean}),
+ ('Disable Python tracebacks. (default)',
+ ['--no-traceback'], {'dest': 'traceback', 'action': 'store_false'}),
+ ('Specify the encoding and optionally the '
+ 'error handler of input text. Default: <locale-dependent>:strict.',
+ ['--input-encoding', '-i'],
+ {'metavar': '<name[:handler]>',
+ 'validator': validate_encoding_and_error_handler}),
+ ('Specify the error handler for undecodable characters. '
+ 'Choices: "strict" (default), "ignore", and "replace".',
+ ['--input-encoding-error-handler'],
+ {'default': 'strict', 'validator': validate_encoding_error_handler}),
+ ('Specify the text encoding and optionally the error handler for '
+ 'output. Default: UTF-8:strict.',
+ ['--output-encoding', '-o'],
+ {'metavar': '<name[:handler]>', 'default': 'utf-8',
+ 'validator': validate_encoding_and_error_handler}),
+ ('Specify error handler for unencodable output characters; '
+ '"strict" (default), "ignore", "replace", '
+ '"xmlcharrefreplace", "backslashreplace".',
+ ['--output-encoding-error-handler'],
+ {'default': 'strict', 'validator': validate_encoding_error_handler}),
+ ('Specify text encoding and error handler for error output. '
+ 'Default: %s:%s.'
+ % (default_error_encoding, default_error_encoding_error_handler),
+ ['--error-encoding', '-e'],
+ {'metavar': '<name[:handler]>', 'default': default_error_encoding,
+ 'validator': validate_encoding_and_error_handler}),
+ ('Specify the error handler for unencodable characters in '
+ 'error output. Default: %s.'
+ % default_error_encoding_error_handler,
+ ['--error-encoding-error-handler'],
+ {'default': default_error_encoding_error_handler,
+ 'validator': validate_encoding_error_handler}),
+ ('Specify the language (as BCP 47 language tag). Default: en.',
+ ['--language', '-l'], {'dest': 'language_code', 'default': 'en',
+ 'metavar': '<name>'}),
+ ('Write output file dependencies to <file>.',
+ ['--record-dependencies'],
+ {'metavar': '<file>', 'validator': validate_dependency_file,
+ 'default': None}), # default set in Values class
+ ('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'}),
+ # Typically not useful for non-programmatical use:
+ (SUPPRESS_HELP, ['--id-prefix'], {'default': ''}),
+ (SUPPRESS_HELP, ['--auto-id-prefix'], {'default': 'id'}),
+ # Hidden options, for development use only:
+ (SUPPRESS_HELP, ['--dump-settings'], {'action': 'store_true'}),
+ (SUPPRESS_HELP, ['--dump-internals'], {'action': 'store_true'}),
+ (SUPPRESS_HELP, ['--dump-transforms'], {'action': 'store_true'}),
+ (SUPPRESS_HELP, ['--dump-pseudo-xml'], {'action': 'store_true'}),
+ (SUPPRESS_HELP, ['--expose-internal-attribute'],
+ {'action': 'append', 'dest': 'expose_internals',
+ 'validator': validate_colon_separated_string_list}),
+ (SUPPRESS_HELP, ['--strict-visitor'], {'action': 'store_true'}),
+ ))
+ """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()`)."""
+
+ settings_defaults = {'_disable_config': None,
+ '_source': None,
+ '_destination': None,
+ '_config_files': None}
+ """Defaults for settings that don't have command-line option equivalents."""
+
+ relative_path_settings = ('warning_stream',)
+
+ config_section = 'general'
+
+ version_template = ('%%prog (Docutils %s [%s], Python %s, on %s)'
+ % (docutils.__version__, docutils.__version_details__,
+ sys.version.split()[0], sys.platform))
+ """Default version message."""
+
+ def __init__(self, components=(), defaults=None, read_config_files=None,
+ *args, **kwargs):
+ """
+ `components` is a list of Docutils components each containing a
+ ``.settings_spec`` attribute. `defaults` is a mapping of setting
+ default overrides.
+ """
+
+ self.lists = {}
+ """Set of list-type settings."""
+
+ self.config_files = []
+ """List of paths of applied configuration files."""
+
+ optparse.OptionParser.__init__(
+ self, option_class=Option, add_help_option=None,
+ formatter=optparse.TitledHelpFormatter(width=78),
+ *args, **kwargs)
+ if not self.version:
+ self.version = self.version_template
+ # Make an instance copy (it will be modified):
+ self.relative_path_settings = list(self.relative_path_settings)
+ self.components = (self,) + tuple(components)
+ self.populate_from_components(self.components)
+ self.set_defaults_from_dict(defaults or {})
+ if read_config_files and not self.defaults['_disable_config']:
+ try:
+ config_settings = self.get_standard_config_settings()
+ except ValueError, error:
+ self.error(error)
+ self.set_defaults_from_dict(config_settings.__dict__)
+
+ def populate_from_components(self, components):
+ """
+ For each component, first populate from the `SettingsSpec.settings_spec`
+ structure, then from the `SettingsSpec.settings_defaults` dictionary.
+ After all components have been processed, check for and populate from
+ each component's `SettingsSpec.settings_default_overrides` dictionary.
+ """
+ for component in components:
+ if component is None:
+ continue
+ settings_spec = component.settings_spec
+ self.relative_path_settings.extend(
+ component.relative_path_settings)
+ for i in range(0, len(settings_spec), 3):
+ title, description, option_spec = settings_spec[i:i+3]
+ if title:
+ group = optparse.OptionGroup(self, title, description)
+ self.add_option_group(group)
+ else:
+ group = self # single options
+ for (help_text, option_strings, kwargs) in option_spec:
+ option = group.add_option(help=help_text, *option_strings,
+ **kwargs)
+ if kwargs.get('action') == 'append':
+ self.lists[option.dest] = 1
+ if component.settings_defaults:
+ self.defaults.update(component.settings_defaults)
+ for component in components:
+ if component and component.settings_default_overrides:
+ self.defaults.update(component.settings_default_overrides)
+
+ def get_standard_config_files(self):
+ """Return list of config files, from environment or standard."""
+ try:
+ config_files = os.environ['DOCUTILSCONFIG'].split(os.pathsep)
+ except KeyError:
+ config_files = self.standard_config_files
+
+ # If 'HOME' is not set, expandvars() requires the 'pwd' module which is
+ # not available under certain environments, for example, within
+ # mod_python. The publisher ends up in here, and we need to publish
+ # from within mod_python. Therefore we need to avoid expanding when we
+ # are in those environments.
+ expand = os.path.expanduser
+ if 'HOME' not in os.environ:
+ try:
+ import pwd
+ except ImportError:
+ expand = lambda x: x
+ return [expand(f) for f in config_files if f.strip()]
+
+ def get_standard_config_settings(self):
+ settings = Values()
+ for filename in self.get_standard_config_files():
+ settings.update(self.get_config_file_settings(filename), self)
+ return settings
+
+ def get_config_file_settings(self, config_file):
+ """Returns a dictionary containing appropriate config file settings."""
+ parser = ConfigParser()
+ parser.read(config_file, self)
+ self.config_files.extend(parser._files)
+ base_path = os.path.dirname(config_file)
+ applied = {}
+ settings = Values()
+ for component in self.components:
+ if not component:
+ continue
+ for section in (tuple(component.config_section_dependencies or ())
+ + (component.config_section,)):
+ if section in applied:
+ continue
+ applied[section] = 1
+ settings.update(parser.get_section(section), self)
+ make_paths_absolute(
+ settings.__dict__, self.relative_path_settings, base_path)
+ return settings.__dict__
+
+ def check_values(self, values, args):
+ """Store positional arguments as runtime settings."""
+ values._source, values._destination = self.check_args(args)
+ make_paths_absolute(values.__dict__, self.relative_path_settings)
+ values._config_files = self.config_files
+ return values
+
+ def check_args(self, args):
+ source = destination = None
+ if args:
+ source = args.pop(0)
+ if source == '-': # means stdin
+ source = None
+ if args:
+ destination = args.pop(0)
+ if destination == '-': # means stdout
+ destination = None
+ 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
+
+ def set_defaults_from_dict(self, defaults):
+ self.defaults.update(defaults)
+
+ def get_default_values(self):
+ """Needed to get custom `Values` instances."""
+ defaults = Values(self.defaults)
+ defaults._config_files = self.config_files
+ return defaults
+
+ def get_option_by_dest(self, dest):
+ """
+ Get an option by its dest.
+
+ If you're supplying a dest which is shared by several options,
+ it is undefined which option of those is returned.
+
+ A KeyError is raised if there is no option with the supplied
+ dest.
+ """
+ for group in self.option_groups + [self]:
+ for option in group.option_list:
+ if option.dest == dest:
+ return option
+ raise KeyError('No option with dest == %r.' % dest)
+
+
+class ConfigParser(CP.RawConfigParser):
+
+ old_settings = {
+ 'pep_stylesheet': ('pep_html writer', 'stylesheet'),
+ 'pep_stylesheet_path': ('pep_html writer', 'stylesheet_path'),
+ 'pep_template': ('pep_html writer', 'template')}
+ """{old setting: (new section, new setting)} mapping, used by
+ `handle_old_config`, to convert settings from the old [options] section."""
+
+ old_warning = """
+The "[option]" section is deprecated. Support for old-format configuration
+files may be removed in a future Docutils release. Please revise your
+configuration files. See <http://docutils.sf.net/docs/user/config.html>,
+section "Old-Format Configuration Files".
+"""
+
+ not_utf8_error = """\
+Unable to read configuration file "%s": content not encoded as UTF-8.
+Skipping "%s" configuration file.
+"""
+
+ def __init__(self, *args, **kwargs):
+ CP.RawConfigParser.__init__(self, *args, **kwargs)
+
+ self._files = []
+ """List of paths of configuration files read."""
+
+ self._stderr = ErrorOutput()
+ """Wrapper around sys.stderr catching en-/decoding errors"""
+
+ def read(self, filenames, option_parser):
+ if type(filenames) in (str, unicode):
+ filenames = [filenames]
+ for filename in filenames:
+ try:
+ # Config files must be UTF-8-encoded:
+ fp = codecs.open(filename, 'r', 'utf-8')
+ except IOError:
+ continue
+ try:
+ if sys.version_info < (3,2):
+ CP.RawConfigParser.readfp(self, fp, filename)
+ else:
+ CP.RawConfigParser.read_file(self, fp, filename)
+ except UnicodeDecodeError:
+ self._stderr.write(self.not_utf8_error % (filename, filename))
+ fp.close()
+ continue
+ fp.close()
+ self._files.append(filename)
+ if self.has_section('options'):
+ self.handle_old_config(filename)
+ self.validate_settings(filename, option_parser)
+
+ def handle_old_config(self, filename):
+ warnings.warn_explicit(self.old_warning, ConfigDeprecationWarning,
+ filename, 0)
+ options = self.get_section('options')
+ if not self.has_section('general'):
+ self.add_section('general')
+ for key, value in options.items():
+ if key in self.old_settings:
+ section, setting = self.old_settings[key]
+ if not self.has_section(section):
+ self.add_section(section)
+ else:
+ section = 'general'
+ setting = key
+ if not self.has_option(section, setting):
+ self.set(section, setting, value)
+ self.remove_section('options')
+
+ def validate_settings(self, filename, option_parser):
+ """
+ Call the validator function and implement overrides on all applicable
+ settings.
+ """
+ for section in self.sections():
+ for setting in self.options(section):
+ try:
+ option = option_parser.get_option_by_dest(setting)
+ except KeyError:
+ continue
+ if option.validator:
+ value = self.get(section, setting)
+ try:
+ new_value = option.validator(
+ setting, value, option_parser,
+ config_parser=self, config_section=section)
+ except Exception, error:
+ raise (ValueError(
+ 'Error in config file "%s", section "[%s]":\n'
+ ' %s\n'
+ ' %s = %s'
+ % (filename, section, ErrorString(error),
+ setting, value)), None, sys.exc_info()[2])
+ self.set(section, setting, new_value)
+ if option.overrides:
+ self.set(section, option.overrides, None)
+
+ 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):
+ """
+ Return a given section as a dictionary (empty if the section
+ doesn't exist).
+ """
+ section_dict = {}
+ if self.has_section(section):
+ for option in self.options(section):
+ section_dict[option] = self.get(section, option)
+ return section_dict
+
+
+class ConfigDeprecationWarning(DeprecationWarning):
+ """Warning for deprecated configuration file features."""
View
497 lib/python/docutils/io.py
@@ -0,0 +1,497 @@
+# $Id: io.py 7440 2012-06-13 14:14:12Z milde $
+# Author: David Goodger <goodger@python.org>
+# 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 os
+import re
+import codecs
+from docutils import TransformSpec
+from docutils._compat import b
+from docutils.error_reporting import locale_encoding, ErrorString, ErrorOutput
+
+
+class InputError(IOError): pass
+class OutputError(IOError): pass
+
+def check_encoding(stream, encoding):
+ """Test, whether the encoding of `stream` matches `encoding`.
+
+ Returns
+
+ :None: if `encoding` or `stream.encoding` are not a valid encoding
+ argument (e.g. ``None``) or `stream.encoding is missing.
+ :True: if the encoding argument resolves to the same value as `encoding`,
+ :False: if the encodings differ.
+ """
+ try:
+ return codecs.lookup(stream.encoding) == codecs.lookup(encoding)
+ except (LookupError, AttributeError, TypeError):
+ return None
+
+
+class Input(TransformSpec):
+
+ """
+ Abstract base class for input wrappers.
+ """
+
+ component_type = 'input'
+
+ default_source_path = None
+
+ def __init__(self, source=None, source_path=None, encoding=None,
+ error_handler='strict'):
+ self.encoding = encoding
+ """Text encoding for the input source."""
+
+ self.error_handler = error_handler
+ """Text decoding error handler."""
+
+ 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
+
+ self.successful_encoding = None
+ """