Added support for optional `scoped` modifier to blocks.

--HG--
branch : trunk
diff --git a/jinja2/compiler.py b/jinja2/compiler.py
index 20ac03b..6b9c786 100644
--- a/jinja2/compiler.py
+++ b/jinja2/compiler.py
@@ -783,8 +783,12 @@
                 self.writeline('if parent_template is None:')
                 self.indent()
                 level += 1
-        self.writeline('for event in context.blocks[%r][0](context):' %
-                       node.name, node)
+        if node.scoped:
+            context = 'context.derived(locals())'
+        else:
+            context = 'context'
+        self.writeline('for event in context.blocks[%r][0](%s):' % (
+                       node.name, context), node)
         self.indent()
         self.simple_write('event', frame)
         self.outdent(level)
diff --git a/jinja2/environment.py b/jinja2/environment.py
index 3c53fbd..fcc11d2 100644
--- a/jinja2/environment.py
+++ b/jinja2/environment.py
@@ -15,7 +15,7 @@
 from jinja2.parser import Parser
 from jinja2.optimizer import optimize
 from jinja2.compiler import generate
-from jinja2.runtime import Undefined, Context
+from jinja2.runtime import Undefined, new_context
 from jinja2.exceptions import TemplateSyntaxError
 from jinja2.utils import import_string, LRUCache, Markup, missing, \
      concat, consume
@@ -646,21 +646,8 @@
 
         `locals` can be a dict of local variables for internal usage.
         """
-        if vars is None:
-            vars = {}
-        if shared:
-            parent = vars
-        else:
-            parent = dict(self.globals, **vars)
-        if locals:
-            # if the parent is shared a copy should be created because
-            # we don't want to modify the dict passed
-            if shared:
-                parent = dict(parent)
-            for key, value in locals.iteritems():
-                if key[:2] == 'l_' and value is not missing:
-                    parent[key[2:]] = value
-        return Context(self.environment, parent, self.name, self.blocks)
+        return new_context(self.environment, self.name, self.blocks,
+                           vars, shared, self.globals, locals)
 
     def make_module(self, vars=None, shared=False, locals=None):
         """This method works like the :attr:`module` attribute when called
diff --git a/jinja2/nodes.py b/jinja2/nodes.py
index 6383372..c7858b6 100644
--- a/jinja2/nodes.py
+++ b/jinja2/nodes.py
@@ -269,7 +269,7 @@
 
 class Block(Stmt):
     """A node that represents a block."""
-    fields = ('name', 'body')
+    fields = ('name', 'body', 'scoped')
 
 
 class Include(Stmt):
diff --git a/jinja2/parser.py b/jinja2/parser.py
index d3eb8c4..f3de6e7 100644
--- a/jinja2/parser.py
+++ b/jinja2/parser.py
@@ -149,6 +149,7 @@
     def parse_block(self):
         node = nodes.Block(lineno=self.stream.next().lineno)
         node.name = self.stream.expect('name').value
+        node.scoped = self.stream.skip_if('name:scoped')
         node.body = self.parse_statements(('name:endblock',), drop_needle=True)
         self.stream.skip_if('name:' + node.name)
         return node
diff --git a/jinja2/runtime.py b/jinja2/runtime.py
index 60a9035..013d987 100644
--- a/jinja2/runtime.py
+++ b/jinja2/runtime.py
@@ -17,7 +17,7 @@
 
 
 # these variables are exported to the template runtime
-__all__ = ['LoopContext', 'Context', 'TemplateReference', 'Macro', 'Markup',
+__all__ = ['LoopContext', 'TemplateReference', 'Macro', 'Markup',
            'TemplateRuntimeError', 'missing', 'concat', 'escape',
            'markup_join', 'unicode_join', 'TemplateNotFound']
 
@@ -42,6 +42,45 @@
     return concat(imap(unicode, seq))
 
 
+def new_context(environment, template_name, blocks, vars=None,
+                shared=None, globals=None, locals=None):
+    """Internal helper to for context creation."""
+    if vars is None:
+        vars = {}
+    if shared:
+        parent = vars
+    else:
+        parent = dict(globals or (), **vars)
+    if locals:
+        # if the parent is shared a copy should be created because
+        # we don't want to modify the dict passed
+        if shared:
+            parent = dict(parent)
+        for key, value in locals.iteritems():
+            if key[:2] == 'l_' and value is not missing:
+                parent[key[2:]] = value
+    return Context(environment, parent, template_name, blocks)
+
+
+class TemplateReference(object):
+    """The `self` in templates."""
+
+    def __init__(self, context):
+        self.__context = context
+
+    def __getitem__(self, name):
+        blocks = self.__context.blocks[name]
+        wrap = self.__context.environment.autoescape and \
+               Markup or (lambda x: x)
+        return BlockReference(name, self.__context, blocks, 0)
+
+    def __repr__(self):
+        return '<%s %r>' % (
+            self.__class__.__name__,
+            self.__context.name
+        )
+
+
 class Context(object):
     """The template context holds the variables of a template.  It stores the
     values passed to the template and also the names the template exports.
@@ -132,6 +171,11 @@
                 args = (__self.environment,) + args
         return __obj(*args, **kwargs)
 
+    def derived(self, locals=None):
+        """Internal helper function to create a derived context."""
+        return new_context(self.environment, self.name, self.blocks,
+                           self.parent, True, None, locals)
+
     def _all(meth):
         proxy = lambda self: getattr(self.get_all(), meth)()
         proxy.__doc__ = getattr(dict, meth).__doc__
@@ -174,25 +218,6 @@
     pass
 
 
-class TemplateReference(object):
-    """The `self` in templates."""
-
-    def __init__(self, context):
-        self.__context = context
-
-    def __getitem__(self, name):
-        blocks = self.__context.blocks[name]
-        wrap = self.__context.environment.autoescape and \
-               Markup or (lambda x: x)
-        return BlockReference(name, self.__context, blocks, 0)
-
-    def __repr__(self):
-        return '<%s %r>' % (
-            self.__class__.__name__,
-            self.__context.name
-        )
-
-
 class BlockReference(object):
     """One block on a template reference."""