Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Zwinkau
libfirm
Commits
6caa200e
Commit
6caa200e
authored
Jan 24, 2015
by
Matthias Braun
Browse files
updated to latest jinja2
parent
a8479789
Changes
19
Hide whitespace changes
Inline
Side-by-side
scripts/jinja2/__init__.py
View file @
6caa200e
...
...
@@ -27,7 +27,7 @@
:license: BSD, see LICENSE for more details.
"""
__docformat__
=
'restructuredtext en'
__version__
=
'2.
7.2
'
__version__
=
'2.
8-dev
'
# high level interface
from
jinja2.environment
import
Environment
,
Template
...
...
@@ -42,7 +42,8 @@ from jinja2.bccache import BytecodeCache, FileSystemBytecodeCache, \
MemcachedBytecodeCache
# undefined types
from
jinja2.runtime
import
Undefined
,
DebugUndefined
,
StrictUndefined
from
jinja2.runtime
import
Undefined
,
DebugUndefined
,
StrictUndefined
,
\
make_logging_undefined
# exceptions
from
jinja2.exceptions
import
TemplateError
,
UndefinedError
,
\
...
...
@@ -65,5 +66,5 @@ __all__ = [
'TemplatesNotFound'
,
'TemplateSyntaxError'
,
'TemplateAssertionError'
,
'ModuleLoader'
,
'environmentfilter'
,
'contextfilter'
,
'Markup'
,
'escape'
,
'environmentfunction'
,
'contextfunction'
,
'clear_caches'
,
'is_undefined'
,
'evalcontextfilter'
,
'evalcontextfunction'
'evalcontextfilter'
,
'evalcontextfunction'
,
'make_logging_undefined'
,
]
scripts/jinja2/_compat.py
View file @
6caa200e
...
...
@@ -82,12 +82,6 @@ else:
return
filename
.
encode
(
'utf-8'
)
return
filename
try
:
next
=
next
except
NameError
:
def
next
(
it
):
return
it
.
next
()
def
with_metaclass
(
meta
,
*
bases
):
# This requires a bit of explanation: the basic idea is to make a
...
...
@@ -109,42 +103,7 @@ def with_metaclass(meta, *bases):
return
metaclass
(
'temporary_class'
,
None
,
{})
try
:
from
collections
import
Mapping
as
mapping_types
except
ImportError
:
import
UserDict
mapping_types
=
(
UserDict
.
UserDict
,
UserDict
.
DictMixin
,
dict
)
# common types. These do exist in the special types module too which however
# does not exist in IronPython out of the box. Also that way we don't have
# to deal with implementation specific stuff here
class
_C
(
object
):
def
method
(
self
):
pass
def
_func
():
yield
None
function_type
=
type
(
_func
)
generator_type
=
type
(
_func
())
method_type
=
type
(
_C
().
method
)
code_type
=
type
(
_C
.
method
.
__code__
)
try
:
raise
TypeError
()
except
TypeError
:
_tb
=
sys
.
exc_info
()[
2
]
traceback_type
=
type
(
_tb
)
frame_type
=
type
(
_tb
.
tb_frame
)
try
:
from
urllib.parse
import
quote_from_bytes
as
url_quote
except
ImportError
:
from
urllib
import
quote
as
url_quote
try
:
from
thread
import
allocate_lock
except
ImportError
:
try
:
from
threading
import
Lock
as
allocate_lock
except
ImportError
:
from
dummy_thread
import
allocate_lock
scripts/jinja2/bccache.py
View file @
6caa200e
...
...
@@ -17,6 +17,7 @@
from
os
import
path
,
listdir
import
os
import
sys
import
stat
import
errno
import
marshal
import
tempfile
...
...
@@ -87,7 +88,12 @@ class Bucket(object):
if
self
.
checksum
!=
checksum
:
self
.
reset
()
return
self
.
code
=
marshal_load
(
f
)
# if marshal_load fails then we need to reload
try
:
self
.
code
=
marshal_load
(
f
)
except
(
EOFError
,
ValueError
,
TypeError
):
self
.
reset
()
return
def
write_bytecode
(
self
,
f
):
"""Dump the bytecode into the file or file like object passed."""
...
...
@@ -211,24 +217,43 @@ class FileSystemBytecodeCache(BytecodeCache):
self
.
pattern
=
pattern
def
_get_default_cache_dir
(
self
):
def
_unsafe_dir
():
raise
RuntimeError
(
'Cannot determine safe temp directory. You '
'need to explicitly provide one.'
)
tmpdir
=
tempfile
.
gettempdir
()
# On windows the temporary directory is used specific unless
# explicitly forced otherwise. We can just use that.
if
os
.
name
==
'n'
:
if
os
.
name
==
'n
t
'
:
return
tmpdir
if
not
hasattr
(
os
,
'getuid'
):
raise
RuntimeError
(
'Cannot determine safe temp directory. You '
'need to explicitly provide one.'
)
_unsafe_dir
()
dirname
=
'_jinja2-cache-%d'
%
os
.
getuid
()
actual_dir
=
os
.
path
.
join
(
tmpdir
,
dirname
)
try
:
# 448 == 0700
os
.
mkdir
(
actual_dir
,
448
)
os
.
mkdir
(
actual_dir
,
stat
.
S_IRWXU
)
except
OSError
as
e
:
if
e
.
errno
!=
errno
.
EEXIST
:
raise
try
:
os
.
chmod
(
actual_dir
,
stat
.
S_IRWXU
)
actual_dir_stat
=
os
.
lstat
(
actual_dir
)
if
actual_dir_stat
.
st_uid
!=
os
.
getuid
()
\
or
not
stat
.
S_ISDIR
(
actual_dir_stat
.
st_mode
)
\
or
stat
.
S_IMODE
(
actual_dir_stat
.
st_mode
)
!=
stat
.
S_IRWXU
:
_unsafe_dir
()
except
OSError
as
e
:
if
e
.
errno
!=
errno
.
EEXIST
:
raise
actual_dir_stat
=
os
.
lstat
(
actual_dir
)
if
actual_dir_stat
.
st_uid
!=
os
.
getuid
()
\
or
not
stat
.
S_ISDIR
(
actual_dir_stat
.
st_mode
)
\
or
stat
.
S_IMODE
(
actual_dir_stat
.
st_mode
)
!=
stat
.
S_IRWXU
:
_unsafe_dir
()
return
actual_dir
...
...
scripts/jinja2/compiler.py
View file @
6caa200e
...
...
@@ -16,7 +16,7 @@ from jinja2.nodes import EvalContext
from
jinja2.visitor
import
NodeVisitor
from
jinja2.exceptions
import
TemplateAssertionError
from
jinja2.utils
import
Markup
,
concat
,
escape
from
jinja2._compat
import
range_type
,
next
,
text_type
,
string_types
,
\
from
jinja2._compat
import
range_type
,
text_type
,
string_types
,
\
iteritems
,
NativeStringIO
,
imap
...
...
@@ -347,6 +347,9 @@ class FrameIdentifierVisitor(NodeVisitor):
def
visit_FilterBlock
(
self
,
node
):
self
.
visit
(
node
.
filter
)
def
visit_AssignBlock
(
self
,
node
):
"""Stop visiting at block assigns."""
def
visit_Scope
(
self
,
node
):
"""Stop visiting at scopes."""
...
...
@@ -1332,42 +1335,62 @@ class CodeGenerator(NodeVisitor):
if
outdent_later
:
self
.
outdent
()
def
visit_Assign
(
self
,
node
,
frame
):
self
.
newline
(
node
)
def
make_assignment_frame
(
self
,
frame
):
# toplevel assignments however go into the local namespace and
# the current template's context. We create a copy of the frame
# here and add a set so that the Name visitor can add the assigned
# names here.
if
frame
.
toplevel
:
assignment_frame
=
frame
.
copy
()
assignment_frame
.
toplevel_assignments
=
set
()
if
not
frame
.
toplevel
:
return
frame
assignment_frame
=
frame
.
copy
()
assignment_frame
.
toplevel_assignments
=
set
()
return
assignment_frame
def
export_assigned_vars
(
self
,
frame
,
assignment_frame
):
if
not
frame
.
toplevel
:
return
public_names
=
[
x
for
x
in
assignment_frame
.
toplevel_assignments
if
not
x
.
startswith
(
'_'
)]
if
len
(
assignment_frame
.
toplevel_assignments
)
==
1
:
name
=
next
(
iter
(
assignment_frame
.
toplevel_assignments
))
self
.
writeline
(
'context.vars[%r] = l_%s'
%
(
name
,
name
))
else
:
assignment_frame
=
frame
self
.
writeline
(
'context.vars.update({'
)
for
idx
,
name
in
enumerate
(
assignment_frame
.
toplevel_assignments
):
if
idx
:
self
.
write
(
', '
)
self
.
write
(
'%r: l_%s'
%
(
name
,
name
))
self
.
write
(
'})'
)
if
public_names
:
if
len
(
public_names
)
==
1
:
self
.
writeline
(
'context.exported_vars.add(%r)'
%
public_names
[
0
])
else
:
self
.
writeline
(
'context.exported_vars.update((%s))'
%
', '
.
join
(
imap
(
repr
,
public_names
)))
def
visit_Assign
(
self
,
node
,
frame
):
self
.
newline
(
node
)
assignment_frame
=
self
.
make_assignment_frame
(
frame
)
self
.
visit
(
node
.
target
,
assignment_frame
)
self
.
write
(
' = '
)
self
.
visit
(
node
.
node
,
frame
)
# make sure toplevel assignments are added to the context.
if
frame
.
toplevel
:
public_names
=
[
x
for
x
in
assignment_frame
.
toplevel_assignments
if
not
x
.
startswith
(
'_'
)]
if
len
(
assignment_frame
.
toplevel_assignments
)
==
1
:
name
=
next
(
iter
(
assignment_frame
.
toplevel_assignments
))
self
.
writeline
(
'context.vars[%r] = l_%s'
%
(
name
,
name
))
else
:
self
.
writeline
(
'context.vars.update({'
)
for
idx
,
name
in
enumerate
(
assignment_frame
.
toplevel_assignments
):
if
idx
:
self
.
write
(
', '
)
self
.
write
(
'%r: l_%s'
%
(
name
,
name
))
self
.
write
(
'})'
)
if
public_names
:
if
len
(
public_names
)
==
1
:
self
.
writeline
(
'context.exported_vars.add(%r)'
%
public_names
[
0
])
else
:
self
.
writeline
(
'context.exported_vars.update((%s))'
%
', '
.
join
(
imap
(
repr
,
public_names
)))
self
.
export_assigned_vars
(
frame
,
assignment_frame
)
def
visit_AssignBlock
(
self
,
node
,
frame
):
block_frame
=
frame
.
inner
()
block_frame
.
inspect
(
node
.
body
)
aliases
=
self
.
push_scope
(
block_frame
)
self
.
pull_locals
(
block_frame
)
self
.
buffer
(
block_frame
)
self
.
blockvisit
(
node
.
body
,
block_frame
)
self
.
pop_scope
(
aliases
,
block_frame
)
assignment_frame
=
self
.
make_assignment_frame
(
frame
)
self
.
newline
(
node
)
self
.
visit
(
node
.
target
,
assignment_frame
)
self
.
write
(
' = concat(%s)'
%
block_frame
.
buffer
)
self
.
export_assigned_vars
(
frame
,
assignment_frame
)
# -- Expression Visitors
...
...
scripts/jinja2/debug.py
View file @
6caa200e
...
...
@@ -12,10 +12,10 @@
"""
import
sys
import
traceback
from
types
import
TracebackType
from
types
import
TracebackType
,
CodeType
from
jinja2.utils
import
missing
,
internal_code
from
jinja2.exceptions
import
TemplateSyntaxError
from
jinja2._compat
import
iteritems
,
reraise
,
code_type
from
jinja2._compat
import
iteritems
,
reraise
# on pypy we can take advantage of transparent proxies
try
:
...
...
@@ -245,11 +245,11 @@ def fake_exc_info(exc_info, filename, lineno):
location
=
'block "%s"'
%
function
[
6
:]
else
:
location
=
'template'
code
=
c
ode
_t
ype
(
0
,
code
.
co_nlocals
,
code
.
co_stacksize
,
code
.
co_flags
,
code
.
co_code
,
code
.
co_consts
,
code
.
co_names
,
code
.
co_varnames
,
filename
,
location
,
code
.
co_firstlineno
,
code
.
co_lnotab
,
(),
())
code
=
C
ode
T
ype
(
0
,
code
.
co_nlocals
,
code
.
co_stacksize
,
code
.
co_flags
,
code
.
co_code
,
code
.
co_consts
,
code
.
co_names
,
code
.
co_varnames
,
filename
,
location
,
code
.
co_firstlineno
,
code
.
co_lnotab
,
(),
())
except
:
pass
...
...
scripts/jinja2/environment.py
View file @
6caa200e
...
...
@@ -90,13 +90,13 @@ def load_extensions(environment, extensions):
def
_environment_sanity_check
(
environment
):
"""Perform a sanity check on the environment."""
assert
issubclass
(
environment
.
undefined
,
Undefined
),
'undefined must '
\
'be a subclass of undefined because filters depend on it.'
'be a subclass of undefined because filters depend on it.'
assert
environment
.
block_start_string
!=
\
environment
.
variable_start_string
!=
\
environment
.
comment_start_string
,
'block, variable and comment '
\
'start strings must be different'
environment
.
variable_start_string
!=
\
environment
.
comment_start_string
,
'block, variable and comment '
\
'start strings must be different'
assert
environment
.
newline_sequence
in
(
'
\r
'
,
'
\r\n
'
,
'
\n
'
),
\
'newline_sequence set to unknown line ending string.'
'newline_sequence set to unknown line ending string.'
return
environment
...
...
@@ -108,16 +108,16 @@ class Environment(object):
Modifications on environments after the first template was loaded
will lead to surprising effects and undefined behavior.
Here the possible initialization parameters:
Here
are
the possible initialization parameters:
`block_start_string`
The string marking the begin of a block. Defaults to ``'{%'``.
The string marking the begin
ning
of a block. Defaults to ``'{%'``.
`block_end_string`
The string marking the end of a block. Defaults to ``'%}'``.
`variable_start_string`
The string marking the begin of a print statement.
The string marking the begin
ning
of a print statement.
Defaults to ``'{{'``.
`variable_end_string`
...
...
@@ -125,7 +125,7 @@ class Environment(object):
``'}}'``.
`comment_start_string`
The string marking the begin of a comment. Defaults to ``'{#'``.
The string marking the begin
ning
of a comment. Defaults to ``'{#'``.
`comment_end_string`
The string marking the end of a comment. Defaults to ``'#}'``.
...
...
@@ -180,7 +180,7 @@ class Environment(object):
`autoescape`
If set to true the XML/HTML autoescaping feature is enabled by
default. For more details about auto
escaping see
default. For more details about autoescaping see
:class:`~jinja2.utils.Markup`. As of Jinja 2.4 this can also
be a callable that is passed the template name and has to
return `True` or `False` depending on autoescape should be
...
...
@@ -193,12 +193,15 @@ class Environment(object):
The template loader for this environment.
`cache_size`
The size of the cache. Per default this is ``
5
0`` which means
that if more than
5
0 templates are loaded the loader will clean
The size of the cache. Per default this is ``
40
0`` which means
that if more than
40
0 templates are loaded the loader will clean
out the least recently used template. If the cache size is set to
``0`` templates are recompiled all the time, if the cache size is
``-1`` the cache will not be cleaned.
.. versionchanged:: 2.8
The cache size was increased to 400 from a low 50.
`auto_reload`
Some loaders load templates from locations where the template
sources may change (ie: file system or database). If
...
...
@@ -254,7 +257,7 @@ class Environment(object):
finalize
=
None
,
autoescape
=
False
,
loader
=
None
,
cache_size
=
5
0
,
cache_size
=
40
0
,
auto_reload
=
True
,
bytecode_cache
=
None
):
# !!Important notice!!
...
...
@@ -330,7 +333,7 @@ class Environment(object):
loader
=
missing
,
cache_size
=
missing
,
auto_reload
=
missing
,
bytecode_cache
=
missing
):
"""Create a new overlay environment that shares all the data with the
current environment except
o
f cache and the overridden attributes.
current environment except f
or
cache and the overridden attributes.
Extensions cannot be removed for an overlayed environment. An overlayed
environment automatically gets all the extensions of the environment it
is linked to plus optional extra extensions.
...
...
@@ -551,7 +554,7 @@ class Environment(object):
return
self
.
_compile
(
source
,
filename
)
except
TemplateSyntaxError
:
exc_info
=
sys
.
exc_info
()
self
.
handle_exception
(
exc_info
,
source_hint
=
source
)
self
.
handle_exception
(
exc_info
,
source_hint
=
source
_hint
)
def
compile_expression
(
self
,
source
,
undefined_to_none
=
True
):
"""A handy helper method that returns a callable that accepts keyword
...
...
@@ -603,8 +606,8 @@ class Environment(object):
ignore_errors
=
True
,
py_compile
=
False
):
"""Finds all the templates the loader can find, compiles them
and stores them in `target`. If `zip` is `None`, instead of in a
zipfile, the templates will be
will be
stored in a directory.
By default a deflate zip algorithm is used
, t
o switch to
zipfile, the templates will be stored in a directory.
By default a deflate zip algorithm is used
. T
o switch to
the stored algorithm, `zip` can be set to ``'stored'``.
`extensions` and `filter_func` are passed to :meth:`list_templates`.
...
...
@@ -634,7 +637,8 @@ class Environment(object):
warn
(
Warning
(
'py_compile has no effect on pypy or Python 3'
))
py_compile
=
False
else
:
import
imp
,
marshal
import
imp
import
marshal
py_header
=
imp
.
get_magic
()
+
\
u
'
\xff\xff\xff\xff
'
.
encode
(
'iso-8859-15'
)
...
...
@@ -716,7 +720,7 @@ class Environment(object):
filter_func
=
lambda
x
:
'.'
in
x
and
\
x
.
rsplit
(
'.'
,
1
)[
1
]
in
extensions
if
filter_func
is
not
None
:
x
=
ifilter
(
filter_func
,
x
)
x
=
list
(
ifilter
(
filter_func
,
x
)
)
return
x
def
handle_exception
(
self
,
exc_info
=
None
,
rendered
=
False
,
source_hint
=
None
):
...
...
@@ -757,14 +761,23 @@ class Environment(object):
def
_load_template
(
self
,
name
,
globals
):
if
self
.
loader
is
None
:
raise
TypeError
(
'no loader for this environment specified'
)
try
:
# use abs path for cache key
cache_key
=
self
.
loader
.
get_source
(
self
,
name
)[
1
]
except
RuntimeError
:
# if loader does not implement get_source()
cache_key
=
None
# if template is not file, use name for cache key
if
cache_key
is
None
:
cache_key
=
name
if
self
.
cache
is
not
None
:
template
=
self
.
cache
.
get
(
name
)
if
template
is
not
None
and
(
not
self
.
auto_reload
or
\
template
=
self
.
cache
.
get
(
cache_key
)
if
template
is
not
None
and
(
not
self
.
auto_reload
or
template
.
is_up_to_date
):
return
template
template
=
self
.
loader
.
load
(
self
,
name
,
globals
)
if
self
.
cache
is
not
None
:
self
.
cache
[
name
]
=
template
self
.
cache
[
cache_key
]
=
template
return
template
@
internalcode
...
...
@@ -1131,7 +1144,9 @@ class TemplateStream(object):
"""
close
=
False
if
isinstance
(
fp
,
string_types
):
fp
=
open
(
fp
,
encoding
is
None
and
'w'
or
'wb'
)
if
encoding
is
None
:
encoding
=
'utf-8'
fp
=
open
(
fp
,
'wb'
)
close
=
True
try
:
if
encoding
is
not
None
:
...
...
scripts/jinja2/ext.py
View file @
6caa200e
...
...
@@ -20,7 +20,7 @@ from jinja2.environment import Environment
from
jinja2.runtime
import
concat
from
jinja2.exceptions
import
TemplateAssertionError
,
TemplateSyntaxError
from
jinja2.utils
import
contextfunction
,
import_string
,
Markup
from
jinja2._compat
import
next
,
with_metaclass
,
string_types
,
iteritems
from
jinja2._compat
import
with_metaclass
,
string_types
,
iteritems
# the only real useful gettext functions for a Jinja template. Note
...
...
scripts/jinja2/filters.py
View file @
6caa200e
...
...
@@ -18,7 +18,7 @@ from jinja2.utils import Markup, escape, pformat, urlize, soft_unicode, \
unicode_urlencode
from
jinja2.runtime
import
Undefined
from
jinja2.exceptions
import
FilterArgumentError
from
jinja2._compat
import
next
,
imap
,
string_types
,
text_type
,
iteritems
from
jinja2._compat
import
imap
,
string_types
,
text_type
,
iteritems
_word_re
=
re
.
compile
(
r
'\w+(?u)'
)
...
...
@@ -183,7 +183,7 @@ def do_title(s):
uppercase letters, all remaining characters are lowercase.
"""
rv
=
[]
for
item
in
re
.
compile
(
r
'([-\s]+)(?u)'
).
split
(
s
):
for
item
in
re
.
compile
(
r
'([-\s]+)(?u)'
).
split
(
s
oft_unicode
(
s
)
):
if
not
item
:
continue
rv
.
append
(
item
[
0
].
upper
()
+
item
[
1
:].
lower
())
...
...
@@ -204,8 +204,7 @@ def do_dictsort(value, case_sensitive=False, by='key'):
sort the dict by key, case sensitive
{% for item in mydict|dictsort(false, 'value') %}
sort the dict by key, case insensitive, sorted
normally and ordered by value.
sort the dict by value, case insensitive
"""
if
by
==
'key'
:
pos
=
0
...
...
@@ -409,7 +408,8 @@ def do_pprint(value, verbose=False):
@
evalcontextfilter
def
do_urlize
(
eval_ctx
,
value
,
trim_url_limit
=
None
,
nofollow
=
False
):
def
do_urlize
(
eval_ctx
,
value
,
trim_url_limit
=
None
,
nofollow
=
False
,
target
=
None
):
"""Converts URLs in plain text into clickable links.
If you pass the filter an additional integer it will shorten the urls
...
...
@@ -420,8 +420,18 @@ def do_urlize(eval_ctx, value, trim_url_limit=None, nofollow=False):
{{ mytext|urlize(40, true) }}
links are shortened to 40 chars and defined with rel="nofollow"
If *target* is specified, the ``target`` attribute will be added to the
``<a>`` tag:
.. sourcecode:: jinja
{{ mytext|urlize(40, target='_blank') }}
.. versionchanged:: 2.8+
The *target* parameter was added.
"""
rv
=
urlize
(
value
,
trim_url_limit
,
nofollow
)
rv
=
urlize
(
value
,
trim_url_limit
,
nofollow
,
target
)
if
eval_ctx
.
autoescape
:
rv
=
Markup
(
rv
)
return
rv
...
...
@@ -456,25 +466,22 @@ def do_truncate(s, length=255, killwords=False, end='...'):
.. sourcecode:: jinja
{{ "foo bar"|truncate(5) }}
{{ "foo bar baz"|truncate(9) }}
-> "foo ba..."
{{ "foo bar baz"|truncate(9, True) }}
-> "foo ..."
{{ "foo bar"|truncate(5, True) }}
-> "foo b..."
"""
if
len
(
s
)
<=
length
:
return
s
elif
killwords
:
return
s
[:
length
]
+
end
words
=
s
.
split
(
' '
)
result
=
[]
m
=
0
for
word
in
words
:
m
+=
len
(
word
)
+
1
if
m
>
length
:
break
result
.
append
(
word
)
result
.
append
(
end
)
return
u
' '
.
join
(
result
)
return
s
[:
length
-
len
(
end
)]
+
end
result
=
s
[:
length
-
len
(
end
)].
rsplit
(
' '
,
1
)[
0
]
if
len
(
result
)
<
length
:
result
+=
' '
return
result
+
end
@
environmentfilter
def
do_wordwrap
(
environment
,
s
,
width
=
79
,
break_long_words
=
True
,
...
...
@@ -612,7 +619,6 @@ def do_batch(value, linecount, fill_with=None):
{%- endfor %}
</table>
"""
result
=
[]
tmp
=
[]
for
item
in
value
:
if
len
(
tmp
)
==
linecount
:
...
...
@@ -842,14 +848,15 @@ def do_map(*args, **kwargs):
@
contextfilter
def
do_select
(
*
args
,
**
kwargs
):
"""Filters a sequence of objects by appying a test to
either
the object
or the attribute and only
selecting the ones with the test succeeding.
"""Filters a sequence of objects by appying a test to the object
and only
selecting the ones with the test succeeding.
Example usage:
.. sourcecode:: jinja
{{ numbers|select("odd") }}
{{ numbers|select("odd") }}
.. versionadded:: 2.7
"""
...
...
@@ -858,8 +865,8 @@ def do_select(*args, **kwargs):
@
contextfilter
def
do_reject
(
*
args
,
**
kwargs
):
"""Filters a sequence of objects by appying a test to
either
the object
or the attribute and
rejecting the ones with the test succeeding.
"""Filters a sequence of objects by appying a test to the object
and
rejecting the ones with the test succeeding.
Example usage:
...
...
@@ -874,8 +881,8 @@ def do_reject(*args, **kwargs):
@
contextfilter
def
do_selectattr
(
*
args
,
**
kwargs
):
"""Filters a sequence of objects by appying a test to
either the object
o
r the attribute
and only selecting the ones with the test succeeding.
"""Filters a sequence of objects by appying a test to
an attribute of an
o
bject
and only selecting the ones with the test succeeding.
Example usage:
...
...
@@ -891,8 +898,8 @@ def do_selectattr(*args, **kwargs):
@
contextfilter
def
do_rejectattr
(
*
args
,
**
kwargs
):
"""Filters a sequence of objects by appying a test to
either the object
or the attribute and rejecting the ones with the test succeeding.
"""Filters a sequence of objects by appying a test to
an attribute of an
object
or the attribute and rejecting the ones with the test succeeding.
.. sourcecode:: jinja
...
...
scripts/jinja2/lexer.py
View file @
6caa200e
...
...
@@ -20,8 +20,8 @@ from operator import itemgetter
from
collections
import
deque