Advertisement
Guest User

Untitled

a guest
May 24th, 2015
252
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.23 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 implements __check_annotation__ by checking whether all the
  7. annotations passed to its constructor are 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.  
  49.  
  50. class Check_Annotation():
  51. # must be True for checking to occur
  52. checking_on = True
  53.  
  54. # self._checking_on must also be true for checking to occur
  55. def __init__(self,f):
  56. self._f = f
  57. self.checking_on = True
  58.  
  59. # Check whether param's annot is correct for value, adding to check_history
  60. # if recurs; defines many local function which use it parameters.
  61. def check(self,param,annot,value,check_history=''):
  62. """
  63. :param param: is a string that specifies the name of the parameter being checked
  64. (or '_return' for checking the returned value)
  65. :param annot: is a data structure that specifies the annotation
  66. :param value: is the value of param that the annotation should be checked against (to ensure it is legal)
  67. :param check_history: is a string that embodies the history of checking the annotation
  68. for the parameter to here (it is extended by concatenation in
  69. each recursive call to provide context for any annotation violations to be checked later);
  70. it is printed after the details of any annotation violation, to suppy context for the failure.
  71. :return:
  72. """
  73. # Define local functions for checking, list/tuple, dict, set/frozenset,
  74. # lambda/functions, and str (str for extra credit)
  75. # Many of these local functions called by check, call check on their
  76. # elements (thus are indirectly recursive)
  77.  
  78. # Decode annotation and check it
  79. #pass
  80.  
  81. #local functions
  82. def check_list():
  83. error_str = '\'{}\' failed annotation check(wrong type):' \
  84. ' value = {} \n\twas type {} ...should be type {}'.format(
  85. param,value,type_as_str(value),'list')
  86. #type list
  87. if type(annot) == type:
  88. if isinstance(value,list):
  89. return
  90. else:
  91. raise AssertionError(error_str)
  92. elif type(annot[0]) == type:
  93. #type [int]
  94. if isinstance(value,list):
  95. if len(annot) == 1:
  96. #check each value to make sure its same type
  97. for object in value:
  98. if not isinstance(object,annot[0]):
  99. raise AssertionError
  100. else:
  101. continue
  102. if len(annot) > 1:
  103. if len(annot) == len(value):
  104. for object,annotation in zip(value,annot):
  105. if not isinstance(object,annotation):
  106. raise AssertionError
  107. else:
  108. continue
  109. else:
  110. raise AssertionError
  111. else:
  112. raise AssertionError(error_str)
  113. else:
  114. if len(annot[0]) == 1:
  115. for object in value:
  116. for sub_object in object:
  117. if not isinstance(sub_object,annot[0][0]):
  118. raise AssertionError
  119. else:
  120. continue
  121.  
  122. def check_tuple():
  123. error_str = '\'{}\' failed annotation check(wrong type):' \
  124. ' value = {} \n\twas type {} ...should be type {}'.format(
  125. param,value,type_as_str(value),'tuple')
  126. #type list
  127. if type(annot) == type:
  128. if isinstance(value,list):
  129. return
  130. else:
  131. raise AssertionError(error_str)
  132. elif type(annot[0]) == type:
  133. #type [int]
  134. if isinstance(value,tuple):
  135. if len(annot) == 1:
  136. #check each value to make sure its same type
  137. for object in value:
  138. if not isinstance(object,annot[0]):
  139. raise AssertionError
  140. else:
  141. continue
  142. if len(annot) > 1:
  143. if len(annot) == len(value):
  144. for object,annotation in zip(value,annot):
  145. if not isinstance(object,annotation):
  146. raise AssertionError
  147. else:
  148. continue
  149. else:
  150. raise AssertionError
  151. else:
  152. raise AssertionError(error_str)
  153. else:
  154. if len(annot[0]) == 1:
  155. for object in value:
  156. for sub_object in object:
  157. if not isinstance(sub_object,annot[0][0]):
  158. raise AssertionError
  159. else:
  160. continue
  161.  
  162. def check_dict():
  163. error_str = '\'{}\' failed annotation check(wrong type):' \
  164. ' value = {} \n\twas type {} ...should be type {}'.format(
  165. param,value,type_as_str(value),'dict')
  166. if type(annot) == type:
  167. if isinstance(value,dict):
  168. return
  169. else:
  170. raise AssertionError(error_str)
  171. #elif type(annot) == dict:
  172. #type [int]
  173. #if isinstance(value,dict):
  174. #pass
  175. if isinstance(value,dict):
  176. for k,v in value.items():
  177. for key in annot.keys():
  178. if type(k) == key and type(v) == annot[key]:
  179. pass
  180. else:
  181. raise AssertionError
  182. else:
  183. raise AssertionError
  184.  
  185. def check_set():
  186. if isinstance(value,set):
  187. if len(annot) > 1:
  188. if not len(value) == len(annot):
  189. raise AssertionError
  190. return
  191. else:
  192. raise AssertionError
  193.  
  194. def check_frozenset():
  195. if isinstance(value,frozenset):
  196. if len(annot) > 1:
  197. if not len(value) == len(annot):
  198. raise AssertionError
  199. return
  200. else:
  201. raise AssertionError
  202.  
  203. def check_lambda():
  204. parameters = annot.__code__.co_varnames
  205.  
  206. if len(parameters) == 0 or len(parameters) > 1:
  207. raise AssertionError
  208.  
  209. # if len(parameters) > 1:
  210. # expected_tuple_len = len(parameters)
  211. # if type(value) == list:
  212. # for tup in value:
  213. # if len(tup) != expected_tuple_len:
  214. # raise AssertionError
  215. # else:
  216. # raise AssertionError
  217.  
  218. #list of values
  219. if type(value) == list:
  220. for x in value:
  221. try:
  222. if annot(x):
  223. pass
  224. else:
  225. raise AssertionError
  226. except:
  227. raise AssertionError
  228. #one elem
  229. else:
  230. if annot(value):
  231. pass
  232. else:
  233. raise AssertionError
  234.  
  235. def check_lambda_list():
  236. parameters = annot[0].__code__.co_varnames
  237.  
  238. if len(parameters) == 0 or len(parameters) > 1:
  239. raise AssertionError
  240.  
  241. # if len(parameters) > 1:
  242. # expected_tuple_len = len(parameters)
  243. # if type(value) == list:
  244. # for tup in value:
  245. # if len(tup) != expected_tuple_len:
  246. # raise AssertionError
  247. # else:
  248. # raise AssertionError
  249.  
  250. #list of values
  251. if type(value) == list:
  252. for x in value:
  253. try:
  254. if annot[0](x):
  255. pass
  256. else:
  257. raise AssertionError
  258. except:
  259. raise AssertionError
  260. #one elem
  261. else:
  262. if annot(value):
  263. pass
  264. else:
  265. raise AssertionError
  266.  
  267. def check_str():
  268. error_str = '\'{}\' failed annotation check(wrong type):' \
  269. ' value = {} \n\twas type {} ...should be type {}'.format(
  270. param,value,type_as_str(value),'str')
  271. if isinstance(value,str):
  272. return
  273. else:
  274. raise AssertionError(error_str)
  275.  
  276. def check_int():
  277. if isinstance(value,int):
  278. return
  279. else:
  280. raise AssertionError
  281.  
  282.  
  283. if annot is None:
  284. #Do Nothing
  285. return
  286. elif isinstance(annot,list) or annot == list:
  287. if inspect.isfunction(annot[0]):
  288. check_lambda_list()
  289. else:
  290. check_list()
  291. elif isinstance(annot,tuple) or annot == tuple:
  292. check_tuple()
  293. elif annot == str:
  294. check_str()
  295. elif isinstance(annot,dict) or annot == dict:
  296. check_dict()
  297. elif isinstance(annot,set) or annot == set:
  298. check_set()
  299. elif isinstance(annot,frozenset) or annot == frozenset:
  300. check_frozenset()
  301. elif inspect.isfunction(annot):
  302. check_lambda()
  303. elif isinstance(annot,int) or annot == int:
  304. check_int()
  305. else: # other
  306. raise AssertionError
  307.  
  308.  
  309.  
  310.  
  311. # Return result of calling decorated function call, checking present
  312. # parameter/return annotations if required
  313. def __call__(self, *args, **kargs):
  314.  
  315. # Return a dictionary of the parameter/argument bindings (actually an
  316. # ordereddict, in the order parameters occur in the function's header)
  317. def param_arg_bindings():
  318. f_signature = inspect.signature(self._f)
  319. bound_f_signature = f_signature.bind(*args,**kargs)
  320. for param in f_signature.parameters.values():
  321. if param.name not in bound_f_signature.arguments:
  322. bound_f_signature.arguments[param.name] = param.default
  323. return bound_f_signature.arguments
  324.  
  325. # If annotation checking is turned off at the class or function level
  326. # just return the result of calling the decorated function
  327. # Otherwise do all the annotation checking
  328. if not self.checking_on:
  329. return self._f(*args,**kargs)
  330.  
  331. try:
  332. # Check the annotation for every parameter (if there is one)
  333. param_dict = param_arg_bindings()
  334. for variable,value in param_dict.items():
  335. self.check(variable,self._f.__annotations__[variable],value)
  336.  
  337. # Compute/remember the value of the decorated function
  338. return_value = self._f(*args,**kargs)
  339.  
  340. # If 'return' is in the annotation, check it
  341. if 'return' in self._f.__annotations__:
  342. self.check('_return',self._f.__annotations__['return'],return_value)
  343.  
  344. # Return the decorated answer
  345. return return_value
  346.  
  347. # On first AssertionError, print the source lines of the function and reraise
  348. except AssertionError:
  349. #print(80*'-')
  350. #for l in inspect.getsourcelines(self._f)[0]: # ignore starting line #
  351. # print(l.rstrip())
  352. #print(80*'-')
  353. raise
  354.  
  355.  
  356.  
  357.  
  358.  
  359. if __name__ == '__main__':
  360.  
  361. #def f(x : list): pass
  362. #f = Check_Annotation(f)
  363. #f([1,2])
  364.  
  365. class NotSupportProtocol: pass
  366. def f(x : NotSupportProtocol()): pass
  367. f = Check_Annotation(f)
  368.  
  369. #f(3)
  370. #f('abc') #assert error
  371.  
  372.  
  373. import driver
  374. #driver.driver()
  375. driver.batch_self_check('bsc.txt')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement