Edgewall Software

Ticket #295: eval.patch

File eval.patch, 9.1 KB (added by Christoph Zwerschke <cito@…>, 7 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: