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

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

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

行番号 
1# Author: Edward Loper
2# Contact: edloper@gradient.cis.upenn.edu
3# Revision: $Revision: 3155 $
4# Date: $Date: 2005-04-02 23:57:06 +0200 (Sat, 02 Apr 2005) $
5# Copyright: This module has been placed in the public domain.
6
7"""
8This module defines standard interpreted text role functions, a registry for
9interpreted text roles, and an API for adding to and retrieving from the
10registry.
11
12The interface for interpreted role functions is as follows::
13
14    def role_fn(name, rawtext, text, lineno, inliner,
15                options={}, content=[]):
16        code...
17
18    # Set function attributes for customization:
19    role_fn.options = ...
20    role_fn.content = ...
21
22Parameters:
23
24- ``name`` is the local name of the interpreted text role, the role name
25  actually used in the document.
26
27- ``rawtext`` is a string containing the entire interpreted text construct.
28  Return it as a ``problematic`` node linked to a system message if there is a
29  problem.
30
31- ``text`` is the interpreted text content, with backslash escapes converted
32  to nulls (``\x00``).
33
34- ``lineno`` is the line number where the interpreted text beings.
35
36- ``inliner`` is the Inliner object that called the role function.
37  It defines the following useful attributes: ``reporter``,
38  ``problematic``, ``memo``, ``parent``, ``document``.
39
40- ``options``: A dictionary of directive options for customization, to be
41  interpreted by the role function.  Used for additional attributes for the
42  generated elements and other functionality.
43
44- ``content``: A list of strings, the directive content for customization
45  ("role" directive).  To be interpreted by the role function.
46
47Function attributes for customization, interpreted by the "role" directive:
48
49- ``options``: A dictionary, mapping known option names to conversion
50  functions such as `int` or `float`.  ``None`` or an empty dict implies no
51  options to parse.  Several directive option conversion functions are defined
52  in the `directives` module.
53
54  All role functions implicitly support the "class" option, unless disabled
55  with an explicit ``{'class': None}``.
56
57- ``content``: A boolean; true if content is allowed.  Client code must handle
58  the case where content is required but not supplied (an empty content list
59  will be supplied).
60
61Note that unlike directives, the "arguments" function attribute is not
62supported for role customization.  Directive arguments are handled by the
63"role" directive itself.
64
65Interpreted role functions return a tuple of two values:
66
67- A list of nodes which will be inserted into the document tree at the
68  point where the interpreted role was encountered (can be an empty
69  list).
70
71- A list of system messages, which will be inserted into the document tree
72  immediately after the end of the current inline block (can also be empty).
73"""
74
75__docformat__ = 'reStructuredText'
76
77from docutils import nodes, utils
78from docutils.parsers.rst import directives
79from docutils.parsers.rst.languages import en as _fallback_language_module
80
81DEFAULT_INTERPRETED_ROLE = 'title-reference'
82"""
83The canonical name of the default interpreted role.  This role is used
84when no role is specified for a piece of interpreted text.
85"""
86
87_role_registry = {}
88"""Mapping of canonical role names to role functions.  Language-dependent role
89names are defined in the ``language`` subpackage."""
90
91_roles = {}
92"""Mapping of local or language-dependent interpreted text role names to role
93functions."""
94
95def role(role_name, language_module, lineno, reporter):
96    """
97    Locate and return a role function from its language-dependent name, along
98    with a list of system messages.  If the role is not found in the current
99    language, check English.  Return a 2-tuple: role function (``None`` if the
100    named role cannot be found) and a list of system messages.
101    """
102    normname = role_name.lower()
103    messages = []
104    msg_text = []
105
106    if _roles.has_key(normname):
107        return _roles[normname], messages
108
109    if role_name:
110        canonicalname = None
111        try:
112            canonicalname = language_module.roles[normname]
113        except AttributeError, error:
114            msg_text.append('Problem retrieving role entry from language '
115                            'module %r: %s.' % (language_module, error))
116        except KeyError:
117            msg_text.append('No role entry for "%s" in module "%s".'
118                            % (role_name, language_module.__name__))
119    else:
120        canonicalname = DEFAULT_INTERPRETED_ROLE
121
122    # If we didn't find it, try English as a fallback.
123    if not canonicalname:
124        try:
125            canonicalname = _fallback_language_module.roles[normname]
126            msg_text.append('Using English fallback for role "%s".'
127                            % role_name)
128        except KeyError:
129            msg_text.append('Trying "%s" as canonical role name.'
130                            % role_name)
131            # The canonical name should be an English name, but just in case:
132            canonicalname = normname
133
134    # Collect any messages that we generated.
135    if msg_text:
136        message = reporter.info('\n'.join(msg_text), line=lineno)
137        messages.append(message)
138
139    # Look the role up in the registry, and return it.
140    if _role_registry.has_key(canonicalname):
141        role_fn = _role_registry[canonicalname]
142        register_local_role(normname, role_fn)
143        return role_fn, messages
144    else:
145        return None, messages # Error message will be generated by caller.
146
147def register_canonical_role(name, role_fn):
148    """
149    Register an interpreted text role by its canonical name.
150
151    :Parameters:
152      - `name`: The canonical name of the interpreted role.
153      - `role_fn`: The role function.  See the module docstring.
154    """
155    set_implicit_options(role_fn)
156    _role_registry[name] = role_fn
157
158def register_local_role(name, role_fn):
159    """
160    Register an interpreted text role by its local or language-dependent name.
161
162    :Parameters:
163      - `name`: The local or language-dependent name of the interpreted role.
164      - `role_fn`: The role function.  See the module docstring.
165    """
166    set_implicit_options(role_fn)
167    _roles[name] = role_fn
168
169def set_implicit_options(role_fn):
170    """
171    Add customization options to role functions, unless explicitly set or
172    disabled.
173    """
174    if not hasattr(role_fn, 'options') or role_fn.options is None:
175        role_fn.options = {'class': directives.class_option}
176    elif not role_fn.options.has_key('class'):
177        role_fn.options['class'] = directives.class_option
178
179def register_generic_role(canonical_name, node_class):
180    """For roles which simply wrap a given `node_class` around the text."""
181    role = GenericRole(canonical_name, node_class)
182    register_canonical_role(canonical_name, role)
183
184
185class GenericRole:
186
187    """
188    Generic interpreted text role, where the interpreted text is simply
189    wrapped with the provided node class.
190    """
191
192    def __init__(self, role_name, node_class):
193        self.name = role_name
194        self.node_class = node_class
195
196    def __call__(self, role, rawtext, text, lineno, inliner,
197                 options={}, content=[]):
198        set_classes(options)
199        return [self.node_class(rawtext, utils.unescape(text), **options)], []
200
201
202class CustomRole:
203
204    """
205    Wrapper for custom interpreted text roles.
206    """
207
208    def __init__(self, role_name, base_role, options={}, content=[]):
209        self.name = role_name
210        self.base_role = base_role
211        self.options = None
212        if hasattr(base_role, 'options'):
213            self.options = base_role.options
214        self.content = None
215        if hasattr(base_role, 'content'):
216            self.content = base_role.content
217        self.supplied_options = options
218        self.supplied_content = content
219
220    def __call__(self, role, rawtext, text, lineno, inliner,
221                 options={}, content=[]):
222        opts = self.supplied_options.copy()
223        opts.update(options)
224        cont = list(self.supplied_content)
225        if cont and content:
226            cont += '\n'
227        cont.extend(content)
228        return self.base_role(role, rawtext, text, lineno, inliner,
229                              options=opts, content=cont)
230
231
232def generic_custom_role(role, rawtext, text, lineno, inliner,
233                        options={}, content=[]):
234    """"""
235    # Once nested inline markup is implemented, this and other methods should
236    # recursively call inliner.nested_parse().
237    set_classes(options)
238    return [nodes.inline(rawtext, utils.unescape(text), **options)], []
239
240generic_custom_role.options = {'class': directives.class_option}
241
242
243######################################################################
244# Define and register the standard roles:
245######################################################################
246
247register_generic_role('abbreviation', nodes.abbreviation)
248register_generic_role('acronym', nodes.acronym)
249register_generic_role('emphasis', nodes.emphasis)
250register_generic_role('literal', nodes.literal)
251register_generic_role('strong', nodes.strong)
252register_generic_role('subscript', nodes.subscript)
253register_generic_role('superscript', nodes.superscript)
254register_generic_role('title-reference', nodes.title_reference)
255
256def pep_reference_role(role, rawtext, text, lineno, inliner,
257                       options={}, content=[]):
258    try:
259        pepnum = int(text)
260        if pepnum < 0 or pepnum > 9999:
261            raise ValueError
262    except ValueError:
263        msg = inliner.reporter.error(
264            'PEP number must be a number from 0 to 9999; "%s" is invalid.'
265            % text, line=lineno)
266        prb = inliner.problematic(rawtext, rawtext, msg)
267        return [prb], [msg]
268    # Base URL mainly used by inliner.pep_reference; so this is correct:
269    ref = inliner.document.settings.pep_base_url + inliner.pep_url % pepnum
270    set_classes(options)
271    return [nodes.reference(rawtext, 'PEP ' + utils.unescape(text), refuri=ref,
272                            **options)], []
273
274register_canonical_role('pep-reference', pep_reference_role)
275
276def rfc_reference_role(role, rawtext, text, lineno, inliner,
277                       options={}, content=[]):
278    try:
279        rfcnum = int(text)
280        if rfcnum <= 0:
281            raise ValueError
282    except ValueError:
283        msg = inliner.reporter.error(
284            'RFC number must be a number greater than or equal to 1; '
285            '"%s" is invalid.' % text, line=lineno)
286        prb = inliner.problematic(rawtext, rawtext, msg)
287        return [prb], [msg]
288    # Base URL mainly used by inliner.rfc_reference, so this is correct:
289    ref = inliner.document.settings.rfc_base_url + inliner.rfc_url % rfcnum
290    set_classes(options)
291    node = nodes.reference(rawtext, 'RFC ' + utils.unescape(text), refuri=ref,
292                           **options)
293    return [node], []
294
295register_canonical_role('rfc-reference', rfc_reference_role)
296
297def raw_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
298    if not options.has_key('format'):
299        msg = inliner.reporter.error(
300            'No format (Writer name) is associated with this role: "%s".\n'
301            'The "raw" role cannot be used directly.\n'
302            'Instead, use the "role" directive to create a new role with '
303            'an associated format.' % role, line=lineno)
304        prb = inliner.problematic(rawtext, rawtext, msg)
305        return [prb], [msg]
306    set_classes(options)
307    node = nodes.raw(rawtext, utils.unescape(text, 1), **options)
308    return [node], []
309
310raw_role.options = {'format': directives.unchanged}
311
312register_canonical_role('raw', raw_role)
313
314
315######################################################################
316# Register roles that are currently unimplemented.
317######################################################################
318
319def unimplemented_role(role, rawtext, text, lineno, inliner, attributes={}):
320    msg = inliner.reporter.error(
321        'Interpreted text role "%s" not implemented.' % role, line=lineno)
322    prb = inliner.problematic(rawtext, rawtext, msg)
323    return [prb], [msg]
324
325register_canonical_role('index', unimplemented_role)
326register_canonical_role('named-reference', unimplemented_role)
327register_canonical_role('anonymous-reference', unimplemented_role)
328register_canonical_role('uri-reference', unimplemented_role)
329register_canonical_role('footnote-reference', unimplemented_role)
330register_canonical_role('citation-reference', unimplemented_role)
331register_canonical_role('substitution-reference', unimplemented_role)
332register_canonical_role('target', unimplemented_role)
333
334# This should remain unimplemented, for testing purposes:
335register_canonical_role('restructuredtext-unimplemented-role',
336                        unimplemented_role)
337
338
339def set_classes(options):
340    """
341    Auxiliary function to set options['classes'] and delete
342    options['class'].
343    """
344    if options.has_key('class'):
345        assert not options.has_key('classes')
346        options['classes'] = options['class']
347        del options['class']
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。