root/galaxy-central/eggs/Mako-0.2.5-py2.6.egg/mako/parsetree.py @ 3

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

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

行番号 
1# parsetree.py
2# Copyright (C) 2006, 2007, 2008, 2009 Michael Bayer mike_mp@zzzcomputing.com
3#
4# This module is part of Mako and is released under
5# the MIT License: http://www.opensource.org/licenses/mit-license.php
6
7"""defines the parse tree components for Mako templates."""
8
9from mako import exceptions, ast, util, filters
10import re
11
12class Node(object):
13    """base class for a Node in the parse tree."""
14    def __init__(self, source, lineno, pos, filename):
15        self.source = source
16        self.lineno = lineno
17        self.pos = pos
18        self.filename = filename
19   
20    def exception_kwargs(self):
21        return {'source':self.source, 'lineno':self.lineno, 'pos':self.pos, 'filename':self.filename}
22    exception_kwargs = property(exception_kwargs)
23   
24    def get_children(self):
25        return []
26       
27    def accept_visitor(self, visitor):
28        def traverse(node):
29            for n in node.get_children():
30                n.accept_visitor(visitor)
31        method = getattr(visitor, "visit" + self.__class__.__name__, traverse)
32        method(self)
33
34class TemplateNode(Node):
35    """a 'container' node that stores the overall collection of nodes."""
36   
37    def __init__(self, filename):
38        super(TemplateNode, self).__init__('', 0, 0, filename)
39        self.nodes = []
40        self.page_attributes = {}
41       
42    def get_children(self):
43        return self.nodes
44       
45    def __repr__(self):
46        return "TemplateNode(%s, %r)" % (util.sorted_dict_repr(self.page_attributes), self.nodes)
47       
48class ControlLine(Node):
49    """defines a control line, a line-oriented python line or end tag.
50   
51    e.g.::
52
53        % if foo:
54            (markup)
55        % endif
56   
57    """
58
59    def __init__(self, keyword, isend, text, **kwargs):
60        super(ControlLine, self).__init__(**kwargs)
61        self.text = text
62        self.keyword = keyword
63        self.isend = isend
64        self.is_primary = keyword in ['for','if', 'while', 'try']
65        if self.isend:
66            self._declared_identifiers = []
67            self._undeclared_identifiers = []
68        else:
69            code = ast.PythonFragment(text, **self.exception_kwargs)
70            self._declared_identifiers = code.declared_identifiers
71            self._undeclared_identifiers = code.undeclared_identifiers
72
73    def declared_identifiers(self):
74        return self._declared_identifiers
75
76    def undeclared_identifiers(self):
77        return self._undeclared_identifiers
78       
79    def is_ternary(self, keyword):
80        """return true if the given keyword is a ternary keyword for this ControlLine"""
81       
82        return keyword in {
83            'if':util.Set(['else', 'elif']),
84            'try':util.Set(['except', 'finally']),
85            'for':util.Set(['else'])
86        }.get(self.keyword, [])
87       
88    def __repr__(self):
89        return "ControlLine(%r, %r, %r, %r)" % (
90            self.keyword,
91            self.text,
92            self.isend,
93            (self.lineno, self.pos)
94        )
95
96class Text(Node):
97    """defines plain text in the template."""
98   
99    def __init__(self, content, **kwargs):
100        super(Text, self).__init__(**kwargs)
101        self.content = content
102       
103    def __repr__(self):
104        return "Text(%r, %r)" % (self.content, (self.lineno, self.pos))
105       
106class Code(Node):
107    """defines a Python code block, either inline or module level.
108   
109    e.g.::
110
111        inline:
112        <%
113            x = 12
114        %>
115   
116        module level:
117        <%!
118            import logger
119        %>
120   
121    """
122
123    def __init__(self, text, ismodule, **kwargs):
124        super(Code, self).__init__(**kwargs)
125        self.text = text
126        self.ismodule = ismodule
127        self.code = ast.PythonCode(text, **self.exception_kwargs)
128
129    def declared_identifiers(self):
130        return self.code.declared_identifiers
131
132    def undeclared_identifiers(self):
133        return self.code.undeclared_identifiers
134
135    def __repr__(self):
136        return "Code(%r, %r, %r)" % (
137            self.text,
138            self.ismodule,
139            (self.lineno, self.pos)
140        )
141       
142class Comment(Node):
143    """defines a comment line.
144   
145    # this is a comment
146   
147    """
148   
149    def __init__(self, text, **kwargs):
150        super(Comment, self).__init__(**kwargs)
151        self.text = text
152
153    def __repr__(self):
154        return "Comment(%r, %r)" % (self.text, (self.lineno, self.pos))
155       
156class Expression(Node):
157    """defines an inline expression.
158   
159    ${x+y}
160   
161    """
162   
163    def __init__(self, text, escapes, **kwargs):
164        super(Expression, self).__init__(**kwargs)
165        self.text = text
166        self.escapes = escapes
167        self.escapes_code = ast.ArgumentList(escapes, **self.exception_kwargs)
168        self.code = ast.PythonCode(text, **self.exception_kwargs)
169
170    def declared_identifiers(self):
171        return []
172
173    def undeclared_identifiers(self):
174        # TODO: make the "filter" shortcut list configurable at parse/gen time
175        return self.code.undeclared_identifiers.union(
176                self.escapes_code.undeclared_identifiers.difference(
177                    util.Set(filters.DEFAULT_ESCAPES.keys())
178                )
179            )
180
181    def __repr__(self):
182        return "Expression(%r, %r, %r)" % (
183            self.text,
184            self.escapes_code.args,
185            (self.lineno, self.pos)
186        )
187       
188class _TagMeta(type):
189    """metaclass to allow Tag to produce a subclass according to its keyword"""
190   
191    _classmap = {}
192   
193    def __init__(cls, clsname, bases, dict):
194        if cls.__keyword__ is not None:
195            cls._classmap[cls.__keyword__] = cls
196            super(_TagMeta, cls).__init__(clsname, bases, dict)
197           
198    def __call__(cls, keyword, attributes, **kwargs):
199        if ":" in keyword:
200            ns, defname = keyword.split(':')
201            return type.__call__(CallNamespaceTag, ns, defname, attributes, **kwargs)
202
203        try:
204            cls = _TagMeta._classmap[keyword]
205        except KeyError:
206            raise exceptions.CompileException(
207                "No such tag: '%s'" % keyword,
208                source=kwargs['source'],
209                lineno=kwargs['lineno'],
210                pos=kwargs['pos'],
211                filename=kwargs['filename']
212            )
213        return type.__call__(cls, keyword, attributes, **kwargs)
214       
215class Tag(Node):
216    """abstract base class for tags.
217   
218    <%sometag/>
219   
220    <%someothertag>
221        stuff
222    </%someothertag>
223   
224    """
225   
226    __metaclass__ = _TagMeta
227    __keyword__ = None
228   
229    def __init__(self, keyword, attributes, expressions, nonexpressions, required, **kwargs):
230        """construct a new Tag instance.
231       
232        this constructor not called directly, and is only called by subclasses.
233       
234        keyword - the tag keyword
235       
236        attributes - raw dictionary of attribute key/value pairs
237       
238        expressions - a util.Set of identifiers that are legal attributes, which can also contain embedded expressions
239       
240        nonexpressions - a util.Set of identifiers that are legal attributes, which cannot contain embedded expressions
241       
242        **kwargs - other arguments passed to the Node superclass (lineno, pos)
243       
244        """
245        super(Tag, self).__init__(**kwargs)
246        self.keyword = keyword
247        self.attributes = attributes
248        self._parse_attributes(expressions, nonexpressions)
249        missing = [r for r in required if r not in self.parsed_attributes]
250        if len(missing):
251            raise exceptions.CompileException(
252                "Missing attribute(s): %s" % ",".join([repr(m) for m in missing]),
253                **self.exception_kwargs)
254        self.parent = None
255        self.nodes = []
256       
257    def is_root(self):
258        return self.parent is None
259       
260    def get_children(self):
261        return self.nodes
262       
263    def _parse_attributes(self, expressions, nonexpressions):
264        undeclared_identifiers = util.Set()
265        self.parsed_attributes = {}
266        for key in self.attributes:
267            if key in expressions:
268                expr = []
269                for x in re.split(r'(\${.+?})', self.attributes[key]):
270                    m = re.match(r'^\${(.+?)}$', x)
271                    if m:
272                        code = ast.PythonCode(m.group(1), **self.exception_kwargs)
273                        undeclared_identifiers = undeclared_identifiers.union(code.undeclared_identifiers)
274                        expr.append("(%s)" % m.group(1))
275                    else:
276                        if x:
277                            expr.append(repr(x))
278                self.parsed_attributes[key] = " + ".join(expr) or repr('')
279            elif key in nonexpressions:
280                if re.search(r'${.+?}', self.attributes[key]):
281                    raise exceptions.CompileException(
282                            "Attibute '%s' in tag '%s' does not allow embedded expressions"  % (key, self.keyword),
283                            **self.exception_kwargs)
284                self.parsed_attributes[key] = repr(self.attributes[key])
285            else:
286                raise exceptions.CompileException("Invalid attribute for tag '%s': '%s'" %(self.keyword, key), **self.exception_kwargs)
287        self.expression_undeclared_identifiers = undeclared_identifiers
288
289    def declared_identifiers(self):
290        return []
291
292    def undeclared_identifiers(self):
293        return self.expression_undeclared_identifiers
294
295    def __repr__(self):
296        return "%s(%r, %s, %r, %r)" % (self.__class__.__name__,
297                                        self.keyword,
298                                        util.sorted_dict_repr(self.attributes),
299                                        (self.lineno, self.pos),
300                                        [repr(x) for x in self.nodes]
301                                    )
302       
303class IncludeTag(Tag):
304    __keyword__ = 'include'
305
306    def __init__(self, keyword, attributes, **kwargs):
307        super(IncludeTag, self).__init__(keyword, attributes, ('file', 'import', 'args'), (), ('file',), **kwargs)
308        self.page_args = ast.PythonCode("__DUMMY(%s)" % attributes.get('args', ''), **self.exception_kwargs)
309
310    def declared_identifiers(self):
311        return []
312
313    def undeclared_identifiers(self):
314        identifiers = self.page_args.undeclared_identifiers.difference(util.Set(["__DUMMY"]))
315        return identifiers.union(super(IncludeTag, self).undeclared_identifiers())
316   
317class NamespaceTag(Tag):
318    __keyword__ = 'namespace'
319
320    def __init__(self, keyword, attributes, **kwargs):
321        super(NamespaceTag, self).__init__(keyword, attributes, (), ('name','inheritable','file','import','module'), (), **kwargs)
322        self.name = attributes.get('name', '__anon_%s' % hex(abs(id(self))))
323        if not 'name' in attributes and not 'import' in attributes:
324            raise exceptions.CompileException("'name' and/or 'import' attributes are required for <%namespace>", **self.exception_kwargs)
325
326    def declared_identifiers(self):
327        return []
328
329class TextTag(Tag):
330    __keyword__ = 'text'
331
332    def __init__(self, keyword, attributes, **kwargs):
333        super(TextTag, self).__init__(keyword, attributes, (), ('filter'), (), **kwargs)
334        self.filter_args = ast.ArgumentList(attributes.get('filter', ''), **self.exception_kwargs)
335       
336class DefTag(Tag):
337    __keyword__ = 'def'
338
339    def __init__(self, keyword, attributes, **kwargs):
340        super(DefTag, self).__init__(
341                keyword,
342                attributes,
343                ('buffered', 'cached', 'cache_key', 'cache_timeout', 'cache_type', 'cache_dir', 'cache_url'),
344                ('name','filter', 'decorator'),
345                ('name',),
346                **kwargs)
347        name = attributes['name']
348        if re.match(r'^[\w_]+$',name):
349            raise exceptions.CompileException("Missing parenthesis in %def", **self.exception_kwargs)
350        self.function_decl = ast.FunctionDecl("def " + name + ":pass", **self.exception_kwargs)
351        self.name = self.function_decl.funcname
352        self.decorator = attributes.get('decorator', '')
353        self.filter_args = ast.ArgumentList(attributes.get('filter', ''), **self.exception_kwargs)
354
355    def declared_identifiers(self):
356        return self.function_decl.argnames
357
358    def undeclared_identifiers(self):
359        res = []
360        for c in self.function_decl.defaults:
361            res += list(ast.PythonCode(c, **self.exception_kwargs).undeclared_identifiers)
362        return res + list(self.filter_args.undeclared_identifiers.difference(util.Set(filters.DEFAULT_ESCAPES.keys())))
363
364class CallTag(Tag):
365    __keyword__ = 'call'
366
367    def __init__(self, keyword, attributes, **kwargs):
368        super(CallTag, self).__init__(keyword, attributes, ('args'), ('expr',), ('expr',), **kwargs)
369        self.expression = attributes['expr']
370        self.code = ast.PythonCode(self.expression, **self.exception_kwargs)
371        self.body_decl = ast.FunctionArgs(attributes.get('args', ''), **self.exception_kwargs)
372
373    def declared_identifiers(self):
374        return self.code.declared_identifiers.union(self.body_decl.argnames)
375
376    def undeclared_identifiers(self):
377        return self.code.undeclared_identifiers
378
379class CallNamespaceTag(Tag):
380
381    def __init__(self, namespace, defname, attributes, **kwargs):
382        super(CallNamespaceTag, self).__init__(
383                    namespace + ":" + defname,
384                    attributes,
385                    tuple(attributes.keys()) + ('args', ),
386                    (),
387                    (),
388                    **kwargs)
389        self.expression = "%s.%s(%s)" % (namespace, defname, ",".join(["%s=%s" % (k, v) for k, v in self.parsed_attributes.iteritems() if k != 'args']))
390        self.code = ast.PythonCode(self.expression, **self.exception_kwargs)
391        self.body_decl = ast.FunctionArgs(attributes.get('args', ''), **self.exception_kwargs)
392
393    def declared_identifiers(self):
394        return self.code.declared_identifiers.union(self.body_decl.argnames)
395
396    def undeclared_identifiers(self):
397        return self.code.undeclared_identifiers
398
399class InheritTag(Tag):
400    __keyword__ = 'inherit'
401
402    def __init__(self, keyword, attributes, **kwargs):
403        super(InheritTag, self).__init__(keyword, attributes, ('file',), (), ('file',), **kwargs)
404
405class PageTag(Tag):
406    __keyword__ = 'page'
407
408    def __init__(self, keyword, attributes, **kwargs):
409        super(PageTag, self).__init__(
410                keyword,
411                attributes,
412                ('cached', 'cache_key', 'cache_timeout', 'cache_type', 'cache_dir', 'cache_url', 'args', 'expression_filter'),
413                (),
414                (),
415                **kwargs)
416        self.body_decl = ast.FunctionArgs(attributes.get('args', ''), **self.exception_kwargs)
417        self.filter_args = ast.ArgumentList(attributes.get('expression_filter', ''), **self.exception_kwargs)
418
419    def declared_identifiers(self):
420        return self.body_decl.argnames
421       
422   
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。