zope.proxy Narrative Documentation

Subclassing ProxyBase

If you subclass a proxy, instances of the subclass have access to data defined in the class, including descriptors.

Your subclass instances don’t get instance dictionaries, but they can have slots.

>>> from zope.proxy import ProxyBase
>>> class MyProxy(ProxyBase):
...    __slots__ = 'x', 'y'
...
...    def f(self):
...        return self.x

>>> l = [1, 2, 3]
>>> p = MyProxy(l)

You can use attributes defined by the class, including slots:

>>> p.x = 'x'
>>> p.x
'x'
>>> p.f()
'x'

You can also use attributes of the proxied object:

>>> p
[1, 2, 3]
>>> p.pop()
3
>>> p
[1, 2]

Using get descriptors in proxy classes

A non-data descriptor in a proxy class doesn’t hide an attribute on a proxied object or prevent writing the attribute.

>>> class ReadDescr(object):
...     def __get__(self, i, c):
...         return 'read'

>>> from zope.proxy import ProxyBase
>>> class MyProxy(ProxyBase):
...    __slots__ = ()
...
...    z = ReadDescr()
...    q = ReadDescr()

>>> class MyOb:
...    q = 1

>>> o = MyOb()
>>> p = MyProxy(o)
>>> p.q
1

>>> p.z
'read'

>>> p.z = 1
>>> o.z, p.z
(1, 1)

Marking proxy attributes as non-overridable

Normally, methods defined in proxies are overridden by methods of proxied objects. This applies to all non-data descriptors. The non_overridable function can be used to convert a non-data descriptor to a data descriptor that disallows writes. This function can be used as a decorator to make functions defined in proxy classes take precedence over functions defined in proxied objects.

>>> from zope.proxy import ProxyBase
>>> from zope.proxy import non_overridable
>>> class MyProxy(ProxyBase):
...    __slots__ = ()
...
...    @non_overridable
...    def foo(self):
...        return 'MyProxy foo'

>>> class MyOb:
...    def foo(self):
...        return 'MyOb foo'

>>> o = MyOb()
>>> p = MyProxy(o)
>>> p.foo()
'MyProxy foo'

Changing the proxied object

>>> from zope.proxy import ProxyBase
>>> from zope.proxy import setProxiedObject, getProxiedObject

>>> class C(object):
...     pass

>>> c1 = C()
>>> c2 = C()

>>> p = ProxyBase(c1)

setProxiedObject() allows us to change the object a proxy refers to, returning the previous referent:

>>> old = setProxiedObject(p, c2)
>>> old is c1
True

>>> getProxiedObject(p) is c2
True

The first argument to setProxiedObject() must be a proxy; other objects cause it to raise an exception:

>>> try:
...     setProxiedObject(c1, None)
... except TypeError:
...     print("TypeError raised")
... else:
...     print("Expected TypeError not raised")
TypeError raised