Advertisement
Guest User

Untitled

a guest
Jul 1st, 2015
178
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.83 KB | None | 0 0
  1. import functools
  2. import collections
  3.  
  4. class Proxy(type):
  5. __special_names__ = {
  6. '__abs__', '__add__', '__and__', '__call__', '__cmp__', '__coerce__',
  7. '__contains__', '__delitem__', '__delslice__', '__div__', '__divmod__',
  8. '__eq__', '__float__', '__floordiv__', '__ge__', '__getitem__', '__getslice__',
  9. '__gt__', '__hash__', '__hex__', '__int__', '__iter__', '__le__', '__len__',
  10. '__long__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__',
  11. '__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__',
  12. '__rdivmod__', '__reduce__', '__reduce_ex__', '__reversed__',
  13. '__rfloorfiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__',
  14. '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setitem__',
  15. '__setslice__', '__sub__', '__truediv__', '__xor__', '__next__'
  16. }
  17. __imethods__ = {
  18. '__iadd__', '__iand__', '__idiv__', '__idivmod__',
  19. '__ifloordiv__', '__ilshift__', '__imod__', '__imul__',
  20. '__invert__', '__ior__', '__ipow__', '__irshift__',
  21. '__isub__', '__itruediv__', '__ixor__'
  22. }
  23. __other_magic__ = {
  24. '__int__',
  25. '__long__',
  26. '__float__',
  27. '__complex__',
  28. '__oct__',
  29. '__hex__',
  30. '__index__',
  31. '__trunc__',
  32. '__coerce__',
  33. '__str__',
  34. '__repr__',
  35. '__unicode__',
  36. '__format__',
  37. '__hash__',
  38. '__nonzero__',
  39. '__dir__',
  40. '__sizeof__'
  41. }
  42. __overridden__ = __special_names__.union(__imethods__).union(__other_magic__)
  43. @staticmethod
  44. def __imethod_wrapper____(method):
  45. '''makes a wrapper around __i<something>__ methods, such as __iadd__ to act on __subject__'''
  46. @functools.wraps(method)
  47. def wrapper(self,*args,**kwargs):
  48. tmp = self.__subject__
  49. tmp = method(tmp,*args,**kwargs)
  50. self.__subject__ = tmp
  51. return self
  52. return wrapper
  53. @staticmethod
  54. def __method_wrapper__(method):
  55. '''makes a wrapper around methods and cast the result to a proxytype if possible'''
  56. @functools.wraps(method)
  57. def wrapper(self,*args,**kwargs):
  58. res = method(self.__subject__,*args,**kwargs)
  59. try:
  60. return Proxy(type(res),'Proxy<{t}>'.format(t=type(res).__name__))(res)
  61. except TypeError: #if the result's type isn't subclassable, i.e. types.FunctionType would raise a TypeException
  62. return res
  63. return wrapper
  64.  
  65. @staticmethod
  66. def usable_base_type(Type):
  67. try:
  68. type('',(Type,),{})
  69. return True
  70. except TypeError:
  71. return False
  72. def __new__(cls,parentType,classname=None): #So that Proxy emulates a function
  73. '''parentType is the type you wish to proxy, and classname is the name that appears for the class, <class 'classname'>'''
  74. if not cls.usable_base_type(parentType):
  75. raise TypeError("type '{Type}' is not an acceptable base type".format(Type=parentType.__name__))
  76. if classname is None:
  77. classname = 'Proxy<{name}>'.format(name=parentType.__name__)
  78. class newType(parentType):
  79. def __init__(self,*args,**kwargs):
  80. self.__subject__ = parentType(*args,**kwargs)
  81. def setvalue(self,value):
  82. self.__subject__ = value
  83. def getvalue(self):
  84. return self.__subject__
  85. def __getattr__(self,name):
  86. if name not in cls.__overridden__:
  87. return getattr(self.__subject__,name)
  88. for name,prop in ((k,v) for k,v in parentType.__dict__.items() if k != '__doc__'): #because magic methods are implemented as staticmethods
  89. if name in cls.__special_names__:
  90. setattr(newType,name,cls.__method_wrapper__(prop))
  91. for name in cls.__imethods__: #parentType may not implement all of them
  92. if hasattr(parentType,name):
  93. setattr(newType,name,cls.__imethod_wrapper____(parentType.__dict__[name]))
  94. else:
  95. non_i_name = name[:2]+name[3:]
  96. if hasattr(parentType,non_i_name):
  97. setattr(newType,name,cls.__imethod_wrapper____(getattr(parentType,non_i_name)))
  98. for name in cls.__other_magic__:
  99. if hasattr(parentType,name):
  100. parent_item = getattr(parentType,name)
  101. if isinstance(parent_item,collections.Callable):
  102. setattr(newType,name,lambda self,*args,**kwargs:parent_item(self.__subject__,*args,**kwargs))
  103. else:
  104. setattr(newType,name,parent_item)
  105. newType.__name__ = classname
  106. return newType
  107.  
  108. __special_names__.union(__imethods__).union(__other_magic__)
  109.  
  110. __special_names__ | __imethods__ | __other_magic__
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement