[Checkins] SVN: RestrictedPython/trunk/src/RestrictedPython/ - Add some tests for features new in 2.5 and 2.6

Sidnei da Silva sidnei at enfoldsystems.com
Mon Oct 13 12:28:53 EDT 2008


Log message for revision 92122:
   - Add some tests for features new in 2.5 and 2.6

Changed:
  U   RestrictedPython/trunk/src/RestrictedPython/Guards.py
  U   RestrictedPython/trunk/src/RestrictedPython/RestrictionMutator.py
  A   RestrictedPython/trunk/src/RestrictedPython/tests/before_and_after25.py
  A   RestrictedPython/trunk/src/RestrictedPython/tests/before_and_after26.py
  A   RestrictedPython/trunk/src/RestrictedPython/tests/security_in_syntax26.py
  U   RestrictedPython/trunk/src/RestrictedPython/tests/testRestrictions.py
  U   RestrictedPython/trunk/src/RestrictedPython/tests/verify.py

-=-
Modified: RestrictedPython/trunk/src/RestrictedPython/Guards.py
===================================================================
--- RestrictedPython/trunk/src/RestrictedPython/Guards.py	2008-10-13 14:16:48 UTC (rev 92121)
+++ RestrictedPython/trunk/src/RestrictedPython/Guards.py	2008-10-13 16:28:51 UTC (rev 92122)
@@ -46,6 +46,8 @@
 # max
 # min
 # sum
+# all
+# any
 
 # Builtins that are intentionally disabled
 # compile   - don't let them produce new code

Modified: RestrictedPython/trunk/src/RestrictedPython/RestrictionMutator.py
===================================================================
--- RestrictedPython/trunk/src/RestrictedPython/RestrictionMutator.py	2008-10-13 14:16:48 UTC (rev 92121)
+++ RestrictedPython/trunk/src/RestrictedPython/RestrictionMutator.py	2008-10-13 16:28:51 UTC (rev 92122)
@@ -400,4 +400,3 @@
             if asname:
                 self.checkName(node, asname)
         return node
-

Added: RestrictedPython/trunk/src/RestrictedPython/tests/before_and_after25.py
===================================================================
--- RestrictedPython/trunk/src/RestrictedPython/tests/before_and_after25.py	                        (rev 0)
+++ RestrictedPython/trunk/src/RestrictedPython/tests/before_and_after25.py	2008-10-13 16:28:51 UTC (rev 92122)
@@ -0,0 +1,34 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Restricted Python transformation examples
+
+This module contains pairs of functions. Each pair has a before and an
+after function.  The after function shows the source code equivalent
+of the before function after it has been modified by the restricted
+compiler.
+
+These examples are actually used in the testRestrictions.py
+checkBeforeAndAfter() unit tests, which verifies that the restricted compiler
+actually produces the same output as would be output by the normal compiler
+for the after function.
+
+$Id: before_and_after24.py 76322 2007-06-04 17:40:03Z philikon $
+"""
+
+def simple_ternary_if_before():
+    x.y = y.z if y.z else y.x
+
+def simple_ternary_if_after():
+    _write_(x).y = _getattr_(y, 'z') if _getattr_(y, 'z') else _getattr_(y, 'x')
+


Property changes on: RestrictedPython/trunk/src/RestrictedPython/tests/before_and_after25.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: RestrictedPython/trunk/src/RestrictedPython/tests/before_and_after26.py
===================================================================
--- RestrictedPython/trunk/src/RestrictedPython/tests/before_and_after26.py	                        (rev 0)
+++ RestrictedPython/trunk/src/RestrictedPython/tests/before_and_after26.py	2008-10-13 16:28:51 UTC (rev 92122)
@@ -0,0 +1,51 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Restricted Python transformation examples
+
+This module contains pairs of functions. Each pair has a before and an
+after function.  The after function shows the source code equivalent
+of the before function after it has been modified by the restricted
+compiler.
+
+These examples are actually used in the testRestrictions.py
+checkBeforeAndAfter() unit tests, which verifies that the restricted compiler
+actually produces the same output as would be output by the normal compiler
+for the after function.
+
+$Id: before_and_after24.py 76322 2007-06-04 17:40:03Z philikon $
+"""
+
+def simple_context_before():
+    with whatever as x:
+        x.y = z
+
+def simple_context_after():
+    with whatever as x:
+        _write_(x).y = z
+
+def simple_context_assign_attr_before():
+    with whatever as x.y:
+        x.y = z
+
+def simple_context_assign_attr_after():
+    with whatever as _write_(x).y:
+        _write_(x).y = z
+
+def simple_context_load_attr_before():
+    with whatever.w as z:
+        x.y = z
+
+def simple_context_load_attr_after():
+    with _getattr_(whatever, 'w') as z:
+        _write_(x).y = z


Property changes on: RestrictedPython/trunk/src/RestrictedPython/tests/before_and_after26.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: RestrictedPython/trunk/src/RestrictedPython/tests/security_in_syntax26.py
===================================================================
--- RestrictedPython/trunk/src/RestrictedPython/tests/security_in_syntax26.py	                        (rev 0)
+++ RestrictedPython/trunk/src/RestrictedPython/tests/security_in_syntax26.py	2008-10-13 16:28:51 UTC (rev 92122)
@@ -0,0 +1,7 @@
+# These are all supposed to raise a SyntaxError when using
+# compile_restricted() but not when using compile().
+# Each function in this module is compiled using compile_restricted().
+
+def with_as_bad_name():
+    with x as _leading_underscore:
+        pass


Property changes on: RestrictedPython/trunk/src/RestrictedPython/tests/security_in_syntax26.py
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: RestrictedPython/trunk/src/RestrictedPython/tests/testRestrictions.py
===================================================================
--- RestrictedPython/trunk/src/RestrictedPython/tests/testRestrictions.py	2008-10-13 14:16:48 UTC (rev 92121)
+++ RestrictedPython/trunk/src/RestrictedPython/tests/testRestrictions.py	2008-10-13 16:28:51 UTC (rev 92122)
@@ -274,6 +274,11 @@
                     self.fail('%s() did not trip security' % k)
 
     def checkSyntaxSecurity(self):
+        self._checkSyntaxSecurity('security_in_syntax.py')
+        if sys.version_info >= (2, 6):
+            self._checkSyntaxSecurity('security_in_syntax26.py')
+
+    def _checkSyntaxSecurity(self, mod_name):
         # Ensures that each of the functions in security_in_syntax.py
         # throws a SyntaxError when using compile_restricted.
         fn = os.path.join(_HERE, 'security_in_syntax.py')
@@ -358,25 +363,23 @@
             rm.compile()
             verify.verify(rm.getCode())
 
-    if sys.version_info[:2] >= (2, 4):
-        def checkBeforeAndAfter24(self):
+    def _checkBeforeAndAfter(self, mod):
             from RestrictedPython.RCompile import RModule
-            from RestrictedPython.tests import before_and_after24
             from compiler import parse
 
             defre = re.compile(r'def ([_A-Za-z0-9]+)_(after|before)\(')
 
-            beforel = [name for name in before_and_after24.__dict__
+            beforel = [name for name in mod.__dict__
                        if name.endswith("_before")]
 
             for name in beforel:
-                before = getattr(before_and_after24, name)
+                before = getattr(mod, name)
                 before_src = get_source(before)
                 before_src = re.sub(defre, r'def \1(', before_src)
                 rm = RModule(before_src, '')
                 tree_before = rm._get_tree()
 
-                after = getattr(before_and_after24, name[:-6]+'after')
+                after = getattr(mod, name[:-6]+'after')
                 after_src = get_source(after)
                 after_src = re.sub(defre, r'def \1(', after_src)
                 tree_after = parse(after_src)
@@ -386,6 +389,21 @@
                 rm.compile()
                 verify.verify(rm.getCode())
 
+    if sys.version_info[:2] >= (2, 4):
+        def checkBeforeAndAfter24(self):
+            from RestrictedPython.tests import before_and_after24
+            self._checkBeforeAndAfter(before_and_after24)
+
+    if sys.version_info[:2] >= (2, 5):
+        def checkBeforeAndAfter25(self):
+            from RestrictedPython.tests import before_and_after25
+            self._checkBeforeAndAfter(before_and_after25)
+
+    if sys.version_info[:2] >= (2, 6):
+        def checkBeforeAndAfter26(self):
+            from RestrictedPython.tests import before_and_after26
+            self._checkBeforeAndAfter(before_and_after26)
+
     def _compile_file(self, name):
         path = os.path.join(_HERE, name)
         f = open(path, "r")

Modified: RestrictedPython/trunk/src/RestrictedPython/tests/verify.py
===================================================================
--- RestrictedPython/trunk/src/RestrictedPython/tests/verify.py	2008-10-13 14:16:48 UTC (rev 92121)
+++ RestrictedPython/trunk/src/RestrictedPython/tests/verify.py	2008-10-13 16:28:51 UTC (rev 92122)
@@ -46,6 +46,7 @@
     line = code.co_firstlineno
     # keep a window of the last three opcodes, with the most recent first
     window = (None, None, None)
+    with_context = (None, None)
 
     for op in disassemble(code):
         if op.line is not None:
@@ -54,11 +55,28 @@
             # All the user code that generates LOAD_ATTR should be
             # rewritten, but the code generated for a list comp
             # includes a LOAD_ATTR to extract the append method.
-            if not (op.arg == "append" and
-                    window[0].opname == "DUP_TOP" and
-                    window[1].opname == "BUILD_LIST"):
+            # Another exception is the new-in-Python 2.6 'context
+            # managers', which do a LOAD_ATTR for __exit__ and
+            # __enter__.
+            if op.arg == "__exit__":
+                with_context = (op, with_context[1])
+            elif op.arg == "__enter__":
+                with_context = (with_context[0], op)
+            elif not ((op.arg == "__enter__" and
+                       window[0].opname == "ROT_TWO" and
+                       window[1].opname == "DUP_TOP") or 
+                      (op.arg == "append" and
+                       window[0].opname == "DUP_TOP" and
+                       window[1].opname == "BUILD_LIST")):
                 raise ValueError("direct attribute access %s: %s, %s:%d"
-                                 % (op.opname, op.arg, co.co_filename, line))
+                                 % (op.opname, op.arg, code.co_filename, line))
+        if op.opname in ("WITH_CLEANUP"):
+            # Here we check if the LOAD_ATTR for __exit__ and
+            # __enter__ were part of a 'with' statement by checking
+            # for the 'WITH_CLEANUP' bytecode. If one is seen, we
+            # clear the with_context variable and let it go. The
+            # access was safe.
+            with_context = (None, None)
         if op.opname in ("STORE_ATTR", "DEL_ATTR"):
             if not (window[0].opname == "CALL_FUNCTION" and
                     window[2].opname == "LOAD_GLOBAL" and
@@ -90,6 +108,16 @@
 
         window = (op,) + window[:2]
 
+    if not with_context == (None, None):
+        # An access to __enter__ and __exit__ was performed but not as
+        # part of a 'with' statement. This is not allowed.
+        for op in with_context:
+            if op is not None:
+                if op.line is not None:
+                    line = op.line
+                raise ValueError("direct attribute access %s: %s, %s:%d"
+                                 % (op.opname, op.arg, code.co_filename, line))
+
 class Op(object):
     __slots__ = (
         "opname",  # string, name of the opcode



More information about the Checkins mailing list