53 lines
1.3 KiB
Python
53 lines
1.3 KiB
Python
import abc
|
|
|
|
|
|
class AutoStorage:
|
|
__counter = 0
|
|
|
|
def __init__(self):
|
|
cls = self.__class__
|
|
prefix = cls.__name__
|
|
index = cls.__counter
|
|
self.storage_name = '_{}#{}'.format(prefix, index)
|
|
cls.__counter += 1
|
|
|
|
def __get__(self, instance, owner):
|
|
if instance is None:
|
|
return self
|
|
else:
|
|
return getattr(instance, self.storage_name)
|
|
|
|
def __set__(self, instance, value):
|
|
setattr(instance, self.storage_name, value)
|
|
|
|
|
|
class Validated(abc.ABC, AutoStorage):
|
|
|
|
def __set__(self, instance, value):
|
|
value = self.validate(instance, value)
|
|
super().__set__(instance, value)
|
|
|
|
@abc.abstractmethod
|
|
def validate(self, instance, value):
|
|
"""return validated value or raise ValueError"""
|
|
|
|
INVALID = object()
|
|
|
|
class Check(Validated):
|
|
|
|
def __init__(self, checker):
|
|
super().__init__()
|
|
self.checker = checker
|
|
if checker.__doc__ is None:
|
|
doc = ''
|
|
else:
|
|
doc = checker.__doc__ + '; '
|
|
self.message = doc + '{!r} is not valid.'
|
|
|
|
|
|
def validate(self, instance, value):
|
|
result = self.checker(value)
|
|
if result is INVALID:
|
|
raise ValueError(self.message.format(value))
|
|
return result
|