moved concat to utils, fixed a few docstrings, fixed memory leak in _speedups.escape
authorArmin Ronacher <armin.ronacher@active-4.com>
Sat, 3 May 2008 08:15:31 +0000 (10:15 +0200)
committerArmin Ronacher <armin.ronacher@active-4.com>
Sat, 3 May 2008 08:15:31 +0000 (10:15 +0200)
--HG--
branch : trunk

12 files changed:
docs/api.rst
jinja2/_speedups.c
jinja2/compiler.py
jinja2/environment.py
jinja2/filters.py
jinja2/nodes.py
jinja2/optimizer.py
jinja2/runtime.py
jinja2/sandbox.py
jinja2/utils.py
setup.py
tests/test_imports.py

index a8d488b6e31154c4fa90055b4f7aff5e05b49483..6cab9837ff489ecfbcb97ce3511a6971e055c1d1 100644 (file)
@@ -85,7 +85,7 @@ High Level API
 
 
 .. autoclass:: jinja2.Template
-    :members: render, stream, generate, module
+    :members: render, stream, generate, make_module, module
 
     .. attribute:: globals
 
index 10ae6f692cd8d43b2f9789b1b2d52d5bb26542a0..5a7e9aa2d958b9f6779e3dc1ead66fdfa3e0588f 100644 (file)
@@ -2,7 +2,10 @@
  * jinja2._speedups
  * ~~~~~~~~~~~~~~~~
  *
- * This module implements a few functions in C for better performance.
+ * This module implements a few functions in C for better performance.  It
+ * also defines a `tb_set_next` function that is used to patch the debug
+ * traceback.  If the speedups module is not compiled a ctypes implementation
+ * is used.
  *
  * :copyright: 2008 by Armin Ronacher.
  * :license: BSD.
@@ -129,15 +132,8 @@ escape(PyObject *self, PyObject *text)
        /* we don't have to escape integers, bools or floats */
        if (PyInt_CheckExact(text) || PyLong_CheckExact(text) ||
            PyFloat_CheckExact(text) || PyBool_Check(text) ||
-           text == Py_None) {
-               PyObject *args = PyTuple_New(1);
-               if (!args) {
-                       Py_DECREF(s);
-                       return NULL;
-               }
-               PyTuple_SET_ITEM(args, 0, text);
-               return PyObject_CallObject(markup, args);
-       }
+           text == Py_None)
+               return PyObject_CallFunctionObjArgs(markup, text, NULL);
 
        /* if the object has an __html__ method that performs the escaping */
        PyObject *html = PyObject_GetAttrString(text, "__html__");
@@ -160,7 +156,9 @@ escape(PyObject *self, PyObject *text)
                s = escape_unicode((PyUnicodeObject*)text);
 
        /* convert the unicode string into a markup object. */
-       return PyObject_CallFunctionObjArgs(markup, (PyObject*)s, NULL);
+       rv = PyObject_CallFunctionObjArgs(markup, (PyObject*)s, NULL);
+       Py_DECREF(s);
+       return rv;
 }
 
 
index 3d4fcbe604e9fbfab03c394b0a0b63997d6fcbbd..e3b9e53305003a996bb000af9ffdcfd1d781a4fe 100644 (file)
@@ -17,8 +17,7 @@ from itertools import chain
 from jinja2 import nodes
 from jinja2.visitor import NodeVisitor, NodeTransformer
 from jinja2.exceptions import TemplateAssertionError
-from jinja2.runtime import concat
-from jinja2.utils import Markup
+from jinja2.utils import Markup, concat
 
 
 operators = {
index 68571fdeb6e4ad33f16c9763257ef34b54fc3c09..a129c387dc23fdeba285b8a7d40bbf5a6b0480eb 100644 (file)
@@ -14,10 +14,10 @@ from jinja2.lexer import Lexer
 from jinja2.parser import Parser
 from jinja2.optimizer import optimize
 from jinja2.compiler import generate
-from jinja2.runtime import Undefined, Context, concat
+from jinja2.runtime import Undefined, Context
 from jinja2.debug import translate_exception, translate_syntax_error
 from jinja2.exceptions import TemplateSyntaxError
-from jinja2.utils import import_string, LRUCache, Markup, missing
+from jinja2.utils import import_string, LRUCache, Markup, missing, concat
 
 
 # for direct template usage we have up to ten living environments
@@ -530,8 +530,11 @@ class Template(object):
         return Context(self.environment, parent, self.name, self.blocks)
 
     def make_module(self, vars=None, shared=False):
-        """Like the `module` property but always reevaluates the template
-        and it's possible to provide a context.
+        """This method works like the :attr:`module` attribute when called
+        without arguments but it will evaluate the template every call
+        rather then caching the template.  It's also possible to provide
+        a dict which is then used as context.  The arguments are the same
+        as fo the :meth:`new_context` method.
         """
         return TemplateModule(self, self.new_context(vars, shared))
 
@@ -593,7 +596,7 @@ class TemplateModule(object):
         # compiler too.  The Include without context passing directly
         # uses the mangled name.  The reason why we use a mangled one
         # is to avoid name clashes with macros with those names.
-        self.__body_stream = tuple(template.root_render_func(context))
+        self.__body_stream = list(template.root_render_func(context))
         self.__dict__.update(context.get_exported())
         self.__name__ = template.name
 
index 850079d44a6cfebd1e8f39f0ecab0adb4a993dd9..09b1babce9a2cbe0c192324b7cf6d00ce80549ea 100644 (file)
 import re
 import math
 from random import choice
-try:
-    from operator import itemgetter
-except ImportError:
-    itemgetter = lambda a: lambda b: b[a]
-from urllib import urlencode, quote
+from operator import itemgetter
 from itertools import imap, groupby
 from jinja2.utils import Markup, escape, pformat, urlize, soft_unicode
 from jinja2.runtime import Undefined
index d0372e808a02b200d696c9f4eff4ffcecbc5b134..83d757378090178d43f93284c6fb12e28665c683 100644 (file)
     :license: BSD, see LICENSE for more details.
 """
 import operator
+from copy import copy
 from types import FunctionType
 from itertools import chain, izip
 from collections import deque
-from copy import copy
 from jinja2.utils import Markup
 
 
index 784c3a8c5d59f9ee75ecbc159e8de56ac0b21ec8..283d1fae5637493aec61f722a995bec87b4edfd9 100644 (file)
@@ -18,7 +18,8 @@
 """
 from jinja2 import nodes
 from jinja2.visitor import NodeVisitor, NodeTransformer
-from jinja2.runtime import LoopContext, concat
+from jinja2.runtime import LoopContext
+from jinja2.utils import concat
 
 
 def optimize(node, environment, context_hint=None):
index 417fa707ec84ffada328baf2077d526002bea510..4b9ce6d635f1b8370cd4ea5cb01b140c4d263fd8 100644 (file)
@@ -11,7 +11,7 @@
 import sys
 from types import FunctionType
 from itertools import chain, imap
-from jinja2.utils import Markup, partial, soft_unicode, escape, missing
+from jinja2.utils import Markup, partial, soft_unicode, escape, missing, concat
 from jinja2.exceptions import UndefinedError, TemplateRuntimeError
 
 
@@ -21,27 +21,6 @@ __all__ = ['LoopContext', 'Context', 'TemplateReference', 'Macro', 'Markup',
            'markup_join', 'unicode_join']
 
 
-# concatenate a list of strings and convert them to unicode.
-# unfortunately there is a bug in python 2.4 and lower that causes
-# unicode.join trash the traceback.
-try:
-    def _test_gen_bug():
-        raise TypeError(_test_gen_bug)
-        yield None
-    u''.join(_test_gen_bug())
-except TypeError, _error:
-    if _error.args and _error.args[0] is _test_gen_bug:
-        concat = u''.join
-    else:
-        def concat(gen):
-            try:
-                return u''.join(list(gen))
-            except:
-                exc_type, exc_value, tb = sys.exc_info()
-                raise exc_type, exc_value, tb.tb_next
-    del _test_gen_bug, _error
-
-
 def markup_join(*args):
     """Concatenation that escapes if necessary and converts to unicode."""
     buf = []
index 71f0239ca363388452bdeb3000260b876a30b34f..02a04383cefb69c6fd83b0d10080bd9dfa5b3164 100644 (file)
@@ -23,7 +23,8 @@ MAX_RANGE = 100000
 
 def safe_range(*args):
     """A range that can't generate ranges with a length of more than
-    MAX_RANGE items."""
+    MAX_RANGE items.
+    """
     rng = xrange(*args)
     if len(rng) > MAX_RANGE:
         raise OverflowError('range too big')
@@ -61,10 +62,11 @@ class SandboxedEnvironment(Environment):
     def is_safe_callable(self, obj):
         """Check if an object is safely callable.  Per default a function is
         considered safe unless the `unsafe_callable` attribute exists and is
-        truish.  Override this method to alter the behavior, but this won't
+        True.  Override this method to alter the behavior, but this won't
         affect the `unsafe` decorator from this module.
         """
-        return not getattr(obj, 'unsafe_callable', False)
+        return not (getattr(obj, 'unsafe_callable', False) or \
+                    getattr(obj, 'alters_data', False))
 
     def subscribe(self, obj, argument):
         """Subscribe an object from sandboxed code."""
index 7bddcfe984bb375e144694737b4dc3a17ead5b2d..d9a45a8188a4aba131279b9b678d4afff0d10512 100644 (file)
@@ -33,6 +33,29 @@ _simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$')
 missing = type('MissingType', (), {'__repr__': lambda x: 'missing'})()
 
 
+# concatenate a list of strings and convert them to unicode.
+# unfortunately there is a bug in python 2.4 and lower that causes
+# unicode.join trash the traceback.
+try:
+    def _test_gen_bug():
+        raise TypeError(_test_gen_bug)
+        yield None
+    u''.join(_test_gen_bug())
+except TypeError, _error:
+    if _error.args and _error.args[0] is _test_gen_bug:
+        concat = u''.join
+    else:
+        def concat(gen):
+            try:
+                return u''.join(list(gen))
+            except:
+                # this hack is needed so that the current frame
+                # does not show up in the traceback.
+                exc_type, exc_value, tb = sys.exc_info()
+                raise exc_type, exc_value, tb.tb_next
+    del _test_gen_bug, _error
+
+
 def contextfunction(f):
     """This decorator can be used to mark a callable as context callable.  A
     context callable is passed the active context as first argument if it
index 0c4fb318c60b950e1e408e70e41be931e8e28b47..7fe263d7fc62ae955ecb90d80b787f2b24ab78b4 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -120,8 +120,7 @@ setup(
     ],
     packages=['jinja2'],
     data_files=[
-        ('docs/html', list(list_files('docs/html'))),
-        ('docs/txt', list(list_files('docs/src')))
+        ##('docs', list(list_files('docs/_build/html')))
     ],
     features={
         'speedups': Feature("optional C speed-enhancements",
index 7ce8bde394cd462c0eeedfd676142c8657f65571..92495e574c8eb02c2203f0a4384e5c5123a943af 100644 (file)
@@ -13,7 +13,7 @@ test_env = Environment(loader=DictLoader(dict(
     module='{% macro test() %}[{{ foo }}|{{ bar }}]{% endmacro %}',
     header='[{{ foo }}|{{ 23 }}]'
 )))
-test_env.globals['bar'] = '23'
+test_env.globals['bar'] = 23
 
 
 def test_context_imports():
@@ -44,3 +44,5 @@ def test_trailing_comma():
     test_env.from_string('{% from "foo" import bar, baz with context %}')
     test_env.from_string('{% from "foo" import bar, baz, with context %}')
     test_env.from_string('{% from "foo" import bar, with context %}')
+    test_env.from_string('{% from "foo" import bar, with, context %}')
+    test_env.from_string('{% from "foo" import bar, with with context %}')