Guest User

Untitled

a guest
Feb 25th, 2018
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.84 KB | None | 0 0
  1. import attr
  2.  
  3. class AutoValidator:
  4. _expr = None
  5. _counter = 0
  6.  
  7. def _newvar(self):
  8. num = AutoValidator._counter
  9. AutoValidator._counter += 1
  10. return f'_v{num}'
  11.  
  12. def __call__(self, cls, attr, value):
  13. if self._expr is None:
  14. self._expr = self._compile()
  15. return self._expr(cls, attr, value)
  16.  
  17. def _compile(self):
  18. scope = dict(self._scope)
  19. scope['_pretty'] = self._pretty
  20. scope['_type_err'] = TypeError
  21. body = (
  22. 'def _func(_cls, _attr, _value):\n'
  23. f' if not {self._source}:\n'
  24. ' raise _type_err(f"{_cls}.{_attr.name} fails check {_pretty}")'
  25. )
  26. exec(body, scope)
  27. return scope['_func']
  28.  
  29. def __add__(self, other):
  30. return Binary('+', self, other)
  31. def __radd__(self, other):
  32. return Binary('+', other, self)
  33. def __mul__(self, other):
  34. return Binary('*', self, other)
  35. def __rmul__(self, other):
  36. return Binary('*', other, self)
  37. def __lt__(self, other):
  38. return Binary('<', self, other)
  39. def __le__(self, other):
  40. return Binary('<=', self, other)
  41. def __eq__(self, other):
  42. return Binary('==', self, other)
  43. def __ne__(self, other):
  44. return Binary('!=', self, other)
  45. def __gt__(self, other):
  46. return Binary('>', self, other)
  47. def __ge__(self, other):
  48. return Binary('>=', self, other)
  49. def len(self):
  50. return Func(len, self)
  51. def isa(self, *type_expr):
  52. def isa_check(val):
  53. return isinstance(val, type_expr)
  54. return Func(isa_check, self)
  55. def __repr__(self):
  56. return self._pretty
  57.  
  58. class Value(AutoValidator):
  59. _source = '_value'
  60. @property
  61. def _scope(self):
  62. return {}
  63. _pretty = 'VAL'
  64.  
  65. VAL = Value()
  66.  
  67. class Constant(AutoValidator):
  68. def __init__(self, constant):
  69. var = self._newvar()
  70. self._scope = {var: constant}
  71. self._source = var
  72. self._pretty = repr(constant)
  73.  
  74. def _autoify(value):
  75. return value if isinstance(value, AutoValidator) else Constant(value)
  76.  
  77. class Binary(AutoValidator):
  78. def __init__(self, op, left, right):
  79. left = _autoify(left)
  80. right = _autoify(right)
  81. self._scope = dict(left._scope)
  82. self._scope.update(right._scope)
  83. self._source = f'({left._source} {op} {right._source})'
  84. self._pretty = f'({left} {op} {right})'
  85.  
  86. class Func(AutoValidator):
  87. def __init__(self, func, arg):
  88. var = self._newvar()
  89. arg = _autoify(arg)
  90. self._scope = {var: func}
  91. self._scope.update(arg._scope)
  92. self._source = f'{var}({arg._source})'
  93. self._pretty = f'{func.__name__}({arg})'
  94.  
  95. @attr.s
  96. class Test:
  97. positive = attr.ib(validator=[VAL.isa(int, float), VAL > 0.0])
  98. nonempty = attr.ib(validator=[VAL.len() >= 1])
Add Comment
Please, Sign In to add comment