Skip to content

Commit

Permalink
100% coverage for _proxy.py.
Browse files Browse the repository at this point in the history
Also convert test_contained.py doctests to real tests for ease of addition and debugging #13.
  • Loading branch information
jamadden committed Jul 27, 2017
1 parent 14b41f5 commit 1e834e7
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 100 deletions.
2 changes: 2 additions & 0 deletions src/zope/container/contained.py
Expand Up @@ -32,8 +32,10 @@
try:
from zope.container._zope_container_contained import ContainedProxyBase
from zope.container._zope_container_contained import getProxiedObject
from zope.container._zope_container_contained import setProxiedObject
except ImportError: # PyPy
from zope.container._proxy import py_getProxiedObject as getProxiedObject
from zope.container._proxy import py_setProxiedObject as setProxiedObject
from zope.container._proxy import PyContainedProxyBase as ContainedProxyBase

from zope.lifecycleevent import ObjectMovedEvent
Expand Down
190 changes: 90 additions & 100 deletions src/zope/container/tests/test_contained.py
Expand Up @@ -13,132 +13,127 @@
##############################################################################
"""Contained Tests
"""

from __future__ import absolute_import
import doctest
import gc

import unittest

from persistent import Persistent

import zope.interface
import zope.component

from zope.container.contained import ContainedProxy, NameChooser
from zope.container.contained import ContainedProxy
from zope.container.contained import NameChooser
from zope.container.sample import SampleContainer
from zope.container import testing
from zope.container.interfaces import NameReserved, IContainer, IReservedNames

class MyOb(Persistent):
pass

def test_basic_proxy_attribute_management_and_picklability():
"""Contained-object proxy
This is a picklable proxy that can be put around objects that
don't implement IContained.
>>> l = [1, 2, 3]
>>> p = ContainedProxy(l)
>>> p.__parent__ = 'Dad'
>>> p.__name__ = 'p'
>>> p
[1, 2, 3]
>>> p.__parent__
'Dad'
>>> p.__name__
'p'

>>> import pickle
>>> p2 = pickle.loads(pickle.dumps(p))
>>> p2
[1, 2, 3]
>>> p2.__parent__
'Dad'
>>> p2.__name__
'p'
"""
class TestContainedProxy(unittest.TestCase):

def test_basic_proxy_attribute_management_and_picklability(self):
# Contained-object proxy

# This is a picklable proxy that can be put around objects that
# don't implement IContained.

l = [1, 2, 3]
p = ContainedProxy(l)
p.__parent__ = 'Dad'
p.__name__ = 'p'
self.assertEqual([1, 2, 3], p)
self.assertEqual('Dad', p.__parent__)
self.assertEqual('p', p.__name__)

import pickle
p2 = pickle.loads(pickle.dumps(p))
self.assertEqual([1, 2, 3], p2)
self.assertEqual('Dad', p2.__parent__)
self.assertEqual('p', p2.__name__)

def test_declarations_on_ContainedProxy():
r"""
def test_declarations_on_ContainedProxy(self):
# It is possible to make declarations on ContainedProxy objects.
from zope.container.interfaces import IContained
from persistent.interfaces import IPersistent

It is possible to make declarations on ContainedProxy objects.
class I1(zope.interface.Interface):
pass
@zope.interface.implementer(I1)
class C(object):
pass

>>> class I1(zope.interface.Interface):
... pass
>>> @zope.interface.implementer(I1)
... class C(object):
... pass
c = C()
p = ContainedProxy(c)

>>> c = C()
>>> p = ContainedProxy(c)
# ContainedProxy provides no interfaces on it's own:

ContainedProxy provides no interfaces on it's own:
self.assertEqual((),
tuple(zope.interface.providedBy(ContainedProxy)))

>>> tuple(zope.interface.providedBy(ContainedProxy))
()

It implements IContained and IPersistent:
# It implements IContained and IPersistent:
self.assertEqual((IContained, IPersistent),
tuple(zope.interface.implementedBy(ContainedProxy)))

>>> tuple(zope.interface.implementedBy(ContainedProxy))
(<InterfaceClass zope.location.interfaces.IContained>,
<InterfaceClass persistent.interfaces.IPersistent>)
# A proxied object has IContainer, in addition to what the unproxied
# object has:
self.assertEqual(tuple(zope.interface.providedBy(p)),
(I1, IContained, IPersistent))

A proxied object has IContainer, in addition to what the unproxied
object has:
class I2(zope.interface.Interface):
pass
zope.interface.directlyProvides(c, I2)
self.assertEqual(tuple(zope.interface.providedBy(p)),
(I2, I1, IContained, IPersistent))

>>> tuple(zope.interface.providedBy(p))
(<InterfaceClass zope.container.tests.test_contained.I1>,
<InterfaceClass zope.location.interfaces.IContained>,
<InterfaceClass persistent.interfaces.IPersistent>)
# We can declare interfaces through the proxy:

>>> class I2(zope.interface.Interface):
... pass
>>> zope.interface.directlyProvides(c, I2)
>>> tuple(zope.interface.providedBy(p))
(<InterfaceClass zope.container.tests.test_contained.I2>,
<InterfaceClass zope.container.tests.test_contained.I1>,
<InterfaceClass zope.location.interfaces.IContained>,
<InterfaceClass persistent.interfaces.IPersistent>)
class I3(zope.interface.Interface):
pass
zope.interface.directlyProvides(p, I3)
self.assertEqual(tuple(zope.interface.providedBy(p)),
(I3, I1, IContained, IPersistent))

We can declare interfaces through the proxy:

>>> class I3(zope.interface.Interface):
... pass
>>> zope.interface.directlyProvides(p, I3)
>>> tuple(zope.interface.providedBy(p))
(<InterfaceClass zope.container.tests.test_contained.I3>,
<InterfaceClass zope.container.tests.test_contained.I1>,
<InterfaceClass zope.location.interfaces.IContained>,
<InterfaceClass persistent.interfaces.IPersistent>)
def test_ContainedProxy_instances_have_no_instance_dictionaries(self):
# Make sure that proxies don't introduce extra instance dictionaries
class C(object):
pass

"""
c = C()
c.x = 1
self.assertEqual(dict(c.__dict__), {'x': 1})

p = ContainedProxy(c)
self.assertEqual(dict(p.__dict__), {'x': 1})

def test_ContainedProxy_instances_have_no_instance_dictionaries():
"""Make sure that proxies don't introduce extra instance dictionaries
p.y = 3
self.assertEqual(dict(p.__dict__), {'x': 1, 'y': 3})
self.assertEqual(dict(c.__dict__), {'x': 1, 'y': 3})

>>> from zope.container.contained import ContainedProxy
>>> class C:
... pass
self.assertIs(p.__dict__, c.__dict__)

>>> c = C()
>>> c.x = 1
>>> c.__dict__
{'x': 1}
def test_get_set_ProxiedObject(self):
from zope.container.contained import getProxiedObject
from zope.container.contained import setProxiedObject

proxy = ContainedProxy(self)
self.assertIs(self, getProxiedObject(proxy))

o = object()
self.assertIs(o, getProxiedObject(o))

old = setProxiedObject(proxy, o)
self.assertIs(self, old)
self.assertIs(o, getProxiedObject(proxy))

with self.assertRaises(TypeError):
setProxiedObject(self, 1)

>>> p = ContainedProxy(c)
>>> p.__dict__
{'x': 1}
>>> p.y = 3
>>> sorted(p.__dict__.items())
[('x', 1), ('y', 3)]
>>> sorted(c.__dict__.items())
[('x', 1), ('y', 3)]
>>> p.__dict__ is c.__dict__
True
"""


class TestNameChooser(unittest.TestCase):
Expand Down Expand Up @@ -216,7 +211,7 @@ def test_chooseName(self):
self.assertEqual(nc.chooseName(None, None), u'None-3')

# even if the given name cannot be converted to unicode
class BadBoy:
class BadBoy(object):
def __unicode__(self):
raise Exception
# Py3: Support
Expand All @@ -226,14 +221,9 @@ def __unicode__(self):


def test_suite():
suite = unittest.TestSuite((
unittest.makeSuite(TestNameChooser),
))
suite.addTest(doctest.DocTestSuite(
'zope.container.contained',
setUp=testing.setUp, tearDown=testing.tearDown,
checker=testing.checker))
suite = unittest.defaultTestLoader.loadTestsFromName(__name__)
suite.addTest(doctest.DocTestSuite(
optionflags=doctest.NORMALIZE_WHITESPACE,
'zope.container.contained',
setUp=testing.setUp, tearDown=testing.tearDown,
checker=testing.checker))
return suite

0 comments on commit 1e834e7

Please sign in to comment.