mirror of
https://gitee.com/openharmony/third_party_jinja2
synced 2024-11-27 01:10:36 +00:00
worked on the tests and made undefined fail on comparisons now
--HG-- branch : trunk
This commit is contained in:
parent
2feed1d5e2
commit
5304229478
@ -678,10 +678,12 @@ class CodeGenerator(NodeVisitor):
|
||||
"""Visit regular imports."""
|
||||
self.writeline('l_%s = ' % node.target, node)
|
||||
if frame.toplevel:
|
||||
self.write('context[%r] = ' % node.target)
|
||||
self.write('context.vars[%r] = ' % node.target)
|
||||
self.write('environment.get_template(')
|
||||
self.visit(node.template, frame)
|
||||
self.write(', %r).include(context)' % self.name)
|
||||
if frame.toplevel:
|
||||
self.writeline('context.exported_vars.discard(%r)' % node.target)
|
||||
|
||||
def visit_FromImport(self, node, frame):
|
||||
"""Visit named imports."""
|
||||
@ -704,7 +706,8 @@ class CodeGenerator(NodeVisitor):
|
||||
'the requested name ' + repr(name)))
|
||||
self.outdent()
|
||||
if frame.toplevel:
|
||||
self.writeline('context[%r] = l_%s' % (alias, alias))
|
||||
self.writeline('context.vars[%r] = l_%s' % (alias, alias))
|
||||
self.writeline('context.exported_vars.discard(%r)' % alias)
|
||||
|
||||
def visit_For(self, node, frame):
|
||||
loop_frame = frame.inner()
|
||||
|
@ -238,7 +238,7 @@ class Environment(object):
|
||||
"""Load a template from a string."""
|
||||
globals = self.make_globals(globals)
|
||||
return template_from_code(self, self.compile(source, globals=globals),
|
||||
globals, template_class)
|
||||
globals, None, template_class)
|
||||
|
||||
def make_globals(self, d):
|
||||
"""Return a dict for the globals."""
|
||||
@ -385,31 +385,36 @@ class Template(object):
|
||||
self._debug_info.split('&')]
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s %r>' % (
|
||||
self.__class__.__name__,
|
||||
self.name or '<from string>'
|
||||
)
|
||||
if self.name is None:
|
||||
name = 'memory:%x' % id(self)
|
||||
else:
|
||||
name = repr(self.name)
|
||||
return '<%s %s>' % (self.__class__.__name__, name)
|
||||
|
||||
|
||||
class IncludedTemplate(object):
|
||||
"""Represents an included template."""
|
||||
"""Represents an included template. All the exported names of the
|
||||
template are available as attributes on this object. Additionally
|
||||
converting it into an unicode- or bytestrings renders the contents.
|
||||
"""
|
||||
|
||||
def __init__(self, template, context):
|
||||
self._body_stream = tuple(template.root_render_func(context))
|
||||
self.__body_stream = tuple(template.root_render_func(context))
|
||||
self.__dict__.update(context.get_exported())
|
||||
self.__name__ = template.name
|
||||
|
||||
__html__ = lambda x: Markup(concat(x._body_stream))
|
||||
__unicode__ = lambda x: unicode(concat(x._body_stream))
|
||||
__html__ = lambda x: Markup(concat(x.__body_stream))
|
||||
__unicode__ = lambda x: unicode(concat(x.__body_stream))
|
||||
|
||||
def __str__(self):
|
||||
return unicode(self).encode('utf-8')
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s %r>' % (
|
||||
self.__class__.__name__,
|
||||
self.__name__
|
||||
)
|
||||
if self.__name__ is None:
|
||||
name = 'memory:%x' % id(self)
|
||||
else:
|
||||
name = repr(self.name)
|
||||
return '<%s %s>' % (self.__class__.__name__, name)
|
||||
|
||||
|
||||
class TemplateStream(object):
|
||||
|
@ -36,16 +36,12 @@ class TemplateSyntaxError(TemplateError):
|
||||
self.name = name
|
||||
|
||||
|
||||
class TemplateAssertionError(AssertionError, TemplateSyntaxError):
|
||||
class TemplateAssertionError(TemplateSyntaxError):
|
||||
"""Like a template syntax error, but covers cases where something in the
|
||||
template caused an error at compile time that wasn't necessarily caused
|
||||
by a syntax error.
|
||||
"""
|
||||
|
||||
def __init__(self, message, lineno, name):
|
||||
AssertionError.__init__(self, message)
|
||||
TemplateSyntaxError.__init__(self, message, lineno, name)
|
||||
|
||||
|
||||
class TemplateRuntimeError(TemplateError):
|
||||
"""Raised by the template engine if a tag encountered an error when
|
||||
|
@ -9,14 +9,13 @@
|
||||
:license: GNU GPL.
|
||||
"""
|
||||
from types import FunctionType
|
||||
from itertools import izip
|
||||
from jinja2.utils import Markup, partial
|
||||
from jinja2.exceptions import UndefinedError
|
||||
|
||||
|
||||
# these variables are exported to the template runtime
|
||||
__all__ = ['LoopContext', 'StaticLoopContext', 'TemplateContext',
|
||||
'Macro', 'Markup', 'missing', 'concat', 'izip']
|
||||
'Macro', 'Markup', 'missing', 'concat']
|
||||
|
||||
|
||||
# special singleton representing missing values for the runtime
|
||||
@ -66,16 +65,24 @@ class TemplateContext(object):
|
||||
'called %r.' % block)
|
||||
return SuperBlock(block, self, last)
|
||||
|
||||
def get(self, name, default=None):
|
||||
def get(self, key, default=None):
|
||||
"""For dict compatibility"""
|
||||
try:
|
||||
return self[name]
|
||||
except KeyError:
|
||||
return default
|
||||
if key in self.vars:
|
||||
return self.vars[key]
|
||||
if key in self.parent:
|
||||
return self.parent[key]
|
||||
return default
|
||||
|
||||
def update(self, mapping):
|
||||
def setdefault(self, key, default=None):
|
||||
"""For dict compatibility"""
|
||||
self.exported_vars.add(key)
|
||||
return self.vars.setdefault(key, default)
|
||||
|
||||
def update(self, *args, **kwargs):
|
||||
"""Update vars from a mapping but don't export them."""
|
||||
self.vars.update(mapping)
|
||||
d = dict(*args, **kwargs)
|
||||
self.vars.update(d)
|
||||
self.exported_vars.update(d)
|
||||
|
||||
def get_exported(self):
|
||||
"""Get a new dict with the exported variables."""
|
||||
@ -100,10 +107,9 @@ class TemplateContext(object):
|
||||
def __getitem__(self, key):
|
||||
if key in self.vars:
|
||||
return self.vars[key]
|
||||
try:
|
||||
if key in self.parent:
|
||||
return self.parent[key]
|
||||
except KeyError:
|
||||
return self.environment.undefined(name=key)
|
||||
return self.environment.undefined(name=key)
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s %s of %r>' % (
|
||||
@ -302,6 +308,7 @@ class Undefined(object):
|
||||
can be printed and iterated over, but every other access will raise a
|
||||
`NameError`. Custom undefined classes must subclass this.
|
||||
"""
|
||||
__slots__ = ('_undefined_hint', '_undefined_obj', '_undefined_name')
|
||||
|
||||
def __init__(self, hint=None, obj=None, name=None):
|
||||
self._undefined_hint = hint
|
||||
@ -311,7 +318,8 @@ class Undefined(object):
|
||||
__add__ = __radd__ = __mul__ = __rmul__ = __div__ = __rdiv__ = \
|
||||
__realdiv__ = __rrealdiv__ = __floordiv__ = __rfloordiv__ = \
|
||||
__mod__ = __rmod__ = __pos__ = __neg__ = __call__ = \
|
||||
__getattr__ = __getitem__ = fail_with_undefined_error
|
||||
__getattr__ = __getitem__ = __lt__ = __le__ = __gt__ = __ge__ = \
|
||||
fail_with_undefined_error
|
||||
|
||||
def __str__(self):
|
||||
return self.__unicode__().encode('utf-8')
|
||||
@ -335,6 +343,7 @@ class Undefined(object):
|
||||
|
||||
class DebugUndefined(Undefined):
|
||||
"""An undefined that returns the debug info when printed."""
|
||||
__slots__ = ()
|
||||
|
||||
def __unicode__(self):
|
||||
if self._undefined_hint is None:
|
||||
@ -349,8 +358,14 @@ class DebugUndefined(Undefined):
|
||||
|
||||
class StrictUndefined(Undefined):
|
||||
"""An undefined that barks on print and iteration as well as boolean
|
||||
tests. In other words: you can do nothing with it except checking if it's
|
||||
defined using the `defined` test.
|
||||
tests and all kinds of comparisons. In other words: you can do nothing
|
||||
with it except checking if it's defined using the `defined` test.
|
||||
"""
|
||||
__slots__ = ()
|
||||
__iter__ = __unicode__ = __len__ = __nonzero__ = __eq__ = __ne__ = \
|
||||
fail_with_undefined_error
|
||||
|
||||
__iter__ = __unicode__ = __len__ = __nonzero__ = fail_with_undefined_error
|
||||
|
||||
# remove remaining slots attributes, after the metaclass did the magic they
|
||||
# are unneeded and irritating as they contain wrong data for the subclasses.
|
||||
del Undefined.__slots__, DebugUndefined.__slots__, StrictUndefined.__slots__
|
||||
|
@ -48,21 +48,34 @@ def test_defined(value):
|
||||
return not isinstance(value, Undefined)
|
||||
|
||||
|
||||
def test_undefined(value):
|
||||
"""Like `defined` but the other way round."""
|
||||
return isinstance(value, Undefined)
|
||||
|
||||
|
||||
def test_none(value):
|
||||
"""Return true if the variable is none."""
|
||||
return value is None
|
||||
|
||||
|
||||
def test_lower(value):
|
||||
"""Return true if the variable is lowercase."""
|
||||
"""Return true if the variable is lowercased."""
|
||||
return unicode(value).islower()
|
||||
|
||||
|
||||
def test_upper(value):
|
||||
"""Return true if the variable is uppercase."""
|
||||
"""Return true if the variable is uppercased."""
|
||||
return unicode(value).isupper()
|
||||
|
||||
|
||||
def test_numeric(value):
|
||||
"""Return true if the variable is numeric."""
|
||||
return isinstance(value, (int, long, float)) or (
|
||||
isinstance(value, basestring) and
|
||||
number_re.match(value) is not None)
|
||||
def test_string(value):
|
||||
"""Return true if the object is a string."""
|
||||
return isinstance(value, basestring)
|
||||
|
||||
|
||||
def test_number(value):
|
||||
"""Return true if the variable is a number."""
|
||||
return isinstance(value, (int, long, float, complex))
|
||||
|
||||
|
||||
def test_sequence(value):
|
||||
@ -90,14 +103,28 @@ def test_sameas(value, other):
|
||||
return value is other
|
||||
|
||||
|
||||
def test_iterable(value):
|
||||
"""Check if it's possible to iterate over an object."""
|
||||
try:
|
||||
iter(value)
|
||||
except TypeError:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
TESTS = {
|
||||
'odd': test_odd,
|
||||
'even': test_even,
|
||||
'divisibleby': test_divisibleby,
|
||||
'defined': test_defined,
|
||||
'undefined': test_undefined,
|
||||
'none': test_none,
|
||||
'lower': test_lower,
|
||||
'upper': test_upper,
|
||||
'numeric': test_numeric,
|
||||
'string': test_string,
|
||||
'number': test_number,
|
||||
'sequence': test_sequence,
|
||||
'iterable': test_iterable,
|
||||
'callable': callable,
|
||||
'sameas': test_sameas
|
||||
}
|
||||
|
@ -10,14 +10,12 @@
|
||||
DEFINED = '''{{ missing is defined }}|{{ true is defined }}'''
|
||||
EVEN = '''{{ 1 is even }}|{{ 2 is even }}'''
|
||||
LOWER = '''{{ "foo" is lower }}|{{ "FOO" is lower }}'''
|
||||
NUMERIC = '''{{ "43" is numeric }}|{{ "foo" is numeric }}|\
|
||||
{{ 42 is numeric }}'''
|
||||
ODD = '''{{ 1 is odd }}|{{ 2 is odd }}'''
|
||||
SEQUENCE = '''{{ [1, 2, 3] is sequence }}|\
|
||||
{{ "foo" is sequence }}|\
|
||||
{{ 42 is sequence }}'''
|
||||
UPPER = '''{{ "FOO" is upper }}|{{ "foo" is upper }}'''
|
||||
SAMEAS = '''{{ foo is sameas(false) }}|{{ 0 is sameas(false) }}'''
|
||||
SAMEAS = '''{{ foo is sameas false }}|{{ 0 is sameas false }}'''
|
||||
NOPARENFORARG1 = '''{{ foo is sameas none }}'''
|
||||
|
||||
|
||||
@ -36,11 +34,6 @@ def test_lower(env):
|
||||
assert tmpl.render() == 'True|False'
|
||||
|
||||
|
||||
def test_numeric(env):
|
||||
tmpl = env.from_string(NUMERIC)
|
||||
assert tmpl.render() == 'True|False|True'
|
||||
|
||||
|
||||
def test_odd(env):
|
||||
tmpl = env.from_string(ODD)
|
||||
assert tmpl.render() == 'True|False'
|
||||
|
Loading…
Reference in New Issue
Block a user