[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 |
---|