root/galaxy-central/eggs/docutils-0.4-py2.6.egg/docutils/core.py @ 3

リビジョン 3, 26.1 KB (コミッタ: kohda, 14 年 前)

Install Unix tools  http://hannonlab.cshl.edu/galaxy_unix_tools/galaxy.html

行番号 
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"""
8Calling the ``publish_*`` convenience functions (or instantiating a
9`Publisher` object) with component names will result in default
10behavior.  For custom behavior (setting component options), create
11custom 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
19import sys
20import pprint
21from types import StringType
22from docutils import __version__, __version_details__, SettingsSpec
23from docutils import frontend, io, utils, readers, writers
24from docutils.frontend import OptionParser
25from docutils.transforms import Transformer
26import docutils.readers.doctree
27
28
29class 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, ("""\
260Exiting due to error.  Use "--traceback" to diagnose.
261Please report errors to <docutils-users@lists.sf.net>.
262Include "--traceback" output, Docutils version (%s [%s]),
263Python version (%s), your OS type & version, and the
264command 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
307default_usage = '%prog [options] [<source> [<destination>]]'
308default_description = ('Reads from <source> (default is stdin) and writes to '
309                       '<destination> (default is stdout).')
310
311def 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
338def 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
364def 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
400def 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
434def 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
465def 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
504def 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
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。