[Zope3-checkins] CVS: Zope3/src/zope/proxy/context/tests - test_decorator.py:1.7

Steve Alexander steve@cat-box.net
Mon, 12 May 2003 11:00:07 -0400


Update of /cvs-repository/Zope3/src/zope/proxy/context/tests
In directory cvs.zope.org:/tmp/cvs-serv14584/src/zope/proxy/context/tests

Modified Files:
	test_decorator.py 
Log Message:
New "inner" member of Decorators, in preparation of support for untrusted
decorators.
Improved getattr and setattr code so that name can't be GCed during the
function call, and we're more strict about checking that name is a
string. (Or a unicode that can be coerced into a string.)
Used PyType_HasFeature to check if we're allowed to look at a descriptor's
class's tp_descr_{get,set} slots.


=== Zope3/src/zope/proxy/context/tests/test_decorator.py 1.6 => 1.7 ===
--- Zope3/src/zope/proxy/context/tests/test_decorator.py:1.6	Sun May 11 12:31:21 2003
+++ Zope3/src/zope/proxy/context/tests/test_decorator.py	Mon May 12 10:59:37 2003
@@ -24,8 +24,8 @@
     proxy_class = decorator.Decorator
 
     def new_proxy(self, o, c=None, mixinfactory=None, names=None,
-                  attrdict=None):
-        return self.proxy_class(o, c, mixinfactory, names, attrdict)
+                  attrdict=None, inner=None):
+        return self.proxy_class(o, c, mixinfactory, names, attrdict, inner)
 
     def test_subclass_constructor(self):
         class MyWrapper(self.proxy_class):
@@ -37,7 +37,7 @@
         self.assertEquals(wrapper.getdict(w), {'key': 'value'})
 
         # __new__ catches too many positional args:
-        self.assertRaises(TypeError, MyWrapper, 1, 2, 3, 4, 5, 6)
+        self.assertRaises(TypeError, MyWrapper, 1, 2, 3, 4, 5, 6, 7)
 
     def test_decorator_basics(self):
         # check that default arguments are set correctly as per the interface
@@ -47,6 +47,7 @@
         self.assert_(decorator.getmixin(w) is None)
         self.assertEquals(decorator.getnames(w), ())
         self.assert_(decorator.getmixinfactory(w) is None)
+        self.assert_(decorator.getinner(w) is obj)
 
         # getnamesdict is not in the official decorator interface, but it
         # is provided so that the caching dict can be unit-tested from Python.
@@ -75,7 +76,8 @@
         f = MixinFactory
         n = ('foo',)
         ad = {'baz':23}
-        w = self.proxy_class(obj, c, f, n, ad)
+        inner = object()
+        w = self.proxy_class(obj, c, f, n, ad, inner)
 
         keys = decorator.getnamesdict(w).keys()
         keys.sort()
@@ -86,6 +88,7 @@
         self.assert_(decorator.getmixin(w) is None)
         self.assertEquals(decorator.getnames(w), n)
         self.assert_(decorator.getmixinfactory(w) is f)
+        self.assert_(decorator.getinner(w) is inner)
 
         # Check that accessing a non-name does not create the mixin.
         w.bar()
@@ -101,15 +104,19 @@
         self.assert_(type(mixin) is MixinFactory)
 
         # Check that the mixin factory is constructed with the correct args.
-        self.assert_(mixin.inner is obj)
+        self.assert_(mixin.inner is inner)
         self.assert_(mixin.outer is w)
 
-        # check that getmixincreate works
-        w = self.proxy_class(obj, c, f, n)
+        # check that getmixincreate works, and incidentally that getinner
+        # returns the same as getobject when there is no inner specified
+
+        # note, neither 'attrdict' nor 'inner' given
+        w = self.proxy_class(obj, c, f, n, None, None)
         self.assert_(decorator.getmixin(w) is None)
         mixin = decorator.getmixincreate(w)
         self.assert_(type(mixin) is MixinFactory)
         self.assert_(decorator.getmixin(w) is mixin)
+        self.assert_(mixin.inner is obj)
 
     def test_mixin_created_once_only(self):
         class SomeObject(object):
@@ -118,13 +125,10 @@
         obj = SomeObject()
 
         class MixinFactory(object):
-            def __init__(self, inner, outer):
-                self.someinstanceattr = 42
             def foo(self):
                 pass
             def bar(self):
                 pass
-            spoo = 23
 
         c = object()
         f = MixinFactory
@@ -140,9 +144,59 @@
         w.foo()
         mixin2 = decorator.getmixin(w)
         self.assert_(mixin is mixin2)
+
+    def test_getattrAspectsThatAreNotTestedElsewhere(self):
+        class SomeObject(object):
+            def bar(self):
+                pass
+        obj = SomeObject()
+
+        class MixinFactory(object):
+            def __init__(self, inner, outer):
+                self.someinstanceattr = 42
+            def foo(self):
+                pass
+            def bar(self):
+                pass
+            spoo = 23
+
+        c = object()
+        f = MixinFactory
+        n = ('foo', 'spoo', 'someinstanceattr')
+        w = self.proxy_class(obj, c, f, n)
+
         self.assertEqual(w.spoo, 23)
+        # Check that getting a unicode attr is handled correctly.
+        self.assertEqual(getattr(w, u'spoo'), 23)
+
         # Check that an attribute on the mixin object can be retrieved.
         self.assertEquals(w.someinstanceattr, 42)
+        self.assertEquals(getattr(w, u'someinstanceattr'), 42)
+
+    def test_horribleUnicodeAbuse(self):
+        class SomeObject(object):
+            def bar(self):
+                pass
+        obj = SomeObject()
+
+        class MixinFactory(object):
+            def __init__(self, inner, outer):
+                self.someinstanceattr = 42
+            def foo(self):
+                pass
+            def bar(self):
+                pass
+            spoo = 23
+
+        c = object()
+        f = MixinFactory
+        n = ('foo', 'spoo', u's\u2323g', 'someinstanceattr')
+        self.assertRaises(TypeError, self.proxy_class, obj, c, f, n)
+        n = ('foo', 'spoo', 'someinstanceattr')
+        w = self.proxy_class(obj, c, f, n)
+        self.assertRaises(UnicodeError, getattr, w, u's\u2323g')
+        self.assertRaises(UnicodeError, setattr, w, u's\u2323g', 23)
+
 
     def test_typeerror_if_no_factory(self):
         w = self.proxy_class(object(), None, None, ('foo',))
@@ -150,6 +204,8 @@
         self.assertRaises(TypeError, decorator.getmixincreate)
 
     def test_decorator_setattr(self):
+        # setattr includes delattr, seeing as we're testing something written
+        # in C, and delattr is a special case of setattr at the C level.
         obj = object()
 
         class MixinFactory(object):
@@ -171,6 +227,12 @@
         w.foo = 'skidoo'
         self.assertEquals(mixin.fooval, 'skidoo')
         del w.foo
+        self.failIf(hasattr(mixin, 'fooval'))
+
+        # test setattr unicode attr string
+        setattr(w, u'foo', 'skidoo')
+        self.assertEquals(mixin.fooval, 'skidoo')
+        delattr(w, u'foo')
         self.failIf(hasattr(mixin, 'fooval'))
 
         # Check that trying to set something in attrdict fails.