import trafaret as t


def _prepare_trafaret_instance(value):
    if isinstance(value, t.Trafaret):
        return value
    elif issubclass(value.__class__, t.Trafaret.__class__):
        return value()
    return


class TrafaretValidatorMeta(type):
    def __new__(mcs, clsname, bases, dct):
        _dct = {}
        _validators = {}
        for name, value in dct.items():
            trafaret_instance = _prepare_trafaret_instance(value)
            if trafaret_instance:
                _validators[name] = trafaret_instance
            else:
                _dct[name] = value

        cls = super().__new__(mcs, clsname, bases, _dct)
        setattr(cls, '_validators', _validators)
        setattr(cls, '_trafaret', t.Dict(**_validators))
        return cls


class TrafaretValidator(metaclass=TrafaretValidatorMeta):
    _validators = {}
    _trafaret = {}
    _errors = {}
    _data = {}

    def __init__(self, **kwargs):
        self._params = self._prepare_params(kwargs)

    def __getattr__(self, name):
        try:
            return self._data[name]
        except KeyError:
            raise AttributeError(name)

    def __setattr__(self, name, value):
        if name in self._validators.keys():
            raise AttributeError('Cannot reassign validator.')

        trafaret_instance = _prepare_trafaret_instance(value)
        if trafaret_instance:
            self._validators[name] = trafaret_instance
            self._trafaret = t.Dict(**self._validators)
        else:
            object.__setattr__(self, name, value)

    def _prepare_params(self, params):
        prepared_params = {}
        for attr_name in self._validators.keys():
            prepared_params[attr_name] = params.get(attr_name)
        return prepared_params

    @property
    def validators(self):
        return self._validators.copy()

    @property
    def trafaret(self):
        return self._trafaret

    @property
    def errors(self):
        return self._errors.copy()

    @property
    def params(self):
        return self._params.copy()

    @property
    def data(self):
        return self._data.copy()

    def validate(self):
        try:
            self._data = self._trafaret.check(self.params)
            return True
        except t.DataError as error:
            self._errors = error.as_dict()
            return False

@@ -302,24 +302,53 @@
   _dct = %7B%7D%0A
+        _dct_validators = %7B%7D%0A
         _val
@@ -508,32 +508,36 @@
                 
+_dct
 _validators%5Bname
@@ -632,16 +632,42 @@
 = super(
+TrafaretValidatorMeta, mcs
 ).__new_
@@ -695,16 +695,116 @@
 , _dct)%0A
+        _validators.update(getattr(cls, '_validators'))%0A        _validators.update(_dct_validators)%0A
         
@@ -885,18 +885,16 @@
  t.Dict(
-**
 _validat
@@ -1616,18 +1616,16 @@
  t.Dict(
-**
 self._va

fix bug when attributes apparently not inherited