Skip to content

Instantly share code, notes, and snippets.

@unautre
Last active April 1, 2016 14:55
Show Gist options
  • Select an option

  • Save unautre/80af350ee69bcda6d9eee43ad54d0278 to your computer and use it in GitHub Desktop.

Select an option

Save unautre/80af350ee69bcda6d9eee43ad54d0278 to your computer and use it in GitHub Desktop.
from functools import partial
def ContractProperty(name):
return partial(Attribut, name)
class Attribut(object):
DEFAULT_ERROR_MESSAGE = "Error: contract not hold"
def __init__(self, name, fset=None, fget=None, fdel=None, doc=None, contracts=None):
self._name = name
# list of predicates/contracts it should hold
self._should = []
if doc is None and fget is not None and hasattr(fget, "__doc__"):
doc = fget.__doc__
self.fget = fget or lambda inst, cls=None: getattr(inst, self._name)
self.fset = fset or lambda inst, value: setattr(inst, self._name, value)
self.fdel = fdel or lambda inst: raise AttributeError("Can't delete attribute")
self.__doc__ = doc
def shouldHold(self, func, err_msg = DEFAULT_ERROR_MESSAGE):
if not isinstance(err_msg, Exception):
err_msg = AttributeError(err_msg)
self._should.append((func, err_msg))
def __get__(self, inst, cls=None):
return self.fget(inst)
def __set__(self, inst, value):
for f, err in self._should_list:
if not f(value):
raise err
self.fset(inst, value)
def getter(self, func):
self.fget = func
def setter(self, func):
self.fset = func
class Foo(object):
x = Attribut("_x") # hidden attribute name
x.shouldHold(lambda x:x>0)
x.shouldHold(lambda x:isinstance(x, int))
@x.setter
def x(self, value):
print("[!] Setter for x called !")
self._x = value
@ContractProperty("_y")
def y(self):
print("[!] Getter for y called !")
f = Foo()
f.x = 12
f.x = -4
f.x = 3.0
print(f.y)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment