buildframework/helium/external/python/lib/2.5/docutils-0.5-py2.5.egg/docutils/parsers/rst/directives/images.py
changeset 179 d8ac696cc51f
parent 1 be27ed110b50
child 180 e02a83d4c571
child 592 3215c239276a
equal deleted inserted replaced
1:be27ed110b50 179:d8ac696cc51f
     1 # $Id: images.py 4667 2006-07-12 21:40:56Z wiemann $
       
     2 # Author: David Goodger <goodger@python.org>
       
     3 # Copyright: This module has been placed in the public domain.
       
     4 
       
     5 """
       
     6 Directives for figures and simple images.
       
     7 """
       
     8 
       
     9 __docformat__ = 'reStructuredText'
       
    10 
       
    11 
       
    12 import sys
       
    13 from docutils import nodes, utils
       
    14 from docutils.parsers.rst import Directive
       
    15 from docutils.parsers.rst import directives, states
       
    16 from docutils.nodes import fully_normalize_name, whitespace_normalize_name
       
    17 from docutils.parsers.rst.roles import set_classes
       
    18 
       
    19 try:
       
    20     import Image as PIL                        # PIL
       
    21 except ImportError:
       
    22     PIL = None
       
    23 
       
    24 
       
    25 class Image(Directive):
       
    26 
       
    27     align_h_values = ('left', 'center', 'right')
       
    28     align_v_values = ('top', 'middle', 'bottom')
       
    29     align_values = align_v_values + align_h_values
       
    30 
       
    31     def align(argument):
       
    32         # This is not callable as self.align.  We cannot make it a
       
    33         # staticmethod because we're saving an unbound method in
       
    34         # option_spec below.
       
    35         return directives.choice(argument, Image.align_values)
       
    36 
       
    37     required_arguments = 1
       
    38     optional_arguments = 0
       
    39     final_argument_whitespace = True
       
    40     option_spec = {'alt': directives.unchanged,
       
    41                    'height': directives.length_or_unitless,
       
    42                    'width': directives.length_or_percentage_or_unitless,
       
    43                    'scale': directives.nonnegative_int,
       
    44                    'align': align,
       
    45                    'target': directives.unchanged_required,
       
    46                    'class': directives.class_option}
       
    47 
       
    48     def run(self):
       
    49         if self.options.has_key('align'):
       
    50             if isinstance(self.state, states.SubstitutionDef):
       
    51                 # Check for align_v_values.
       
    52                 if self.options['align'] not in self.align_v_values:
       
    53                     raise self.error(
       
    54                         'Error in "%s" directive: "%s" is not a valid value '
       
    55                         'for the "align" option within a substitution '
       
    56                         'definition.  Valid values for "align" are: "%s".'
       
    57                         % (self.name, self.options['align'],
       
    58                            '", "'.join(self.align_v_values)))
       
    59             elif self.options['align'] not in self.align_h_values:
       
    60                 raise self.error(
       
    61                     'Error in "%s" directive: "%s" is not a valid value for '
       
    62                     'the "align" option.  Valid values for "align" are: "%s".'
       
    63                     % (self.name, self.options['align'],
       
    64                        '", "'.join(self.align_h_values)))
       
    65         messages = []
       
    66         reference = directives.uri(self.arguments[0])
       
    67         self.options['uri'] = reference
       
    68         reference_node = None
       
    69         if self.options.has_key('target'):
       
    70             block = states.escape2null(
       
    71                 self.options['target']).splitlines()
       
    72             block = [line for line in block]
       
    73             target_type, data = self.state.parse_target(
       
    74                 block, self.block_text, self.lineno)
       
    75             if target_type == 'refuri':
       
    76                 reference_node = nodes.reference(refuri=data)
       
    77             elif target_type == 'refname':
       
    78                 reference_node = nodes.reference(
       
    79                     refname=fully_normalize_name(data),
       
    80                     name=whitespace_normalize_name(data))
       
    81                 reference_node.indirect_reference_name = data
       
    82                 self.state.document.note_refname(reference_node)
       
    83             else:                           # malformed target
       
    84                 messages.append(data)       # data is a system message
       
    85             del self.options['target']
       
    86         set_classes(self.options)
       
    87         image_node = nodes.image(self.block_text, **self.options)
       
    88         if reference_node:
       
    89             reference_node += image_node
       
    90             return messages + [reference_node]
       
    91         else:
       
    92             return messages + [image_node]
       
    93 
       
    94 
       
    95 class Figure(Image):
       
    96 
       
    97     def align(argument):
       
    98         return directives.choice(argument, Figure.align_h_values)
       
    99 
       
   100     def figwidth_value(argument):
       
   101         if argument.lower() == 'image':
       
   102             return 'image'
       
   103         else:
       
   104             return directives.nonnegative_int(argument)
       
   105 
       
   106     option_spec = Image.option_spec.copy()
       
   107     option_spec['figwidth'] = figwidth_value
       
   108     option_spec['figclass'] = directives.class_option
       
   109     option_spec['align'] = align
       
   110     has_content = True
       
   111 
       
   112     def run(self):
       
   113         figwidth = self.options.get('figwidth')
       
   114         if figwidth:
       
   115             del self.options['figwidth']
       
   116         figclasses = self.options.get('figclass')
       
   117         if figclasses:
       
   118             del self.options['figclass']
       
   119         align = self.options.get('align')
       
   120         if align:
       
   121             del self.options['align']
       
   122         (image_node,) = Image.run(self)
       
   123         if isinstance(image_node, nodes.system_message):
       
   124             return [image_node]
       
   125         figure_node = nodes.figure('', image_node)
       
   126         if figwidth == 'image':
       
   127             if PIL and self.state.document.settings.file_insertion_enabled:
       
   128                 # PIL doesn't like Unicode paths:
       
   129                 try:
       
   130                     i = PIL.open(str(image_node['uri']))
       
   131                 except (IOError, UnicodeError):
       
   132                     pass
       
   133                 else:
       
   134                     self.state.document.settings.record_dependencies.add(
       
   135                         image_node['uri'])
       
   136                     figure_node['width'] = i.size[0]
       
   137         elif figwidth is not None:
       
   138             figure_node['width'] = figwidth
       
   139         if figclasses:
       
   140             figure_node['classes'] += figclasses
       
   141         if align:
       
   142             figure_node['align'] = align
       
   143         if self.content:
       
   144             node = nodes.Element()          # anonymous container for parsing
       
   145             self.state.nested_parse(self.content, self.content_offset, node)
       
   146             first_node = node[0]
       
   147             if isinstance(first_node, nodes.paragraph):
       
   148                 caption = nodes.caption(first_node.rawsource, '',
       
   149                                         *first_node.children)
       
   150                 figure_node += caption
       
   151             elif not (isinstance(first_node, nodes.comment)
       
   152                       and len(first_node) == 0):
       
   153                 error = self.state_machine.reporter.error(
       
   154                       'Figure caption must be a paragraph or empty comment.',
       
   155                       nodes.literal_block(self.block_text, self.block_text),
       
   156                       line=self.lineno)
       
   157                 return [figure_node, error]
       
   158             if len(node) > 1:
       
   159                 figure_node += nodes.legend('', *node[1:])
       
   160         return [figure_node]