|
1 # $Id: core.py 5033 2007-03-21 19:51:22Z wiemann $ |
|
2 # Author: David Goodger <goodger@python.org> |
|
3 # Copyright: This module has been placed in the public domain. |
|
4 |
|
5 """ |
|
6 Calling the ``publish_*`` convenience functions (or instantiating a |
|
7 `Publisher` object) with component names will result in default |
|
8 behavior. For custom behavior (setting component options), create |
|
9 custom component objects first, and pass *them* to |
|
10 ``publish_*``/`Publisher`. See `The Docutils Publisher`_. |
|
11 |
|
12 .. _The Docutils Publisher: http://docutils.sf.net/docs/api/publisher.html |
|
13 """ |
|
14 |
|
15 __docformat__ = 'reStructuredText' |
|
16 |
|
17 import sys |
|
18 import pprint |
|
19 from types import StringType |
|
20 from docutils import __version__, __version_details__, SettingsSpec |
|
21 from docutils import frontend, io, utils, readers, writers |
|
22 from docutils.frontend import OptionParser |
|
23 from docutils.transforms import Transformer |
|
24 import docutils.readers.doctree |
|
25 |
|
26 |
|
27 class Publisher: |
|
28 |
|
29 """ |
|
30 A facade encapsulating the high-level logic of a Docutils system. |
|
31 """ |
|
32 |
|
33 def __init__(self, reader=None, parser=None, writer=None, |
|
34 source=None, source_class=io.FileInput, |
|
35 destination=None, destination_class=io.FileOutput, |
|
36 settings=None): |
|
37 """ |
|
38 Initial setup. If any of `reader`, `parser`, or `writer` are not |
|
39 specified, the corresponding ``set_...`` method should be called with |
|
40 a component name (`set_reader` sets the parser as well). |
|
41 """ |
|
42 |
|
43 self.document = None |
|
44 """The document tree (`docutils.nodes` objects).""" |
|
45 |
|
46 self.reader = reader |
|
47 """A `docutils.readers.Reader` instance.""" |
|
48 |
|
49 self.parser = parser |
|
50 """A `docutils.parsers.Parser` instance.""" |
|
51 |
|
52 self.writer = writer |
|
53 """A `docutils.writers.Writer` instance.""" |
|
54 |
|
55 for component in 'reader', 'parser', 'writer': |
|
56 assert not isinstance(getattr(self, component), StringType), \ |
|
57 ('passed string as "%s" parameter; use "%s_name" instead' |
|
58 % (getattr(self, component), component, component)) |
|
59 |
|
60 self.source = source |
|
61 """The source of input data, a `docutils.io.Input` instance.""" |
|
62 |
|
63 self.source_class = source_class |
|
64 """The class for dynamically created source objects.""" |
|
65 |
|
66 self.destination = destination |
|
67 """The destination for docutils output, a `docutils.io.Output` |
|
68 instance.""" |
|
69 |
|
70 self.destination_class = destination_class |
|
71 """The class for dynamically created destination objects.""" |
|
72 |
|
73 self.settings = settings |
|
74 """An object containing Docutils settings as instance attributes. |
|
75 Set by `self.process_command_line()` or `self.get_settings()`.""" |
|
76 |
|
77 def set_reader(self, reader_name, parser, parser_name): |
|
78 """Set `self.reader` by name.""" |
|
79 reader_class = readers.get_reader_class(reader_name) |
|
80 self.reader = reader_class(parser, parser_name) |
|
81 self.parser = self.reader.parser |
|
82 |
|
83 def set_writer(self, writer_name): |
|
84 """Set `self.writer` by name.""" |
|
85 writer_class = writers.get_writer_class(writer_name) |
|
86 self.writer = writer_class() |
|
87 |
|
88 def set_components(self, reader_name, parser_name, writer_name): |
|
89 if self.reader is None: |
|
90 self.set_reader(reader_name, self.parser, parser_name) |
|
91 if self.parser is None: |
|
92 if self.reader.parser is None: |
|
93 self.reader.set_parser(parser_name) |
|
94 self.parser = self.reader.parser |
|
95 if self.writer is None: |
|
96 self.set_writer(writer_name) |
|
97 |
|
98 def setup_option_parser(self, usage=None, description=None, |
|
99 settings_spec=None, config_section=None, |
|
100 **defaults): |
|
101 if config_section: |
|
102 if not settings_spec: |
|
103 settings_spec = SettingsSpec() |
|
104 settings_spec.config_section = config_section |
|
105 parts = config_section.split() |
|
106 if len(parts) > 1 and parts[-1] == 'application': |
|
107 settings_spec.config_section_dependencies = ['applications'] |
|
108 #@@@ Add self.source & self.destination to components in future? |
|
109 option_parser = OptionParser( |
|
110 components=(self.parser, self.reader, self.writer, settings_spec), |
|
111 defaults=defaults, read_config_files=1, |
|
112 usage=usage, description=description) |
|
113 return option_parser |
|
114 |
|
115 def get_settings(self, usage=None, description=None, |
|
116 settings_spec=None, config_section=None, **defaults): |
|
117 """ |
|
118 Set and return default settings (overrides in `defaults` dict). |
|
119 |
|
120 Set components first (`self.set_reader` & `self.set_writer`). |
|
121 Explicitly setting `self.settings` disables command line option |
|
122 processing from `self.publish()`. |
|
123 """ |
|
124 option_parser = self.setup_option_parser( |
|
125 usage, description, settings_spec, config_section, **defaults) |
|
126 self.settings = option_parser.get_default_values() |
|
127 return self.settings |
|
128 |
|
129 def process_programmatic_settings(self, settings_spec, |
|
130 settings_overrides, |
|
131 config_section): |
|
132 if self.settings is None: |
|
133 defaults = (settings_overrides or {}).copy() |
|
134 # Propagate exceptions by default when used programmatically: |
|
135 defaults.setdefault('traceback', 1) |
|
136 self.get_settings(settings_spec=settings_spec, |
|
137 config_section=config_section, |
|
138 **defaults) |
|
139 |
|
140 def process_command_line(self, argv=None, usage=None, description=None, |
|
141 settings_spec=None, config_section=None, |
|
142 **defaults): |
|
143 """ |
|
144 Pass an empty list to `argv` to avoid reading `sys.argv` (the |
|
145 default). |
|
146 |
|
147 Set components first (`self.set_reader` & `self.set_writer`). |
|
148 """ |
|
149 option_parser = self.setup_option_parser( |
|
150 usage, description, settings_spec, config_section, **defaults) |
|
151 if argv is None: |
|
152 argv = sys.argv[1:] |
|
153 self.settings = option_parser.parse_args(argv) |
|
154 |
|
155 def set_io(self, source_path=None, destination_path=None): |
|
156 if self.source is None: |
|
157 self.set_source(source_path=source_path) |
|
158 if self.destination is None: |
|
159 self.set_destination(destination_path=destination_path) |
|
160 |
|
161 def set_source(self, source=None, source_path=None): |
|
162 if source_path is None: |
|
163 source_path = self.settings._source |
|
164 else: |
|
165 self.settings._source = source_path |
|
166 self.source = self.source_class( |
|
167 source=source, source_path=source_path, |
|
168 encoding=self.settings.input_encoding) |
|
169 |
|
170 def set_destination(self, destination=None, destination_path=None): |
|
171 if destination_path is None: |
|
172 destination_path = self.settings._destination |
|
173 else: |
|
174 self.settings._destination = destination_path |
|
175 self.destination = self.destination_class( |
|
176 destination=destination, destination_path=destination_path, |
|
177 encoding=self.settings.output_encoding, |
|
178 error_handler=self.settings.output_encoding_error_handler) |
|
179 |
|
180 def apply_transforms(self): |
|
181 self.document.transformer.populate_from_components( |
|
182 (self.source, self.reader, self.reader.parser, self.writer, |
|
183 self.destination)) |
|
184 self.document.transformer.apply_transforms() |
|
185 |
|
186 def publish(self, argv=None, usage=None, description=None, |
|
187 settings_spec=None, settings_overrides=None, |
|
188 config_section=None, enable_exit_status=None): |
|
189 """ |
|
190 Process command line options and arguments (if `self.settings` not |
|
191 already set), run `self.reader` and then `self.writer`. Return |
|
192 `self.writer`'s output. |
|
193 """ |
|
194 exit = None |
|
195 try: |
|
196 if self.settings is None: |
|
197 self.process_command_line( |
|
198 argv, usage, description, settings_spec, config_section, |
|
199 **(settings_overrides or {})) |
|
200 self.set_io() |
|
201 self.document = self.reader.read(self.source, self.parser, |
|
202 self.settings) |
|
203 self.apply_transforms() |
|
204 output = self.writer.write(self.document, self.destination) |
|
205 self.writer.assemble_parts() |
|
206 except SystemExit, error: |
|
207 exit = 1 |
|
208 exit_status = error.code |
|
209 except Exception, error: |
|
210 if not self.settings: # exception too early to report nicely |
|
211 raise |
|
212 if self.settings.traceback: # Propagate exceptions? |
|
213 self.debugging_dumps() |
|
214 raise |
|
215 self.report_Exception(error) |
|
216 exit = 1 |
|
217 exit_status = 1 |
|
218 self.debugging_dumps() |
|
219 if (enable_exit_status and self.document |
|
220 and (self.document.reporter.max_level |
|
221 >= self.settings.exit_status_level)): |
|
222 sys.exit(self.document.reporter.max_level + 10) |
|
223 elif exit: |
|
224 sys.exit(exit_status) |
|
225 return output |
|
226 |
|
227 def debugging_dumps(self): |
|
228 if not self.document: |
|
229 return |
|
230 if self.settings.dump_settings: |
|
231 print >>sys.stderr, '\n::: Runtime settings:' |
|
232 print >>sys.stderr, pprint.pformat(self.settings.__dict__) |
|
233 if self.settings.dump_internals: |
|
234 print >>sys.stderr, '\n::: Document internals:' |
|
235 print >>sys.stderr, pprint.pformat(self.document.__dict__) |
|
236 if self.settings.dump_transforms: |
|
237 print >>sys.stderr, '\n::: Transforms applied:' |
|
238 print >>sys.stderr, (' (priority, transform class, ' |
|
239 'pending node details, keyword args)') |
|
240 print >>sys.stderr, pprint.pformat( |
|
241 [(priority, '%s.%s' % (xclass.__module__, xclass.__name__), |
|
242 pending and pending.details, kwargs) |
|
243 for priority, xclass, pending, kwargs |
|
244 in self.document.transformer.applied]) |
|
245 if self.settings.dump_pseudo_xml: |
|
246 print >>sys.stderr, '\n::: Pseudo-XML:' |
|
247 print >>sys.stderr, self.document.pformat().encode( |
|
248 'raw_unicode_escape') |
|
249 |
|
250 def report_Exception(self, error): |
|
251 if isinstance(error, utils.SystemMessage): |
|
252 self.report_SystemMessage(error) |
|
253 elif isinstance(error, UnicodeError): |
|
254 self.report_UnicodeError(error) |
|
255 else: |
|
256 print >>sys.stderr, '%s: %s' % (error.__class__.__name__, error) |
|
257 print >>sys.stderr, ("""\ |
|
258 Exiting due to error. Use "--traceback" to diagnose. |
|
259 Please report errors to <docutils-users@lists.sf.net>. |
|
260 Include "--traceback" output, Docutils version (%s [%s]), |
|
261 Python version (%s), your OS type & version, and the |
|
262 command line used.""" % (__version__, __version_details__, |
|
263 sys.version.split()[0])) |
|
264 |
|
265 def report_SystemMessage(self, error): |
|
266 print >>sys.stderr, ('Exiting due to level-%s (%s) system message.' |
|
267 % (error.level, |
|
268 utils.Reporter.levels[error.level])) |
|
269 |
|
270 def report_UnicodeError(self, error): |
|
271 sys.stderr.write( |
|
272 '%s: %s\n' |
|
273 '\n' |
|
274 'The specified output encoding (%s) cannot\n' |
|
275 'handle all of the output.\n' |
|
276 'Try setting "--output-encoding-error-handler" to\n' |
|
277 '\n' |
|
278 '* "xmlcharrefreplace" (for HTML & XML output);\n' |
|
279 % (error.__class__.__name__, error, |
|
280 self.settings.output_encoding)) |
|
281 try: |
|
282 data = error.object[error.start:error.end] |
|
283 sys.stderr.write( |
|
284 ' the output will contain "%s" and should be usable.\n' |
|
285 '* "backslashreplace" (for other output formats, Python 2.3+);\n' |
|
286 ' look for "%s" in the output.\n' |
|
287 % (data.encode('ascii', 'xmlcharrefreplace'), |
|
288 data.encode('ascii', 'backslashreplace'))) |
|
289 except AttributeError: |
|
290 sys.stderr.write(' the output should be usable as-is.\n') |
|
291 sys.stderr.write( |
|
292 '* "replace"; look for "?" in the output.\n' |
|
293 '\n' |
|
294 '"--output-encoding-error-handler" is currently set to "%s".\n' |
|
295 '\n' |
|
296 'Exiting due to error. Use "--traceback" to diagnose.\n' |
|
297 'If the advice above doesn\'t eliminate the error,\n' |
|
298 'please report it to <docutils-users@lists.sf.net>.\n' |
|
299 'Include "--traceback" output, Docutils version (%s),\n' |
|
300 'Python version (%s), your OS type & version, and the\n' |
|
301 'command line used.\n' |
|
302 % (self.settings.output_encoding_error_handler, |
|
303 __version__, sys.version.split()[0])) |
|
304 |
|
305 default_usage = '%prog [options] [<source> [<destination>]]' |
|
306 default_description = ('Reads from <source> (default is stdin) and writes to ' |
|
307 '<destination> (default is stdout). See ' |
|
308 '<http://docutils.sf.net/docs/user/config.html> for ' |
|
309 'the full reference.') |
|
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 |
|
472 tree data structure, for programmatic use with string I/O. Return |
|
473 the encoded string output. |
|
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 |