root/galaxy-central/eggs/docutils-0.4-py2.6.egg/docutils/parsers/rst/directives/misc.py

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

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

行番号 
1# Authors: David Goodger, Dethe Elza
2# Contact: goodger@users.sourceforge.net
3# Revision: $Revision: 4229 $
4# Date: $Date: 2005-12-23 00:46:16 +0100 (Fri, 23 Dec 2005) $
5# Copyright: This module has been placed in the public domain.
6
7"""Miscellaneous directives."""
8
9__docformat__ = 'reStructuredText'
10
11import sys
12import os.path
13import re
14import time
15from docutils import io, nodes, statemachine, utils
16from docutils.parsers.rst import directives, roles, states
17from docutils.transforms import misc
18
19try:
20    import urllib2
21except ImportError:
22    urllib2 = None
23
24
25standard_include_path = os.path.join(os.path.dirname(states.__file__),
26                                     'include')
27
28def include(name, arguments, options, content, lineno,
29            content_offset, block_text, state, state_machine):
30    """Include a reST file as part of the content of this reST file."""
31    if not state.document.settings.file_insertion_enabled:
32        warning = state_machine.reporter.warning(
33              '"%s" directive disabled.' % name,
34              nodes.literal_block(block_text, block_text), line=lineno)
35        return [warning]
36    source = state_machine.input_lines.source(
37        lineno - state_machine.input_offset - 1)
38    source_dir = os.path.dirname(os.path.abspath(source))
39    path = directives.path(arguments[0])
40    if path.startswith('<') and  path.endswith('>'):
41        path = os.path.join(standard_include_path, path[1:-1])
42    path = os.path.normpath(os.path.join(source_dir, path))
43    path = utils.relative_path(None, path)
44    encoding = options.get('encoding', state.document.settings.input_encoding)
45    try:
46        state.document.settings.record_dependencies.add(path)
47        include_file = io.FileInput(
48            source_path=path, encoding=encoding,
49            error_handler=state.document.settings.input_encoding_error_handler,
50            handle_io_errors=None)
51    except IOError, error:
52        severe = state_machine.reporter.severe(
53              'Problems with "%s" directive path:\n%s: %s.'
54              % (name, error.__class__.__name__, error),
55              nodes.literal_block(block_text, block_text), line=lineno)
56        return [severe]
57    try:
58        include_text = include_file.read()
59    except UnicodeError, error:
60        severe = state_machine.reporter.severe(
61              'Problem with "%s" directive:\n%s: %s'
62              % (name, error.__class__.__name__, error),
63              nodes.literal_block(block_text, block_text), line=lineno)
64        return [severe]
65    if options.has_key('literal'):
66        literal_block = nodes.literal_block(include_text, include_text,
67                                            source=path)
68        literal_block.line = 1
69        return literal_block
70    else:
71        include_lines = statemachine.string2lines(include_text,
72                                                  convert_whitespace=1)
73        state_machine.insert_input(include_lines, path)
74        return []
75
76include.arguments = (1, 0, 1)
77include.options = {'literal': directives.flag,
78                   'encoding': directives.encoding}
79
80def raw(name, arguments, options, content, lineno,
81        content_offset, block_text, state, state_machine):
82    """
83    Pass through content unchanged
84
85    Content is included in output based on type argument
86
87    Content may be included inline (content section of directive) or
88    imported from a file or url.
89    """
90    if ( not state.document.settings.raw_enabled
91         or (not state.document.settings.file_insertion_enabled
92             and (options.has_key('file') or options.has_key('url'))) ):
93        warning = state_machine.reporter.warning(
94              '"%s" directive disabled.' % name,
95              nodes.literal_block(block_text, block_text), line=lineno)
96        return [warning]
97    attributes = {'format': ' '.join(arguments[0].lower().split())}
98    encoding = options.get('encoding', state.document.settings.input_encoding)
99    if content:
100        if options.has_key('file') or options.has_key('url'):
101            error = state_machine.reporter.error(
102                  '"%s" directive may not both specify an external file and '
103                  'have content.' % name,
104                  nodes.literal_block(block_text, block_text), line=lineno)
105            return [error]
106        text = '\n'.join(content)
107    elif options.has_key('file'):
108        if options.has_key('url'):
109            error = state_machine.reporter.error(
110                  'The "file" and "url" options may not be simultaneously '
111                  'specified for the "%s" directive.' % name,
112                  nodes.literal_block(block_text, block_text), line=lineno)
113            return [error]
114        source_dir = os.path.dirname(
115            os.path.abspath(state.document.current_source))
116        path = os.path.normpath(os.path.join(source_dir, options['file']))
117        path = utils.relative_path(None, path)
118        try:
119            state.document.settings.record_dependencies.add(path)
120            raw_file = io.FileInput(
121                source_path=path, encoding=encoding,
122                error_handler=state.document.settings.input_encoding_error_handler,
123                handle_io_errors=None)
124        except IOError, error:
125            severe = state_machine.reporter.severe(
126                  'Problems with "%s" directive path:\n%s.' % (name, error),
127                  nodes.literal_block(block_text, block_text), line=lineno)
128            return [severe]
129        try:
130            text = raw_file.read()
131        except UnicodeError, error:
132            severe = state_machine.reporter.severe(
133                  'Problem with "%s" directive:\n%s: %s'
134                  % (name, error.__class__.__name__, error),
135                  nodes.literal_block(block_text, block_text), line=lineno)
136            return [severe]
137        attributes['source'] = path
138    elif options.has_key('url'):
139        if not urllib2:
140            severe = state_machine.reporter.severe(
141                  'Problems with the "%s" directive and its "url" option: '
142                  'unable to access the required functionality (from the '
143                  '"urllib2" module).' % name,
144                  nodes.literal_block(block_text, block_text), line=lineno)
145            return [severe]
146        source = options['url']
147        try:
148            raw_text = urllib2.urlopen(source).read()
149        except (urllib2.URLError, IOError, OSError), error:
150            severe = state_machine.reporter.severe(
151                  'Problems with "%s" directive URL "%s":\n%s.'
152                  % (name, options['url'], error),
153                  nodes.literal_block(block_text, block_text), line=lineno)
154            return [severe]
155        raw_file = io.StringInput(
156            source=raw_text, source_path=source, encoding=encoding,
157            error_handler=state.document.settings.input_encoding_error_handler)
158        try:
159            text = raw_file.read()
160        except UnicodeError, error:
161            severe = state_machine.reporter.severe(
162                  'Problem with "%s" directive:\n%s: %s'
163                  % (name, error.__class__.__name__, error),
164                  nodes.literal_block(block_text, block_text), line=lineno)
165            return [severe]
166        attributes['source'] = source
167    else:
168        error = state_machine.reporter.warning(
169            'The "%s" directive requires content; none supplied.' % (name),
170            nodes.literal_block(block_text, block_text), line=lineno)
171        return [error]
172    raw_node = nodes.raw('', text, **attributes)
173    return [raw_node]
174
175raw.arguments = (1, 0, 1)
176raw.options = {'file': directives.path,
177               'url': directives.uri,
178               'encoding': directives.encoding}
179raw.content = 1
180
181def replace(name, arguments, options, content, lineno,
182            content_offset, block_text, state, state_machine):
183    if not isinstance(state, states.SubstitutionDef):
184        error = state_machine.reporter.error(
185            'Invalid context: the "%s" directive can only be used within a '
186            'substitution definition.' % (name),
187            nodes.literal_block(block_text, block_text), line=lineno)
188        return [error]
189    text = '\n'.join(content)
190    element = nodes.Element(text)
191    if text:
192        state.nested_parse(content, content_offset, element)
193        if len(element) != 1 or not isinstance(element[0], nodes.paragraph):
194            messages = []
195            for node in element:
196                if isinstance(node, nodes.system_message):
197                    node['backrefs'] = []
198                    messages.append(node)
199            error = state_machine.reporter.error(
200                'Error in "%s" directive: may contain a single paragraph '
201                'only.' % (name), line=lineno)
202            messages.append(error)
203            return messages
204        else:
205            return element[0].children
206    else:
207        error = state_machine.reporter.error(
208            'The "%s" directive is empty; content required.' % (name),
209            line=lineno)
210        return [error]
211
212replace.content = 1
213
214def unicode_directive(name, arguments, options, content, lineno,
215                      content_offset, block_text, state, state_machine):
216    r"""
217    Convert Unicode character codes (numbers) to characters.  Codes may be
218    decimal numbers, hexadecimal numbers (prefixed by ``0x``, ``x``, ``\x``,
219    ``U+``, ``u``, or ``\u``; e.g. ``U+262E``), or XML-style numeric character
220    entities (e.g. ``&#x262E;``).  Text following ".." is a comment and is
221    ignored.  Spaces are ignored, and any other text remains as-is.
222    """
223    if not isinstance(state, states.SubstitutionDef):
224        error = state_machine.reporter.error(
225            'Invalid context: the "%s" directive can only be used within a '
226            'substitution definition.' % (name),
227            nodes.literal_block(block_text, block_text), line=lineno)
228        return [error]
229    substitution_definition = state_machine.node
230    if options.has_key('trim'):
231        substitution_definition.attributes['ltrim'] = 1
232        substitution_definition.attributes['rtrim'] = 1
233    if options.has_key('ltrim'):
234        substitution_definition.attributes['ltrim'] = 1
235    if options.has_key('rtrim'):
236        substitution_definition.attributes['rtrim'] = 1
237    codes = unicode_comment_pattern.split(arguments[0])[0].split()
238    element = nodes.Element()
239    for code in codes:
240        try:
241            decoded = directives.unicode_code(code)
242        except ValueError, err:
243            error = state_machine.reporter.error(
244                'Invalid character code: %s\n%s: %s'
245                % (code, err.__class__.__name__, err),
246                nodes.literal_block(block_text, block_text), line=lineno)
247            return [error]
248        element += nodes.Text(decoded)
249    return element.children
250
251unicode_directive.arguments = (1, 0, 1)
252unicode_directive.options = {'trim': directives.flag,
253                             'ltrim': directives.flag,
254                             'rtrim': directives.flag}
255unicode_comment_pattern = re.compile(r'( |\n|^)\.\. ')
256
257def class_directive(name, arguments, options, content, lineno,
258                       content_offset, block_text, state, state_machine):
259    """
260    Set a "class" attribute on the directive content or the next element.
261    When applied to the next element, a "pending" element is inserted, and a
262    transform does the work later.
263    """
264    try:
265        class_value = directives.class_option(arguments[0])
266    except ValueError:
267        error = state_machine.reporter.error(
268            'Invalid class attribute value for "%s" directive: "%s".'
269            % (name, arguments[0]),
270            nodes.literal_block(block_text, block_text), line=lineno)
271        return [error]
272    node_list = []
273    if content:
274        container = nodes.Element()
275        state.nested_parse(content, content_offset, container)
276        for node in container:
277            node['classes'].extend(class_value)
278        node_list.extend(container.children)
279    else:
280        pending = nodes.pending(misc.ClassAttribute,
281                                {'class': class_value, 'directive': name},
282                                block_text)
283        state_machine.document.note_pending(pending)
284        node_list.append(pending)
285    return node_list
286
287class_directive.arguments = (1, 0, 1)
288class_directive.content = 1
289
290role_arg_pat = re.compile(r'(%s)\s*(\(\s*(%s)\s*\)\s*)?$'
291                          % ((states.Inliner.simplename,) * 2))
292def role(name, arguments, options, content, lineno,
293         content_offset, block_text, state, state_machine):
294    """Dynamically create and register a custom interpreted text role."""
295    if content_offset > lineno or not content:
296        error = state_machine.reporter.error(
297            '"%s" directive requires arguments on the first line.'
298            % name, nodes.literal_block(block_text, block_text), line=lineno)
299        return [error]
300    args = content[0]
301    match = role_arg_pat.match(args)
302    if not match:
303        error = state_machine.reporter.error(
304            '"%s" directive arguments not valid role names: "%s".'
305            % (name, args), nodes.literal_block(block_text, block_text),
306            line=lineno)
307        return [error]
308    new_role_name = match.group(1)
309    base_role_name = match.group(3)
310    messages = []
311    if base_role_name:
312        base_role, messages = roles.role(
313            base_role_name, state_machine.language, lineno, state.reporter)
314        if base_role is None:
315            error = state.reporter.error(
316                'Unknown interpreted text role "%s".' % base_role_name,
317                nodes.literal_block(block_text, block_text), line=lineno)
318            return messages + [error]
319    else:
320        base_role = roles.generic_custom_role
321    assert not hasattr(base_role, 'arguments'), (
322        'Supplemental directive arguments for "%s" directive not supported'
323        '(specified by "%r" role).' % (name, base_role))
324    try:
325        (arguments, options, content, content_offset) = (
326            state.parse_directive_block(content[1:], content_offset, base_role,
327                                        option_presets={}))
328    except states.MarkupError, detail:
329        error = state_machine.reporter.error(
330            'Error in "%s" directive:\n%s.' % (name, detail),
331            nodes.literal_block(block_text, block_text), line=lineno)
332        return messages + [error]
333    if not options.has_key('class'):
334        try:
335            options['class'] = directives.class_option(new_role_name)
336        except ValueError, detail:
337            error = state_machine.reporter.error(
338                'Invalid argument for "%s" directive:\n%s.'
339                % (name, detail),
340                nodes.literal_block(block_text, block_text), line=lineno)
341            return messages + [error]
342    role = roles.CustomRole(new_role_name, base_role, options, content)
343    roles.register_local_role(new_role_name, role)
344    return messages
345
346role.content = 1
347
348def default_role(name, arguments, options, content, lineno,
349                 content_offset, block_text, state, state_machine):
350    """Set the default interpreted text role."""
351    if not arguments:
352        if roles._roles.has_key(''):
353            # restore the "default" default role
354            del roles._roles['']
355        return []
356    role_name = arguments[0]
357    role, messages = roles.role(
358        role_name, state_machine.language, lineno, state.reporter)
359    if role is None:
360        error = state.reporter.error(
361            'Unknown interpreted text role "%s".' % role_name,
362            nodes.literal_block(block_text, block_text), line=lineno)
363        return messages + [error]
364    roles._roles[''] = role
365    # @@@ should this be local to the document, not the parser?
366    return messages
367
368default_role.arguments = (0, 1, 0)
369
370def title(name, arguments, options, content, lineno,
371          content_offset, block_text, state, state_machine):
372    state_machine.document['title'] = arguments[0]
373    return []
374
375title.arguments = (1, 0, 1)
376
377def date(name, arguments, options, content, lineno,
378         content_offset, block_text, state, state_machine):
379    if not isinstance(state, states.SubstitutionDef):
380        error = state_machine.reporter.error(
381            'Invalid context: the "%s" directive can only be used within a '
382            'substitution definition.' % (name),
383            nodes.literal_block(block_text, block_text), line=lineno)
384        return [error]
385    format = '\n'.join(content) or '%Y-%m-%d'
386    text = time.strftime(format)
387    return [nodes.Text(text)]
388
389date.content = 1
390
391def directive_test_function(name, arguments, options, content, lineno,
392                            content_offset, block_text, state, state_machine):
393    """This directive is useful only for testing purposes."""
394    if content:
395        text = '\n'.join(content)
396        info = state_machine.reporter.info(
397            'Directive processed. Type="%s", arguments=%r, options=%r, '
398            'content:' % (name, arguments, options),
399            nodes.literal_block(text, text), line=lineno)
400    else:
401        info = state_machine.reporter.info(
402            'Directive processed. Type="%s", arguments=%r, options=%r, '
403            'content: None' % (name, arguments, options), line=lineno)
404    return [info]
405
406directive_test_function.arguments = (0, 1, 1)
407directive_test_function.options = {'option': directives.unchanged_required}
408directive_test_function.content = 1
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。