Edgewall Software

Ticket #295: eval.patch

File eval.patch, 9.1 KB (added by Christoph Zwerschke <cito@…>, 6 years ago)

Patch for genshi.template.base

  • base.py

     
    3636 
    3737    def __init__(self, message, filename=None, lineno=-1, offset=-1): 
    3838        """Create the exception. 
    39          
     39 
    4040        :param message: the error message 
    4141        :param filename: the filename of the template 
    4242        :param lineno: the number of line in the template at which the error 
     
    6161 
    6262    def __init__(self, message, filename=None, lineno=-1, offset=-1): 
    6363        """Create the exception 
    64          
     64 
    6565        :param message: the error message 
    6666        :param filename: the filename of the template 
    6767        :param lineno: the number of line in the template at which the error 
     
    7676class BadDirectiveError(TemplateSyntaxError): 
    7777    """Exception raised when an unknown directive is encountered when parsing 
    7878    a template. 
    79      
     79 
    8080    An unknown directive is any attribute using the namespace for directives, 
    8181    with a local name that doesn't match any registered directive. 
    8282    """ 
    8383 
    8484    def __init__(self, name, filename=None, lineno=-1): 
    8585        """Create the exception 
    86          
     86 
    8787        :param name: the name of the directive 
    8888        :param filename: the filename of the template 
    8989        :param lineno: the number of line in the template at which the error 
     
    101101 
    102102class Context(object): 
    103103    """Container for template input data. 
    104      
     104 
    105105    A context provides a stack of scopes (represented by dictionaries). 
    106      
     106 
    107107    Template directives such as loops can push a new scope on the stack with 
    108108    data that should only be available inside the loop. When the loop 
    109109    terminates, that scope can get popped off the stack again. 
    110      
     110 
    111111    >>> ctxt = Context(one='foo', other=1) 
    112112    >>> ctxt.get('one') 
    113113    'foo' 
     
    151151 
    152152    def __contains__(self, key): 
    153153        """Return whether a variable exists in any of the scopes. 
    154          
     154 
    155155        :param key: the name of the variable 
    156156        """ 
    157157        return self._find(key)[1] is not None 
     
    159159 
    160160    def __delitem__(self, key): 
    161161        """Remove a variable from all scopes. 
    162          
     162 
    163163        :param key: the name of the variable 
    164164        """ 
    165165        for frame in self.frames: 
     
    169169    def __getitem__(self, key): 
    170170        """Get a variables's value, starting at the current scope and going 
    171171        upward. 
    172          
     172 
    173173        :param key: the name of the variable 
    174174        :return: the variable value 
    175175        :raises KeyError: if the requested variable wasn't found in any scope 
     
    181181 
    182182    def __len__(self): 
    183183        """Return the number of distinctly named variables in the context. 
    184          
     184 
    185185        :return: the number of variables in the context 
    186186        """ 
    187187        return len(self.items()) 
    188188 
    189189    def __setitem__(self, key, value): 
    190190        """Set a variable in the current scope. 
    191          
     191 
    192192        :param key: the name of the variable 
    193193        :param value: the variable value 
    194194        """ 
     
    198198        """Retrieve a given variable's value and the frame it was found in. 
    199199 
    200200        Intended primarily for internal use by directives. 
    201          
     201 
    202202        :param key: the name of the variable 
    203203        :param default: the default value to return when the variable is not 
    204204                        found 
     
    211211    def get(self, key, default=None): 
    212212        """Get a variable's value, starting at the current scope and going 
    213213        upward. 
    214          
     214 
    215215        :param key: the name of the variable 
    216216        :param default: the default value to return when the variable is not 
    217217                        found 
     
    223223 
    224224    def keys(self): 
    225225        """Return the name of all variables in the context. 
    226          
     226 
    227227        :return: a list of variable names 
    228228        """ 
    229229        keys = [] 
     
    234234    def items(self): 
    235235        """Return a list of ``(name, value)`` tuples for all variables in the 
    236236        context. 
    237          
     237 
    238238        :return: a list of variables 
    239239        """ 
    240240        return [(key, self.get(key)) for key in self.keys()] 
     
    245245 
    246246    def push(self, data): 
    247247        """Push a new scope on the stack. 
    248          
     248 
    249249        :param data: the data dictionary to push on the context stack. 
    250250        """ 
    251251 
     
    255255 
    256256def _apply_directives(stream, directives, ctxt, **vars): 
    257257    """Apply the given directives to the stream. 
    258      
     258 
    259259    :param stream: the stream the directives should be applied to 
    260260    :param directives: the list of directives to apply 
    261261    :param ctxt: the `Context` 
     
    269269 
    270270def _eval_expr(expr, ctxt, **vars): 
    271271    """Evaluate the given `Expression` object. 
    272      
     272 
    273273    :param expr: the expression to evaluate 
    274274    :param ctxt: the `Context` 
    275275    :param vars: additional variables that should be available to the 
     
    285285 
    286286def _exec_suite(suite, ctxt, **vars): 
    287287    """Execute the given `Suite` object. 
    288      
     288 
    289289    :param suite: the code suite to execute 
    290290    :param ctxt: the `Context` 
    291291    :param vars: additional variables that should be available to the 
     
    314314 
    315315class DirectiveFactory(object): 
    316316    """Base for classes that provide a set of template directives. 
    317      
     317 
    318318    :since: version 0.6 
    319319    """ 
    320320    __metaclass__ = DirectiveFactoryMeta 
     
    336336 
    337337    def get_directive(self, name): 
    338338        """Return the directive class for the given name. 
    339          
     339 
    340340        :param name: the directive name as used in the template 
    341341        :return: the directive class 
    342342        :see: `Directive` 
     
    346346 
    347347class Template(DirectiveFactory): 
    348348    """Abstract template base class. 
    349      
     349 
    350350    This class implements most of the template processing model, but does not 
    351351    specify the syntax of templates. 
    352352    """ 
     
    372372                 encoding=None, lookup='strict', allow_exec=True): 
    373373        """Initialize a template from either a string, a file-like object, or 
    374374        an already parsed markup stream. 
    375          
     375 
    376376        :param source: a string, file-like object, or markup stream to read the 
    377377                       template from 
    378378        :param filepath: the absolute path to the template file 
     
    385385                       default), "lenient", or a custom lookup class 
    386386        :param allow_exec: whether Python code blocks in templates should be 
    387387                           allowed 
    388          
     388 
    389389        :note: Changed in 0.5: Added the `allow_exec` argument 
    390390        """ 
    391391        self.filepath = filepath or filename 
     
    431431 
    432432    def _parse(self, source, encoding): 
    433433        """Parse the template. 
    434          
     434 
    435435        The parsing stage parses the template and constructs a list of 
    436436        directives that will be executed in the render stage. The input is 
    437437        split up into literal output (text that does not depend on the context 
    438438        data) and directives or expressions. 
    439          
     439 
    440440        :param source: a file-like object containing the XML source of the 
    441441                       template, or an XML event stream 
    442442        :param encoding: the encoding of the `source` 
     
    445445 
    446446    def _prepare(self, stream): 
    447447        """Call the `attach` method of every directive found in the template. 
    448          
     448 
    449449        :param stream: the event stream of the template 
    450450        """ 
    451451        from genshi.template.loader import TemplateNotFound 
     
    492492 
    493493    def generate(self, *args, **kwargs): 
    494494        """Apply the template to the given context data. 
    495          
     495 
    496496        Any keyword arguments are made available to the template as context 
    497497        data. 
    498          
     498 
    499499        Only one positional argument is accepted: if it is provided, it must be 
    500500        an instance of the `Context` class, and keyword arguments are ignored. 
    501501        This calling style is used for internal processing. 
    502          
     502 
    503503        :return: a markup event stream representing the result of applying 
    504504                 the template to the context data. 
    505505        """ 
     
    531531                tag, attrs = data 
    532532                new_attrs = [] 
    533533                for name, substream in attrs: 
    534                     if type(substream) is list: 
    535                         values = [] 
    536                         for event in self._flatten(substream, ctxt, **vars): 
    537                             if event[0] is TEXT: 
    538                                 values.append(event[1]) 
    539                         value = [x for x in values if x is not None] 
     534                    if isinstance(substream, basestring): 
     535                        value = substream 
     536                    else: 
     537                        value = [event[1] 
     538                            for event in self._flatten(substream, ctxt, **vars) 
     539                            if event[0] is TEXT and event[1] is not None] 
    540540                        if not value: 
    541541                            continue 
    542                     else: 
    543                         value = substream 
    544                     new_attrs.append((name, u''.join(value))) 
     542                        value = u''.join(value) 
     543                    new_attrs.append((name, value)) 
    545544                yield kind, (tag, Attrs(new_attrs)), pos 
    546545 
    547546            elif kind is EXPR: