Advertisement
Guest User

Untitled

a guest
May 24th, 2015
319
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.13 KB | None | 0 0
  1. from goody import type_as_str
  2. import inspect
  3.  
  4. class Check_All_OK:
  5. """
  6. Check_All_OK class implements __check_annotation__ by checking whether each
  7. annotation passed to its constructor is OK; the first one that
  8. fails (raises AssertionError) prints its problem, with a list of all
  9. annotations being tried at the end of the check_history.
  10. """
  11.  
  12. def __init__(self,*args):
  13. self._annotations = args
  14.  
  15. def __repr__(self):
  16. return 'Check_All_OK('+','.join([str(i) for i in self._annotations])+')'
  17.  
  18. def __check_annotation__(self, check, param, value,check_history):
  19. for annot in self._annotations:
  20. check(param, annot, value, check_history+'Check_All_OK check: '+str(annot)+' while trying: '+str(self)+'\n')
  21.  
  22.  
  23. class Check_Any_OK:
  24. """
  25. Check_Any_OK implements __check_annotation__ by checking whether at least
  26. one of the annotations passed to its constructor is OK; if all fail
  27. (raise AssertionError) this classes raises AssertionError and prints its
  28. failure, along with a list of all annotations tried followed by the check_history.
  29. """
  30.  
  31. def __init__(self,*args):
  32. self._annotations = args
  33.  
  34. def __repr__(self):
  35. return 'Check_Any_OK('+','.join([str(i) for i in self._annotations])+')'
  36.  
  37. def __check_annotation__(self, check, param, value, check_history):
  38. failed = 0
  39. for annot in self._annotations:
  40. try:
  41. check(param, annot, value, check_history)
  42. except AssertionError:
  43. failed += 1
  44. if failed == len(self._annotations):
  45. assert False, repr(param)+' failed annotation check(Check_Any_OK): value = '+repr(value)+\
  46. '\n tried '+str(self)+'\n'+check_history
  47.  
  48. class Check_Annotation():
  49. # set name to True for checking to occur
  50. checking_on = True
  51.  
  52. # self._checking_on must also be true for checking to occur
  53. def __init__(self,f):
  54. self._f = f
  55. self.checking_on = True
  56.  
  57. # Check whether param's annot is correct for value, adding to check_history
  58. # if recurs; defines many local function which use it parameters.
  59. def check(self,param,annot,value,check_history=''):
  60.  
  61. # Define local functions for checking, list/tuple, dict, set/frozenset,
  62. # lambda/functions, and str (str for extra credit)
  63. # Many of these local functions called by check, call check on their
  64. # elements (thus are indirectly recursive)
  65.  
  66. print("Annot:", annot)
  67. print("Type of annot:", type(annot))
  68. print("Param", param)
  69. print("Value", value, "\tValue Type", type(value))
  70. print("history", check_history)
  71.  
  72. def check_type():
  73. if isinstance(value, annot): return
  74. else: raise AssertionError
  75. def check_list():
  76. if isinstance(value, list):
  77. if len(annot) == 1:
  78. for i in value:
  79. if not isinstance(i, annot[0]): raise AssertionError
  80. return
  81. elif len(value) == len(annot):
  82. for i,j in zip(value,annot):
  83. if not isinstance(i, j): raise AssertionError
  84. return
  85. else: raise AssertionError
  86. else: raise AssertionError
  87. def check_dict():
  88. if isinstance(value, dict): return
  89. else: raise AssertionError
  90. def check_tuple():
  91. if isinstance(value, tuple):
  92. if len(annot) == 1:
  93. for i in value:
  94. if not isinstance(i, annot[0]): raise AssertionError
  95. return
  96. elif len(value) == len(annot):
  97. for i,j in zip(value,annot):
  98. if not isinstance(i, j): raise AssertionError
  99. return
  100. else: raise AssertionError
  101. else: raise AssertionError
  102. def check_set():
  103. if isinstance(value, set):
  104. if len(annot) > 1:
  105. raise AssertionError
  106. elif len(annot) == 1:
  107. for i in value:
  108. if type(i) not in annot: raise AssertionError
  109. return
  110. else: raise AssertionError
  111. def check_frozenset():
  112. if isinstance(value, frozenset):
  113. if len(annot) > 1:
  114. raise AssertionError
  115. elif len(annot) == 1:
  116. for i in value:
  117. if type(i) not in annot: raise AssertionError
  118. return
  119. else: raise AssertionError
  120. def check_lambda():
  121. pass
  122. def check_str():
  123. if isinstance(value, str):
  124. print("\nEVAL\n", eval(annot))
  125. return
  126. else: raise AssertionError
  127. def check_int():
  128. if isinstance(value, int): return
  129. else: raise AssertionError
  130.  
  131. # Decode annotation and check it
  132. if annot == None: return
  133. elif isinstance(annot, type): check_type()
  134. elif isinstance(annot, list):
  135. if isinstance(annot[0], list):
  136. for i, j in zip(annot, value):
  137. self.check(param, i, j, check_history)
  138.  
  139. else: check_list()
  140. elif isinstance(annot, dict): check_dict()
  141. elif isinstance(annot, tuple): check_tuple()
  142. elif isinstance(annot, set): check_set()
  143. elif isinstance(annot, frozenset): check_frozenset()
  144. # elif isinstance(annot, function): check_lambda()
  145. elif isinstance(annot, str): check_str()
  146. elif isinstance(annot, int): check_int()
  147. else: raise AssertionError
  148.  
  149.  
  150. # Return result of calling decorated function call, checking present
  151. # parameter/return annotations if required
  152. def __call__(self, *args, **kargs):
  153.  
  154. # Return a dictionary of the parameter/argument bindings (actually an
  155. # ordereddict, in the order parameters occur in the function's header)
  156. def param_arg_bindings():
  157. f_signature = inspect.signature(self._f)
  158. bound_f_signature = f_signature.bind(*args,**kargs)
  159. for param in f_signature.parameters.values():
  160. if param.name not in bound_f_signature.arguments:
  161. bound_f_signature.arguments[param.name] = param.default
  162. return bound_f_signature.arguments
  163.  
  164. # If annotation checking is turned off at the class or function level
  165. # just return the result of calling the decorated function
  166. # Otherwise do all the annotation checking
  167. if Check_Annotation.checking_on and self.checking_on:
  168. try:
  169. # Check the annotation for every parameter (if there is one)
  170. for x, y in param_arg_bindings().items():
  171. self.check(x, self._f.__annotations__[x], y)
  172. # Compute/remember the value of the decorated function
  173. answer = self._f(*args, **kargs)
  174. # If 'return' is in the annotation, check it
  175. if "return" in self._f.__annotations__:
  176. self.check("_return", self._f.__annotaions__["return"])
  177. # Return the decorated answer
  178. return answer
  179.  
  180. # On first AssertionError, print the source lines of the function and reraise
  181. except AssertionError:
  182. # print(80*'-')
  183. # for l in inspect.getsourcelines(self._f)[0]: # ignore starting line #
  184. # print(l.rstrip())
  185. # print(80*'-')
  186. raise
  187. else:
  188. return self._f(*args, **kargs)
  189.  
  190. if __name__ == '__main__':
  191. # an example of testing a simple annotation
  192. # def f(x:int): pass
  193. # f = Check_Annotation(f)
  194. # f(3)
  195. # f('a')
  196.  
  197. import driver
  198. driver.driver()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement