Improved attribute and item lookup by allowing template designers to express the priority.  foo.bar checks foo.bar first and then foo['bar'] and the other way round.

--HG--
branch : trunk
diff --git a/jinja2/environment.py b/jinja2/environment.py
index acb5c02..689bc92 100644
--- a/jinja2/environment.py
+++ b/jinja2/environment.py
@@ -286,8 +286,8 @@
         """Return a fresh lexer for the environment."""
         return Lexer(self)
 
-    def subscribe(self, obj, argument):
-        """Get an item or attribute of an object."""
+    def getitem(self, obj, argument):
+        """Get an item or attribute of an object but prefer the item."""
         try:
             return obj[argument]
         except (TypeError, LookupError):
@@ -303,6 +303,19 @@
                         pass
             return self.undefined(obj=obj, name=argument)
 
+    def getattr(self, obj, attribute):
+        """Get an item or attribute of an object but prefer the attribute.
+        Unlike :meth:`getitem` the attribute *must* be a bytestring.
+        """
+        try:
+            return getattr(obj, attribute)
+        except AttributeError:
+            pass
+        try:
+            return obj[attribute]
+        except (TypeError, LookupError):
+            return self.undefined(obj=obj, name=attribute)
+
     def parse(self, source, name=None, filename=None):
         """Parse the sourcecode and return the abstract syntax tree.  This
         tree of nodes is used by the compiler to convert the template into