Merge pull request #33 from razamatan/master
authorArmin Ronacher <armin.ronacher@active-4.com>
Tue, 24 May 2011 15:50:55 +0000 (08:50 -0700)
committerArmin Ronacher <armin.ronacher@active-4.com>
Tue, 24 May 2011 15:50:55 +0000 (08:50 -0700)
jinja.vim subsumes htmljinja.vim

CHANGES
docs/faq.rst
docs/templates.rst
jinja2-debug.py
jinja2/bccache.py
jinja2/tests.py
jinja2/testsuite/tests.py

diff --git a/CHANGES b/CHANGES
index 2cdedf426e61997fdce33bef1c5ae00e257a4ef1..9fdfba2a963b54007b8f13c5962833a772586f5a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -32,6 +32,8 @@ Version 2.6
 - like sum and sort, join now also is able to join attributes of objects
   as string.
 - the internal eval context now has a reference to the environment.
+- added a mapping test to see if an object is a dict or an object with
+  a similar interface.
 
 Version 2.5.5
 -------------
index 89186b1e284674d512afd6680570dde058fc9653..2e4be8c211a8c3b4208092fd59f2e3e0261b97e7 100644 (file)
@@ -10,7 +10,7 @@ Why is it called Jinja?
 
 The name Jinja was chosen because it's the name of a Japanese temple and
 temple and template share a similar pronunciation.  It is not named after
-the capital city of Uganda.
+the city in Uganda.
 
 How fast is it?
 ---------------
index b9fbb474a4fdd7016a163f40a60acc0e7c137f6a..a4a7d30324b313c6e47dd04e08ba3db3e5854448 100644 (file)
@@ -972,7 +972,7 @@ but exists for completeness' sake.  The following operators are supported:
 
 //
     Divide two numbers and return the truncated integer result.
-    ``{{ 20 / 7 }}`` is ``2``.
+    ``{{ 20 // 7 }}`` is ``2``.
 
 %
     Calculate the remainder of an integer division.  ``{{ 11 % 7 }}`` is ``4``.
index c9c482f109402dcadbd51bb91a5d9a46049605f9..80bbc628a050ee9f77cafa1fc4d140452c169d79 100755 (executable)
@@ -14,7 +14,10 @@ import jinja2
 from werkzeug import script
 
 env = jinja2.Environment(extensions=['jinja2.ext.i18n', 'jinja2.ext.do',
-                                     'jinja2.ext.loopcontrols'])
+                                     'jinja2.ext.loopcontrols',
+                                     'jinja2.ext.with_',
+                                     'jinja2.ext.autoescape'],
+                         autoescape=True)
 
 def shell_init_func():
     def _compile(x):
index 0f7f566c95cba96a350b5284e0382397ac7ced80..866568cff95c5cc427be05f5d94c3a7dca55f2eb 100644 (file)
@@ -20,7 +20,6 @@ import marshal
 import tempfile
 import cPickle as pickle
 import fnmatch
-from cStringIO import StringIO
 try:
     from hashlib import sha1
 except ImportError:
@@ -28,6 +27,26 @@ except ImportError:
 from jinja2.utils import open_if_exists
 
 
+# marshal works better on 3.x, one hack less required
+if sys.version_info > (3, 0):
+    from io import BytesIO
+    marshal_dump = marshal.dump
+    marshal_load = marshal.load
+else:
+    from cStringIO import StringIO as BytesIO
+
+    def marshal_dump(code, f):
+        if isinstance(f, file):
+            marshal.dump(code, f)
+        else:
+            f.write(marshal.dumps(code))
+
+    def marshal_load(f):
+        if isinstance(f, file):
+            return marshal.load(f)
+        return marshal.loads(f.read())
+
+
 bc_version = 2
 
 # magic version used to only change with new jinja versions.  With 2.6
@@ -71,12 +90,7 @@ class Bucket(object):
         if self.checksum != checksum:
             self.reset()
             return
-        # now load the code.  Because marshal is not able to load
-        # from arbitrary streams we have to work around that
-        if isinstance(f, file):
-            self.code = marshal.load(f)
-        else:
-            self.code = marshal.loads(f.read())
+        self.code = marshal_load(f)
 
     def write_bytecode(self, f):
         """Dump the bytecode into the file or file like object passed."""
@@ -84,18 +98,15 @@ class Bucket(object):
             raise TypeError('can\'t write empty bucket')
         f.write(bc_magic)
         pickle.dump(self.checksum, f, 2)
-        if isinstance(f, file):
-            marshal.dump(self.code, f)
-        else:
-            f.write(marshal.dumps(self.code))
+        marshal_dump(code, f)
 
     def bytecode_from_string(self, string):
         """Load bytecode from a string."""
-        self.load_bytecode(StringIO(string))
+        self.load_bytecode(BytesIO(string))
 
     def bytecode_to_string(self):
         """Return the bytecode as string."""
-        out = StringIO()
+        out = BytesIO()
         self.write_bytecode(out)
         return out.getvalue()
 
@@ -153,9 +164,10 @@ class BytecodeCache(object):
         """Returns the unique hash key for this template name."""
         hash = sha1(name.encode('utf-8'))
         if filename is not None:
+            filename = '|' + filename
             if isinstance(filename, unicode):
                 filename = filename.encode('utf-8')
-            hash.update('|' + filename)
+            hash.update(filename)
         return hash.hexdigest()
 
     def get_source_checksum(self, source):
index d257eca0a1e8a8e9ed5a65ac1c566d409727a06b..50510b0d353791c5dd3c3fd213cfc1545a9576cc 100644 (file)
 import re
 from jinja2.runtime import Undefined
 
+try:
+    from collections import Mapping as MappingType
+except ImportError:
+    import UserDict
+    MappingType = (UserDict.UserDict, UserDict.DictMixin, dict)
+
 # nose, nothing here to test
 __test__ = False
 
@@ -83,6 +89,14 @@ def test_string(value):
     return isinstance(value, basestring)
 
 
+def test_mapping(value):
+    """Return true if the object is a mapping (dict etc.).
+
+    .. versionadded:: 2.6
+    """
+    return isinstance(value, MappingType)
+
+
 def test_number(value):
     """Return true if the variable is a number."""
     return isinstance(value, (int, long, float, complex))
@@ -137,6 +151,7 @@ TESTS = {
     'lower':            test_lower,
     'upper':            test_upper,
     'string':           test_string,
+    'mapping':          test_mapping,
     'number':           test_number,
     'sequence':         test_sequence,
     'iterable':         test_iterable,
index cd5006fd37f1ec2f06017ade14bb8f1340ac0c59..3ece7a8ff71ddf03e7006a5bb450895521b19e94 100644 (file)
@@ -48,10 +48,16 @@ class TestsTestCase(JinjaTestCase):
             {{ range is callable }}
             {{ 42 is callable }}
             {{ range(5) is iterable }}
+            {{ {} is mapping }}
+            {{ mydict is mapping }}
+            {{ [] is mapping }}
         ''')
-        assert tmpl.render().split() == [
+        class MyDict(dict):
+            pass
+        assert tmpl.render(mydict=MyDict()).split() == [
             'False', 'True', 'False', 'True', 'True', 'False',
-            'True', 'True', 'True', 'True', 'False', 'True'
+            'True', 'True', 'True', 'True', 'False', 'True',
+            'True', 'True', 'False'
         ]
 
     def test_sequence(self):