Updated documentation for operator intercepting
authorArmin Ronacher <armin.ronacher@active-4.com>
Mon, 29 Nov 2010 13:29:00 +0000 (14:29 +0100)
committerArmin Ronacher <armin.ronacher@active-4.com>
Mon, 29 Nov 2010 13:29:00 +0000 (14:29 +0100)
docs/sandbox.rst
jinja2/environment.py

index bb0ca9fce9ce5a8081eea7a121cbd8aae9531b72..1302f18b1b86e1770cb738c7684c33d1a5952bb4 100644 (file)
@@ -14,11 +14,15 @@ Traceback (most recent call last):
   ...
 SecurityError: access to attribute 'func_code' of 'function' object is unsafe.
 
+API
+---
 
 .. module:: jinja2.sandbox
 
 .. autoclass:: SandboxedEnvironment([options])
-    :members: is_safe_attribute, is_safe_callable
+    :members: is_safe_attribute, is_safe_callable, default_binop_table,
+              default_unop_table, intercepted_binops, intercepted_unops,
+              call_binop, call_unop
 
 .. autoclass:: ImmutableSandboxedEnvironment([options])
 
@@ -44,3 +48,47 @@ SecurityError: access to attribute 'func_code' of 'function' object is unsafe.
 
     Also keep in mind that templates may raise runtime or compile time errors,
     so make sure to catch them.
+
+Operator Intercepting
+---------------------
+
+.. versionadded:: 2.6
+
+For maximum performace Jinja2 will let operators call directly the type
+specific callback methods.  This means that it's not possible to have this
+intercepted by overriding :meth:`Environment.call`.  Furthermore a
+conversion from operator to special method is not always directly possible
+due to how operators work.  For instance for divisions more than one
+special method exist.
+
+With Jinja 2.6 there is now support for explicit operator intercepting.
+This can be used to customize specific operators as necessary.  In order
+to intercept an operator one has to override the
+:attr:`SandboxedEnvironment.intercepted_binops` attribute.  Once the
+operator that needs to be intercepted is added to that set Jinja2 will
+generate bytecode that calls the :meth:`SandboxedEnvironment.call_binop`
+function.  For unary operators the `unary` attributes and methods have to
+be used instead.
+
+The default implementation of :attr:`SandboxedEnvironment.call_binop`
+will use the :attr:`SandboxedEnvironment.binop_table` to translate
+operator symbols into callbacks performing the default operator behavior.
+
+This example shows how the power (``**``) operator can be disabled in
+Jinja2::
+
+    from jinja2.sandbox import SandboxedEnvironment
+
+
+    class MyEnvironment(SandboxedEnvironment):
+        intercepted_binops = frozenset(['**'])
+
+        def call_binop(self, context, operator, left, right):
+            if operator == '**':
+                return self.undefined('the power operator is unavailable')
+            return SandboxedEnvironment.call_binop(self, context,
+                                                   operator, left, right)
+
+Make sure to always call into the super method, even if you are not
+intercepting the call.  Jinja2 might internally call the method to
+evaluate expressions.
index 2dd38ef9fa797ec4d9b98b9a997fdaeec48ab273..095329ee925097ec781a883179778fb5c6ad5af1 100644 (file)
@@ -196,7 +196,8 @@ class Environment(object):
 
     #: if this environment is sandboxed.  Modifying this variable won't make
     #: the environment sandboxed though.  For a real sandboxed environment
-    #: have a look at jinja2.sandbox
+    #: have a look at jinja2.sandbox.  This flag alone controls the code
+    #: generation by the compiler.
     sandboxed = False
 
     #: True if the environment is just an overlay