tputil.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. """
  2. application level support module for transparent proxies.
  3. """
  4. from __pypy__ import tproxy
  5. from types import MethodType
  6. _dummy = object()
  7. origtype = type
  8. def make_proxy(controller, type=_dummy, obj=_dummy):
  9. """ return a tranparent proxy controlled by the given
  10. 'controller' callable. The proxy will appear
  11. as a completely regular instance of the given
  12. type but all operations on it are send to the
  13. specified controller - which receives on
  14. ProxyOperation instance on each such call.
  15. A non-specified type will default to type(obj)
  16. if obj is specified.
  17. """
  18. if type is _dummy:
  19. if obj is _dummy:
  20. raise TypeError("you must specify a type or an instance obj of it")
  21. type = origtype(obj)
  22. def perform(opname, *args, **kwargs):
  23. operation = ProxyOperation(tp, obj, opname, args, kwargs)
  24. return controller(operation)
  25. tp = tproxy(type, perform)
  26. return tp
  27. class ProxyOperation(object):
  28. def __init__(self, proxyobj, obj, opname, args, kwargs):
  29. self.proxyobj = proxyobj
  30. self.opname = opname
  31. self.args = args
  32. self.kwargs = kwargs
  33. if obj is not _dummy:
  34. self.obj = obj
  35. def delegate(self):
  36. """ return result from delegating this operation to the
  37. underyling self.obj - which must exist and is usually
  38. provided through the initial make_proxy(..., obj=...)
  39. creation.
  40. """
  41. try:
  42. obj = getattr(self, 'obj')
  43. except AttributeError:
  44. raise TypeError("proxy does not have an underlying 'obj', "
  45. "cannot delegate")
  46. objattr = getattr(obj, self.opname)
  47. res = objattr(*self.args, **self.kwargs)
  48. if self.opname == "__getattribute__":
  49. if (isinstance(res, MethodType) and
  50. res.__self__ is self.instance):
  51. res = MethodType(res.__func__, self.proxyobj, res.__self__.__class__)
  52. if res is self.obj:
  53. res = self.proxyobj
  54. return res
  55. def __repr__(self):
  56. args = ", ".join([repr(x) for x in self.args])
  57. args = "<0x%x>, " % id(self.proxyobj) + args
  58. if self.kwargs:
  59. args += ", ".join(["%s=%r" % item
  60. for item in self.kwargs.items()])
  61. return "<ProxyOperation %s.%s(%s)>" %(
  62. type(self.proxyobj).__name__, self.opname, args)