d2py.abc.validate 源代码

from abc import ABC, abstractmethod


[文档] class Validator(ABC):
[文档] def __set_name__(self, owner, name): self.public_name = name self.private_name = '_' + name
[文档] def __get__(self, obj, objtype=None): return getattr(obj, self.private_name)
[文档] def __set__(self, obj, value): self.validate(value) setattr(obj, self.private_name, value)
[文档] @abstractmethod def validate(self, value): NotImplemented
[文档] class OneOf(Validator): def __init__(self, *options): self.options = set(options)
[文档] def validate(self, value): if value not in self.options: raise ValueError(f'Expected {value!r} to be one of {self.options!r}')
[文档] class Number(Validator): def __init__(self, minvalue=None, maxvalue=None): self.minvalue = minvalue self.maxvalue = maxvalue
[文档] def validate(self, value): if not isinstance(value, (int, float)): raise TypeError(f'Expected {value!r} to be an int or float') if self.minvalue is not None and value < self.minvalue: raise ValueError( f'Expected {value!r} to be at least {self.minvalue!r}' ) if self.maxvalue is not None and value > self.maxvalue: raise ValueError( f'Expected {value!r} to be no more than {self.maxvalue!r}' )
[文档] class String(Validator): def __init__(self, minsize=None, maxsize=None, predicate=None): self.minsize = minsize self.maxsize = maxsize self.predicate = predicate
[文档] def validate(self, value): if not isinstance(value, str): raise TypeError(f'Expected {value!r} to be an str') if self.minsize is not None and len(value) < self.minsize: raise ValueError( f'Expected {value!r} to be no smaller than {self.minsize!r}' ) if self.maxsize is not None and len(value) > self.maxsize: raise ValueError( f'Expected {value!r} to be no bigger than {self.maxsize!r}' ) if self.predicate is not None and not self.predicate(value): raise ValueError( f'Expected {self.predicate} to be true for {value!r}' )
if __name__ == "__main__": class Component: name = String(minsize=3, maxsize=10, predicate=str.isupper) kind = OneOf('wood', 'metal', 'plastic') quantity = Number(minvalue=0) def __init__(self, name, kind, quantity): self.name = name self.kind = kind self.quantity = quantity