| [3] | 1 | # Authors: David Goodger | 
|---|
|  | 2 | # Contact: goodger@python.org | 
|---|
|  | 3 | # Revision: $Revision: 4208 $ | 
|---|
|  | 4 | # Date: $Date: 2005-12-14 03:12:00 +0100 (Wed, 14 Dec 2005) $ | 
|---|
|  | 5 | # Copyright: This module has been placed in the public domain. | 
|---|
|  | 6 |  | 
|---|
|  | 7 | """ | 
|---|
|  | 8 | Calling the ``publish_*`` convenience functions (or instantiating a | 
|---|
|  | 9 | `Publisher` object) with component names will result in default | 
|---|
|  | 10 | behavior.  For custom behavior (setting component options), create | 
|---|
|  | 11 | custom component objects first, and pass *them* to | 
|---|
|  | 12 | ``publish_*``/`Publisher`.  See `The Docutils Publisher`_. | 
|---|
|  | 13 |  | 
|---|
|  | 14 | .. _The Docutils Publisher: http://docutils.sf.net/docs/api/publisher.html | 
|---|
|  | 15 | """ | 
|---|
|  | 16 |  | 
|---|
|  | 17 | __docformat__ = 'reStructuredText' | 
|---|
|  | 18 |  | 
|---|
|  | 19 | import sys | 
|---|
|  | 20 | import pprint | 
|---|
|  | 21 | from types import StringType | 
|---|
|  | 22 | from docutils import __version__, __version_details__, SettingsSpec | 
|---|
|  | 23 | from docutils import frontend, io, utils, readers, writers | 
|---|
|  | 24 | from docutils.frontend import OptionParser | 
|---|
|  | 25 | from docutils.transforms import Transformer | 
|---|
|  | 26 | import docutils.readers.doctree | 
|---|
|  | 27 |  | 
|---|
|  | 28 |  | 
|---|
|  | 29 | class Publisher: | 
|---|
|  | 30 |  | 
|---|
|  | 31 | """ | 
|---|
|  | 32 | A facade encapsulating the high-level logic of a Docutils system. | 
|---|
|  | 33 | """ | 
|---|
|  | 34 |  | 
|---|
|  | 35 | def __init__(self, reader=None, parser=None, writer=None, | 
|---|
|  | 36 | source=None, source_class=io.FileInput, | 
|---|
|  | 37 | destination=None, destination_class=io.FileOutput, | 
|---|
|  | 38 | settings=None): | 
|---|
|  | 39 | """ | 
|---|
|  | 40 | Initial setup.  If any of `reader`, `parser`, or `writer` are not | 
|---|
|  | 41 | specified, the corresponding ``set_...`` method should be called with | 
|---|
|  | 42 | a component name (`set_reader` sets the parser as well). | 
|---|
|  | 43 | """ | 
|---|
|  | 44 |  | 
|---|
|  | 45 | self.document = None | 
|---|
|  | 46 | """The document tree (`docutils.nodes` objects).""" | 
|---|
|  | 47 |  | 
|---|
|  | 48 | self.reader = reader | 
|---|
|  | 49 | """A `docutils.readers.Reader` instance.""" | 
|---|
|  | 50 |  | 
|---|
|  | 51 | self.parser = parser | 
|---|
|  | 52 | """A `docutils.parsers.Parser` instance.""" | 
|---|
|  | 53 |  | 
|---|
|  | 54 | self.writer = writer | 
|---|
|  | 55 | """A `docutils.writers.Writer` instance.""" | 
|---|
|  | 56 |  | 
|---|
|  | 57 | for component in 'reader', 'parser', 'writer': | 
|---|
|  | 58 | assert not isinstance(getattr(self, component), StringType), \ | 
|---|
|  | 59 | ('passed string as "%s" parameter; use "%s_name" instead' | 
|---|
|  | 60 | % (getattr(self, component), component, component)) | 
|---|
|  | 61 |  | 
|---|
|  | 62 | self.source = source | 
|---|
|  | 63 | """The source of input data, a `docutils.io.Input` instance.""" | 
|---|
|  | 64 |  | 
|---|
|  | 65 | self.source_class = source_class | 
|---|
|  | 66 | """The class for dynamically created source objects.""" | 
|---|
|  | 67 |  | 
|---|
|  | 68 | self.destination = destination | 
|---|
|  | 69 | """The destination for docutils output, a `docutils.io.Output` | 
|---|
|  | 70 | instance.""" | 
|---|
|  | 71 |  | 
|---|
|  | 72 | self.destination_class = destination_class | 
|---|
|  | 73 | """The class for dynamically created destination objects.""" | 
|---|
|  | 74 |  | 
|---|
|  | 75 | self.settings = settings | 
|---|
|  | 76 | """An object containing Docutils settings as instance attributes. | 
|---|
|  | 77 | Set by `self.process_command_line()` or `self.get_settings()`.""" | 
|---|
|  | 78 |  | 
|---|
|  | 79 | def set_reader(self, reader_name, parser, parser_name): | 
|---|
|  | 80 | """Set `self.reader` by name.""" | 
|---|
|  | 81 | reader_class = readers.get_reader_class(reader_name) | 
|---|
|  | 82 | self.reader = reader_class(parser, parser_name) | 
|---|
|  | 83 | self.parser = self.reader.parser | 
|---|
|  | 84 |  | 
|---|
|  | 85 | def set_writer(self, writer_name): | 
|---|
|  | 86 | """Set `self.writer` by name.""" | 
|---|
|  | 87 | writer_class = writers.get_writer_class(writer_name) | 
|---|
|  | 88 | self.writer = writer_class() | 
|---|
|  | 89 |  | 
|---|
|  | 90 | def set_components(self, reader_name, parser_name, writer_name): | 
|---|
|  | 91 | if self.reader is None: | 
|---|
|  | 92 | self.set_reader(reader_name, self.parser, parser_name) | 
|---|
|  | 93 | if self.parser is None: | 
|---|
|  | 94 | if self.reader.parser is None: | 
|---|
|  | 95 | self.reader.set_parser(parser_name) | 
|---|
|  | 96 | self.parser = self.reader.parser | 
|---|
|  | 97 | if self.writer is None: | 
|---|
|  | 98 | self.set_writer(writer_name) | 
|---|
|  | 99 |  | 
|---|
|  | 100 | def setup_option_parser(self, usage=None, description=None, | 
|---|
|  | 101 | settings_spec=None, config_section=None, | 
|---|
|  | 102 | **defaults): | 
|---|
|  | 103 | if config_section: | 
|---|
|  | 104 | if not settings_spec: | 
|---|
|  | 105 | settings_spec = SettingsSpec() | 
|---|
|  | 106 | settings_spec.config_section = config_section | 
|---|
|  | 107 | parts = config_section.split() | 
|---|
|  | 108 | if len(parts) > 1 and parts[-1] == 'application': | 
|---|
|  | 109 | settings_spec.config_section_dependencies = ['applications'] | 
|---|
|  | 110 | #@@@ Add self.source & self.destination to components in future? | 
|---|
|  | 111 | option_parser = OptionParser( | 
|---|
|  | 112 | components=(self.parser, self.reader, self.writer, settings_spec), | 
|---|
|  | 113 | defaults=defaults, read_config_files=1, | 
|---|
|  | 114 | usage=usage, description=description) | 
|---|
|  | 115 | return option_parser | 
|---|
|  | 116 |  | 
|---|
|  | 117 | def get_settings(self, usage=None, description=None, | 
|---|
|  | 118 | settings_spec=None, config_section=None, **defaults): | 
|---|
|  | 119 | """ | 
|---|
|  | 120 | Set and return default settings (overrides in `defaults` dict). | 
|---|
|  | 121 |  | 
|---|
|  | 122 | Set components first (`self.set_reader` & `self.set_writer`). | 
|---|
|  | 123 | Explicitly setting `self.settings` disables command line option | 
|---|
|  | 124 | processing from `self.publish()`. | 
|---|
|  | 125 | """ | 
|---|
|  | 126 | option_parser = self.setup_option_parser( | 
|---|
|  | 127 | usage, description, settings_spec, config_section, **defaults) | 
|---|
|  | 128 | self.settings = option_parser.get_default_values() | 
|---|
|  | 129 | return self.settings | 
|---|
|  | 130 |  | 
|---|
|  | 131 | def process_programmatic_settings(self, settings_spec, | 
|---|
|  | 132 | settings_overrides, | 
|---|
|  | 133 | config_section): | 
|---|
|  | 134 | if self.settings is None: | 
|---|
|  | 135 | defaults = (settings_overrides or {}).copy() | 
|---|
|  | 136 | # Propagate exceptions by default when used programmatically: | 
|---|
|  | 137 | defaults.setdefault('traceback', 1) | 
|---|
|  | 138 | self.get_settings(settings_spec=settings_spec, | 
|---|
|  | 139 | config_section=config_section, | 
|---|
|  | 140 | **defaults) | 
|---|
|  | 141 |  | 
|---|
|  | 142 | def process_command_line(self, argv=None, usage=None, description=None, | 
|---|
|  | 143 | settings_spec=None, config_section=None, | 
|---|
|  | 144 | **defaults): | 
|---|
|  | 145 | """ | 
|---|
|  | 146 | Pass an empty list to `argv` to avoid reading `sys.argv` (the | 
|---|
|  | 147 | default). | 
|---|
|  | 148 |  | 
|---|
|  | 149 | Set components first (`self.set_reader` & `self.set_writer`). | 
|---|
|  | 150 | """ | 
|---|
|  | 151 | option_parser = self.setup_option_parser( | 
|---|
|  | 152 | usage, description, settings_spec, config_section, **defaults) | 
|---|
|  | 153 | if argv is None: | 
|---|
|  | 154 | argv = sys.argv[1:] | 
|---|
|  | 155 | self.settings = option_parser.parse_args(argv) | 
|---|
|  | 156 |  | 
|---|
|  | 157 | def set_io(self, source_path=None, destination_path=None): | 
|---|
|  | 158 | if self.source is None: | 
|---|
|  | 159 | self.set_source(source_path=source_path) | 
|---|
|  | 160 | if self.destination is None: | 
|---|
|  | 161 | self.set_destination(destination_path=destination_path) | 
|---|
|  | 162 |  | 
|---|
|  | 163 | def set_source(self, source=None, source_path=None): | 
|---|
|  | 164 | if source_path is None: | 
|---|
|  | 165 | source_path = self.settings._source | 
|---|
|  | 166 | else: | 
|---|
|  | 167 | self.settings._source = source_path | 
|---|
|  | 168 | self.source = self.source_class( | 
|---|
|  | 169 | source=source, source_path=source_path, | 
|---|
|  | 170 | encoding=self.settings.input_encoding) | 
|---|
|  | 171 |  | 
|---|
|  | 172 | def set_destination(self, destination=None, destination_path=None): | 
|---|
|  | 173 | if destination_path is None: | 
|---|
|  | 174 | destination_path = self.settings._destination | 
|---|
|  | 175 | else: | 
|---|
|  | 176 | self.settings._destination = destination_path | 
|---|
|  | 177 | self.destination = self.destination_class( | 
|---|
|  | 178 | destination=destination, destination_path=destination_path, | 
|---|
|  | 179 | encoding=self.settings.output_encoding, | 
|---|
|  | 180 | error_handler=self.settings.output_encoding_error_handler) | 
|---|
|  | 181 |  | 
|---|
|  | 182 | def apply_transforms(self): | 
|---|
|  | 183 | self.document.transformer.populate_from_components( | 
|---|
|  | 184 | (self.source, self.reader, self.reader.parser, self.writer, | 
|---|
|  | 185 | self.destination)) | 
|---|
|  | 186 | self.document.transformer.apply_transforms() | 
|---|
|  | 187 |  | 
|---|
|  | 188 | def publish(self, argv=None, usage=None, description=None, | 
|---|
|  | 189 | settings_spec=None, settings_overrides=None, | 
|---|
|  | 190 | config_section=None, enable_exit_status=None): | 
|---|
|  | 191 | """ | 
|---|
|  | 192 | Process command line options and arguments (if `self.settings` not | 
|---|
|  | 193 | already set), run `self.reader` and then `self.writer`.  Return | 
|---|
|  | 194 | `self.writer`'s output. | 
|---|
|  | 195 | """ | 
|---|
|  | 196 | exit = None | 
|---|
|  | 197 | try: | 
|---|
|  | 198 | if self.settings is None: | 
|---|
|  | 199 | self.process_command_line( | 
|---|
|  | 200 | argv, usage, description, settings_spec, config_section, | 
|---|
|  | 201 | **(settings_overrides or {})) | 
|---|
|  | 202 | self.set_io() | 
|---|
|  | 203 | self.document = self.reader.read(self.source, self.parser, | 
|---|
|  | 204 | self.settings) | 
|---|
|  | 205 | self.apply_transforms() | 
|---|
|  | 206 | output = self.writer.write(self.document, self.destination) | 
|---|
|  | 207 | self.writer.assemble_parts() | 
|---|
|  | 208 | except SystemExit, error: | 
|---|
|  | 209 | exit = 1 | 
|---|
|  | 210 | exit_status = error.code | 
|---|
|  | 211 | except Exception, error: | 
|---|
|  | 212 | if not self.settings:       # exception too early to report nicely | 
|---|
|  | 213 | raise | 
|---|
|  | 214 | if self.settings.traceback: # Propagate exceptions? | 
|---|
|  | 215 | self.debugging_dumps() | 
|---|
|  | 216 | raise | 
|---|
|  | 217 | self.report_Exception(error) | 
|---|
|  | 218 | exit = 1 | 
|---|
|  | 219 | exit_status = 1 | 
|---|
|  | 220 | self.debugging_dumps() | 
|---|
|  | 221 | if (enable_exit_status and self.document | 
|---|
|  | 222 | and (self.document.reporter.max_level | 
|---|
|  | 223 | >= self.settings.exit_status_level)): | 
|---|
|  | 224 | sys.exit(self.document.reporter.max_level + 10) | 
|---|
|  | 225 | elif exit: | 
|---|
|  | 226 | sys.exit(exit_status) | 
|---|
|  | 227 | return output | 
|---|
|  | 228 |  | 
|---|
|  | 229 | def debugging_dumps(self): | 
|---|
|  | 230 | if not self.document: | 
|---|
|  | 231 | return | 
|---|
|  | 232 | if self.settings.dump_settings: | 
|---|
|  | 233 | print >>sys.stderr, '\n::: Runtime settings:' | 
|---|
|  | 234 | print >>sys.stderr, pprint.pformat(self.settings.__dict__) | 
|---|
|  | 235 | if self.settings.dump_internals: | 
|---|
|  | 236 | print >>sys.stderr, '\n::: Document internals:' | 
|---|
|  | 237 | print >>sys.stderr, pprint.pformat(self.document.__dict__) | 
|---|
|  | 238 | if self.settings.dump_transforms: | 
|---|
|  | 239 | print >>sys.stderr, '\n::: Transforms applied:' | 
|---|
|  | 240 | print >>sys.stderr, (' (priority, transform class, ' | 
|---|
|  | 241 | 'pending node details, keyword args)') | 
|---|
|  | 242 | print >>sys.stderr, pprint.pformat( | 
|---|
|  | 243 | [(priority, '%s.%s' % (xclass.__module__, xclass.__name__), | 
|---|
|  | 244 | pending and pending.details, kwargs) | 
|---|
|  | 245 | for priority, xclass, pending, kwargs | 
|---|
|  | 246 | in self.document.transformer.applied]) | 
|---|
|  | 247 | if self.settings.dump_pseudo_xml: | 
|---|
|  | 248 | print >>sys.stderr, '\n::: Pseudo-XML:' | 
|---|
|  | 249 | print >>sys.stderr, self.document.pformat().encode( | 
|---|
|  | 250 | 'raw_unicode_escape') | 
|---|
|  | 251 |  | 
|---|
|  | 252 | def report_Exception(self, error): | 
|---|
|  | 253 | if isinstance(error, utils.SystemMessage): | 
|---|
|  | 254 | self.report_SystemMessage(error) | 
|---|
|  | 255 | elif isinstance(error, UnicodeError): | 
|---|
|  | 256 | self.report_UnicodeError(error) | 
|---|
|  | 257 | else: | 
|---|
|  | 258 | print >>sys.stderr, '%s: %s' % (error.__class__.__name__, error) | 
|---|
|  | 259 | print >>sys.stderr, ("""\ | 
|---|
|  | 260 | Exiting due to error.  Use "--traceback" to diagnose. | 
|---|
|  | 261 | Please report errors to <docutils-users@lists.sf.net>. | 
|---|
|  | 262 | Include "--traceback" output, Docutils version (%s [%s]), | 
|---|
|  | 263 | Python version (%s), your OS type & version, and the | 
|---|
|  | 264 | command line used.""" % (__version__, __version_details__, | 
|---|
|  | 265 | sys.version.split()[0])) | 
|---|
|  | 266 |  | 
|---|
|  | 267 | def report_SystemMessage(self, error): | 
|---|
|  | 268 | print >>sys.stderr, ('Exiting due to level-%s (%s) system message.' | 
|---|
|  | 269 | % (error.level, | 
|---|
|  | 270 | utils.Reporter.levels[error.level])) | 
|---|
|  | 271 |  | 
|---|
|  | 272 | def report_UnicodeError(self, error): | 
|---|
|  | 273 | sys.stderr.write( | 
|---|
|  | 274 | '%s: %s\n' | 
|---|
|  | 275 | '\n' | 
|---|
|  | 276 | 'The specified output encoding (%s) cannot\n' | 
|---|
|  | 277 | 'handle all of the output.\n' | 
|---|
|  | 278 | 'Try setting "--output-encoding-error-handler" to\n' | 
|---|
|  | 279 | '\n' | 
|---|
|  | 280 | '* "xmlcharrefreplace" (for HTML & XML output);\n' | 
|---|
|  | 281 | % (error.__class__.__name__, error, | 
|---|
|  | 282 | self.settings.output_encoding)) | 
|---|
|  | 283 | try: | 
|---|
|  | 284 | data = error.object[error.start:error.end] | 
|---|
|  | 285 | sys.stderr.write( | 
|---|
|  | 286 | '  the output will contain "%s" and should be usable.\n' | 
|---|
|  | 287 | '* "backslashreplace" (for other output formats, Python 2.3+);\n' | 
|---|
|  | 288 | '  look for "%s" in the output.\n' | 
|---|
|  | 289 | % (data.encode('ascii', 'xmlcharrefreplace'), | 
|---|
|  | 290 | data.encode('ascii', 'backslashreplace'))) | 
|---|
|  | 291 | except AttributeError: | 
|---|
|  | 292 | sys.stderr.write('  the output should be usable as-is.\n') | 
|---|
|  | 293 | sys.stderr.write( | 
|---|
|  | 294 | '* "replace"; look for "?" in the output.\n' | 
|---|
|  | 295 | '\n' | 
|---|
|  | 296 | '"--output-encoding-error-handler" is currently set to "%s".\n' | 
|---|
|  | 297 | '\n' | 
|---|
|  | 298 | 'Exiting due to error.  Use "--traceback" to diagnose.\n' | 
|---|
|  | 299 | 'If the advice above doesn\'t eliminate the error,\n' | 
|---|
|  | 300 | 'please report it to <docutils-users@lists.sf.net>.\n' | 
|---|
|  | 301 | 'Include "--traceback" output, Docutils version (%s),\n' | 
|---|
|  | 302 | 'Python version (%s), your OS type & version, and the\n' | 
|---|
|  | 303 | 'command line used.\n' | 
|---|
|  | 304 | % (self.settings.output_encoding_error_handler, | 
|---|
|  | 305 | __version__, sys.version.split()[0])) | 
|---|
|  | 306 |  | 
|---|
|  | 307 | default_usage = '%prog [options] [<source> [<destination>]]' | 
|---|
|  | 308 | default_description = ('Reads from <source> (default is stdin) and writes to ' | 
|---|
|  | 309 | '<destination> (default is stdout).') | 
|---|
|  | 310 |  | 
|---|
|  | 311 | def publish_cmdline(reader=None, reader_name='standalone', | 
|---|
|  | 312 | parser=None, parser_name='restructuredtext', | 
|---|
|  | 313 | writer=None, writer_name='pseudoxml', | 
|---|
|  | 314 | settings=None, settings_spec=None, | 
|---|
|  | 315 | settings_overrides=None, config_section=None, | 
|---|
|  | 316 | enable_exit_status=1, argv=None, | 
|---|
|  | 317 | usage=default_usage, description=default_description): | 
|---|
|  | 318 | """ | 
|---|
|  | 319 | Set up & run a `Publisher` for command-line-based file I/O (input and | 
|---|
|  | 320 | output file paths taken automatically from the command line).  Return the | 
|---|
|  | 321 | encoded string output also. | 
|---|
|  | 322 |  | 
|---|
|  | 323 | Parameters: see `publish_programmatically` for the remainder. | 
|---|
|  | 324 |  | 
|---|
|  | 325 | - `argv`: Command-line argument list to use instead of ``sys.argv[1:]``. | 
|---|
|  | 326 | - `usage`: Usage string, output if there's a problem parsing the command | 
|---|
|  | 327 | line. | 
|---|
|  | 328 | - `description`: Program description, output for the "--help" option | 
|---|
|  | 329 | (along with command-line option descriptions). | 
|---|
|  | 330 | """ | 
|---|
|  | 331 | pub = Publisher(reader, parser, writer, settings=settings) | 
|---|
|  | 332 | pub.set_components(reader_name, parser_name, writer_name) | 
|---|
|  | 333 | output = pub.publish( | 
|---|
|  | 334 | argv, usage, description, settings_spec, settings_overrides, | 
|---|
|  | 335 | config_section=config_section, enable_exit_status=enable_exit_status) | 
|---|
|  | 336 | return output | 
|---|
|  | 337 |  | 
|---|
|  | 338 | def publish_file(source=None, source_path=None, | 
|---|
|  | 339 | destination=None, destination_path=None, | 
|---|
|  | 340 | reader=None, reader_name='standalone', | 
|---|
|  | 341 | parser=None, parser_name='restructuredtext', | 
|---|
|  | 342 | writer=None, writer_name='pseudoxml', | 
|---|
|  | 343 | settings=None, settings_spec=None, settings_overrides=None, | 
|---|
|  | 344 | config_section=None, enable_exit_status=None): | 
|---|
|  | 345 | """ | 
|---|
|  | 346 | Set up & run a `Publisher` for programmatic use with file-like I/O. | 
|---|
|  | 347 | Return the encoded string output also. | 
|---|
|  | 348 |  | 
|---|
|  | 349 | Parameters: see `publish_programmatically`. | 
|---|
|  | 350 | """ | 
|---|
|  | 351 | output, pub = publish_programmatically( | 
|---|
|  | 352 | source_class=io.FileInput, source=source, source_path=source_path, | 
|---|
|  | 353 | destination_class=io.FileOutput, | 
|---|
|  | 354 | destination=destination, destination_path=destination_path, | 
|---|
|  | 355 | reader=reader, reader_name=reader_name, | 
|---|
|  | 356 | parser=parser, parser_name=parser_name, | 
|---|
|  | 357 | writer=writer, writer_name=writer_name, | 
|---|
|  | 358 | settings=settings, settings_spec=settings_spec, | 
|---|
|  | 359 | settings_overrides=settings_overrides, | 
|---|
|  | 360 | config_section=config_section, | 
|---|
|  | 361 | enable_exit_status=enable_exit_status) | 
|---|
|  | 362 | return output | 
|---|
|  | 363 |  | 
|---|
|  | 364 | def publish_string(source, source_path=None, destination_path=None, | 
|---|
|  | 365 | reader=None, reader_name='standalone', | 
|---|
|  | 366 | parser=None, parser_name='restructuredtext', | 
|---|
|  | 367 | writer=None, writer_name='pseudoxml', | 
|---|
|  | 368 | settings=None, settings_spec=None, | 
|---|
|  | 369 | settings_overrides=None, config_section=None, | 
|---|
|  | 370 | enable_exit_status=None): | 
|---|
|  | 371 | """ | 
|---|
|  | 372 | Set up & run a `Publisher` for programmatic use with string I/O.  Return | 
|---|
|  | 373 | the encoded string or Unicode string output. | 
|---|
|  | 374 |  | 
|---|
|  | 375 | For encoded string output, be sure to set the 'output_encoding' setting to | 
|---|
|  | 376 | the desired encoding.  Set it to 'unicode' for unencoded Unicode string | 
|---|
|  | 377 | output.  Here's one way:: | 
|---|
|  | 378 |  | 
|---|
|  | 379 | publish_string(..., settings_overrides={'output_encoding': 'unicode'}) | 
|---|
|  | 380 |  | 
|---|
|  | 381 | Similarly for Unicode string input (`source`):: | 
|---|
|  | 382 |  | 
|---|
|  | 383 | publish_string(..., settings_overrides={'input_encoding': 'unicode'}) | 
|---|
|  | 384 |  | 
|---|
|  | 385 | Parameters: see `publish_programmatically`. | 
|---|
|  | 386 | """ | 
|---|
|  | 387 | output, pub = publish_programmatically( | 
|---|
|  | 388 | source_class=io.StringInput, source=source, source_path=source_path, | 
|---|
|  | 389 | destination_class=io.StringOutput, | 
|---|
|  | 390 | destination=None, destination_path=destination_path, | 
|---|
|  | 391 | reader=reader, reader_name=reader_name, | 
|---|
|  | 392 | parser=parser, parser_name=parser_name, | 
|---|
|  | 393 | writer=writer, writer_name=writer_name, | 
|---|
|  | 394 | settings=settings, settings_spec=settings_spec, | 
|---|
|  | 395 | settings_overrides=settings_overrides, | 
|---|
|  | 396 | config_section=config_section, | 
|---|
|  | 397 | enable_exit_status=enable_exit_status) | 
|---|
|  | 398 | return output | 
|---|
|  | 399 |  | 
|---|
|  | 400 | def publish_parts(source, source_path=None, source_class=io.StringInput, | 
|---|
|  | 401 | destination_path=None, | 
|---|
|  | 402 | reader=None, reader_name='standalone', | 
|---|
|  | 403 | parser=None, parser_name='restructuredtext', | 
|---|
|  | 404 | writer=None, writer_name='pseudoxml', | 
|---|
|  | 405 | settings=None, settings_spec=None, | 
|---|
|  | 406 | settings_overrides=None, config_section=None, | 
|---|
|  | 407 | enable_exit_status=None): | 
|---|
|  | 408 | """ | 
|---|
|  | 409 | Set up & run a `Publisher`, and return a dictionary of document parts. | 
|---|
|  | 410 | Dictionary keys are the names of parts, and values are Unicode strings; | 
|---|
|  | 411 | encoding is up to the client.  For programmatic use with string I/O. | 
|---|
|  | 412 |  | 
|---|
|  | 413 | For encoded string input, be sure to set the 'input_encoding' setting to | 
|---|
|  | 414 | the desired encoding.  Set it to 'unicode' for unencoded Unicode string | 
|---|
|  | 415 | input.  Here's how:: | 
|---|
|  | 416 |  | 
|---|
|  | 417 | publish_parts(..., settings_overrides={'input_encoding': 'unicode'}) | 
|---|
|  | 418 |  | 
|---|
|  | 419 | Parameters: see `publish_programmatically`. | 
|---|
|  | 420 | """ | 
|---|
|  | 421 | output, pub = publish_programmatically( | 
|---|
|  | 422 | source=source, source_path=source_path, source_class=source_class, | 
|---|
|  | 423 | destination_class=io.StringOutput, | 
|---|
|  | 424 | destination=None, destination_path=destination_path, | 
|---|
|  | 425 | reader=reader, reader_name=reader_name, | 
|---|
|  | 426 | parser=parser, parser_name=parser_name, | 
|---|
|  | 427 | writer=writer, writer_name=writer_name, | 
|---|
|  | 428 | settings=settings, settings_spec=settings_spec, | 
|---|
|  | 429 | settings_overrides=settings_overrides, | 
|---|
|  | 430 | config_section=config_section, | 
|---|
|  | 431 | enable_exit_status=enable_exit_status) | 
|---|
|  | 432 | return pub.writer.parts | 
|---|
|  | 433 |  | 
|---|
|  | 434 | def publish_doctree(source, source_path=None, | 
|---|
|  | 435 | source_class=io.StringInput, | 
|---|
|  | 436 | reader=None, reader_name='standalone', | 
|---|
|  | 437 | parser=None, parser_name='restructuredtext', | 
|---|
|  | 438 | settings=None, settings_spec=None, | 
|---|
|  | 439 | settings_overrides=None, config_section=None, | 
|---|
|  | 440 | enable_exit_status=None): | 
|---|
|  | 441 | """ | 
|---|
|  | 442 | Set up & run a `Publisher` for programmatic use with string I/O. | 
|---|
|  | 443 | Return the document tree. | 
|---|
|  | 444 |  | 
|---|
|  | 445 | For encoded string input, be sure to set the 'input_encoding' setting to | 
|---|
|  | 446 | the desired encoding.  Set it to 'unicode' for unencoded Unicode string | 
|---|
|  | 447 | input.  Here's one way:: | 
|---|
|  | 448 |  | 
|---|
|  | 449 | publish_doctree(..., settings_overrides={'input_encoding': 'unicode'}) | 
|---|
|  | 450 |  | 
|---|
|  | 451 | Parameters: see `publish_programmatically`. | 
|---|
|  | 452 | """ | 
|---|
|  | 453 | pub = Publisher(reader=reader, parser=parser, writer=None, | 
|---|
|  | 454 | settings=settings, | 
|---|
|  | 455 | source_class=source_class, | 
|---|
|  | 456 | destination_class=io.NullOutput) | 
|---|
|  | 457 | pub.set_components(reader_name, parser_name, 'null') | 
|---|
|  | 458 | pub.process_programmatic_settings( | 
|---|
|  | 459 | settings_spec, settings_overrides, config_section) | 
|---|
|  | 460 | pub.set_source(source, source_path) | 
|---|
|  | 461 | pub.set_destination(None, None) | 
|---|
|  | 462 | output = pub.publish(enable_exit_status=enable_exit_status) | 
|---|
|  | 463 | return pub.document | 
|---|
|  | 464 |  | 
|---|
|  | 465 | def publish_from_doctree(document, destination_path=None, | 
|---|
|  | 466 | writer=None, writer_name='pseudoxml', | 
|---|
|  | 467 | settings=None, settings_spec=None, | 
|---|
|  | 468 | settings_overrides=None, config_section=None, | 
|---|
|  | 469 | enable_exit_status=None): | 
|---|
|  | 470 | """ | 
|---|
|  | 471 | Set up & run a `Publisher` to render from an existing document tree data | 
|---|
|  | 472 | structure, for programmatic use with string I/O.  Return a pair of encoded | 
|---|
|  | 473 | string output and document parts. | 
|---|
|  | 474 |  | 
|---|
|  | 475 | Note that document.settings is overridden; if you want to use the settings | 
|---|
|  | 476 | of the original `document`, pass settings=document.settings. | 
|---|
|  | 477 |  | 
|---|
|  | 478 | Also, new document.transformer and document.reporter objects are | 
|---|
|  | 479 | generated. | 
|---|
|  | 480 |  | 
|---|
|  | 481 | For encoded string output, be sure to set the 'output_encoding' setting to | 
|---|
|  | 482 | the desired encoding.  Set it to 'unicode' for unencoded Unicode string | 
|---|
|  | 483 | output.  Here's one way:: | 
|---|
|  | 484 |  | 
|---|
|  | 485 | publish_from_doctree( | 
|---|
|  | 486 | ..., settings_overrides={'output_encoding': 'unicode'}) | 
|---|
|  | 487 |  | 
|---|
|  | 488 | Parameters: `document` is a `docutils.nodes.document` object, an existing | 
|---|
|  | 489 | document tree. | 
|---|
|  | 490 |  | 
|---|
|  | 491 | Other parameters: see `publish_programmatically`. | 
|---|
|  | 492 | """ | 
|---|
|  | 493 | reader = docutils.readers.doctree.Reader(parser_name='null') | 
|---|
|  | 494 | pub = Publisher(reader, None, writer, | 
|---|
|  | 495 | source=io.DocTreeInput(document), | 
|---|
|  | 496 | destination_class=io.StringOutput, settings=settings) | 
|---|
|  | 497 | if not writer and writer_name: | 
|---|
|  | 498 | pub.set_writer(writer_name) | 
|---|
|  | 499 | pub.process_programmatic_settings( | 
|---|
|  | 500 | settings_spec, settings_overrides, config_section) | 
|---|
|  | 501 | pub.set_destination(None, destination_path) | 
|---|
|  | 502 | return pub.publish(enable_exit_status=enable_exit_status) | 
|---|
|  | 503 |  | 
|---|
|  | 504 | def publish_programmatically(source_class, source, source_path, | 
|---|
|  | 505 | destination_class, destination, destination_path, | 
|---|
|  | 506 | reader, reader_name, | 
|---|
|  | 507 | parser, parser_name, | 
|---|
|  | 508 | writer, writer_name, | 
|---|
|  | 509 | settings, settings_spec, | 
|---|
|  | 510 | settings_overrides, config_section, | 
|---|
|  | 511 | enable_exit_status): | 
|---|
|  | 512 | """ | 
|---|
|  | 513 | Set up & run a `Publisher` for custom programmatic use.  Return the | 
|---|
|  | 514 | encoded string output and the Publisher object. | 
|---|
|  | 515 |  | 
|---|
|  | 516 | Applications should not need to call this function directly.  If it does | 
|---|
|  | 517 | seem to be necessary to call this function directly, please write to the | 
|---|
|  | 518 | Docutils-develop mailing list | 
|---|
|  | 519 | <http://docutils.sf.net/docs/user/mailing-lists.html#docutils-develop>. | 
|---|
|  | 520 |  | 
|---|
|  | 521 | Parameters: | 
|---|
|  | 522 |  | 
|---|
|  | 523 | * `source_class` **required**: The class for dynamically created source | 
|---|
|  | 524 | objects.  Typically `io.FileInput` or `io.StringInput`. | 
|---|
|  | 525 |  | 
|---|
|  | 526 | * `source`: Type depends on `source_class`: | 
|---|
|  | 527 |  | 
|---|
|  | 528 | - If `source_class` is `io.FileInput`: Either a file-like object | 
|---|
|  | 529 | (must have 'read' and 'close' methods), or ``None`` | 
|---|
|  | 530 | (`source_path` is opened).  If neither `source` nor | 
|---|
|  | 531 | `source_path` are supplied, `sys.stdin` is used. | 
|---|
|  | 532 |  | 
|---|
|  | 533 | - If `source_class` is `io.StringInput` **required**: The input | 
|---|
|  | 534 | string, either an encoded 8-bit string (set the | 
|---|
|  | 535 | 'input_encoding' setting to the correct encoding) or a Unicode | 
|---|
|  | 536 | string (set the 'input_encoding' setting to 'unicode'). | 
|---|
|  | 537 |  | 
|---|
|  | 538 | * `source_path`: Type depends on `source_class`: | 
|---|
|  | 539 |  | 
|---|
|  | 540 | - `io.FileInput`: Path to the input file, opened if no `source` | 
|---|
|  | 541 | supplied. | 
|---|
|  | 542 |  | 
|---|
|  | 543 | - `io.StringInput`: Optional.  Path to the file or object that produced | 
|---|
|  | 544 | `source`.  Only used for diagnostic output. | 
|---|
|  | 545 |  | 
|---|
|  | 546 | * `destination_class` **required**: The class for dynamically created | 
|---|
|  | 547 | destination objects.  Typically `io.FileOutput` or `io.StringOutput`. | 
|---|
|  | 548 |  | 
|---|
|  | 549 | * `destination`: Type depends on `destination_class`: | 
|---|
|  | 550 |  | 
|---|
|  | 551 | - `io.FileOutput`: Either a file-like object (must have 'write' and | 
|---|
|  | 552 | 'close' methods), or ``None`` (`destination_path` is opened).  If | 
|---|
|  | 553 | neither `destination` nor `destination_path` are supplied, | 
|---|
|  | 554 | `sys.stdout` is used. | 
|---|
|  | 555 |  | 
|---|
|  | 556 | - `io.StringOutput`: Not used; pass ``None``. | 
|---|
|  | 557 |  | 
|---|
|  | 558 | * `destination_path`: Type depends on `destination_class`: | 
|---|
|  | 559 |  | 
|---|
|  | 560 | - `io.FileOutput`: Path to the output file.  Opened if no `destination` | 
|---|
|  | 561 | supplied. | 
|---|
|  | 562 |  | 
|---|
|  | 563 | - `io.StringOutput`: Path to the file or object which will receive the | 
|---|
|  | 564 | output; optional.  Used for determining relative paths (stylesheets, | 
|---|
|  | 565 | source links, etc.). | 
|---|
|  | 566 |  | 
|---|
|  | 567 | * `reader`: A `docutils.readers.Reader` object. | 
|---|
|  | 568 |  | 
|---|
|  | 569 | * `reader_name`: Name or alias of the Reader class to be instantiated if | 
|---|
|  | 570 | no `reader` supplied. | 
|---|
|  | 571 |  | 
|---|
|  | 572 | * `parser`: A `docutils.parsers.Parser` object. | 
|---|
|  | 573 |  | 
|---|
|  | 574 | * `parser_name`: Name or alias of the Parser class to be instantiated if | 
|---|
|  | 575 | no `parser` supplied. | 
|---|
|  | 576 |  | 
|---|
|  | 577 | * `writer`: A `docutils.writers.Writer` object. | 
|---|
|  | 578 |  | 
|---|
|  | 579 | * `writer_name`: Name or alias of the Writer class to be instantiated if | 
|---|
|  | 580 | no `writer` supplied. | 
|---|
|  | 581 |  | 
|---|
|  | 582 | * `settings`: A runtime settings (`docutils.frontend.Values`) object, for | 
|---|
|  | 583 | dotted-attribute access to runtime settings.  It's the end result of the | 
|---|
|  | 584 | `SettingsSpec`, config file, and option processing.  If `settings` is | 
|---|
|  | 585 | passed, it's assumed to be complete and no further setting/config/option | 
|---|
|  | 586 | processing is done. | 
|---|
|  | 587 |  | 
|---|
|  | 588 | * `settings_spec`: A `docutils.SettingsSpec` subclass or object.  Provides | 
|---|
|  | 589 | extra application-specific settings definitions independently of | 
|---|
|  | 590 | components.  In other words, the application becomes a component, and | 
|---|
|  | 591 | its settings data is processed along with that of the other components. | 
|---|
|  | 592 | Used only if no `settings` specified. | 
|---|
|  | 593 |  | 
|---|
|  | 594 | * `settings_overrides`: A dictionary containing application-specific | 
|---|
|  | 595 | settings defaults that override the defaults of other components. | 
|---|
|  | 596 | Used only if no `settings` specified. | 
|---|
|  | 597 |  | 
|---|
|  | 598 | * `config_section`: A string, the name of the configuration file section | 
|---|
|  | 599 | for this application.  Overrides the ``config_section`` attribute | 
|---|
|  | 600 | defined by `settings_spec`.  Used only if no `settings` specified. | 
|---|
|  | 601 |  | 
|---|
|  | 602 | * `enable_exit_status`: Boolean; enable exit status at end of processing? | 
|---|
|  | 603 | """ | 
|---|
|  | 604 | pub = Publisher(reader, parser, writer, settings=settings, | 
|---|
|  | 605 | source_class=source_class, | 
|---|
|  | 606 | destination_class=destination_class) | 
|---|
|  | 607 | pub.set_components(reader_name, parser_name, writer_name) | 
|---|
|  | 608 | pub.process_programmatic_settings( | 
|---|
|  | 609 | settings_spec, settings_overrides, config_section) | 
|---|
|  | 610 | pub.set_source(source, source_path) | 
|---|
|  | 611 | pub.set_destination(destination, destination_path) | 
|---|
|  | 612 | output = pub.publish(enable_exit_status=enable_exit_status) | 
|---|
|  | 613 | return output, pub | 
|---|