New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating custom Validator instance with `_validator_*` method raises SchemaError #265

Closed
bryanwweber opened this Issue Sep 11, 2016 · 6 comments

Comments

Projects
None yet
5 participants
@bryanwweber
Copy link
Contributor

bryanwweber commented Sep 11, 2016

Used Cerberus version / latest commit: 1.0.1


Use-case abstract

I am trying to follow the example from the docs to create a custom validator. The example defining a function oddity works, but creating the custom subclass of Validator with the equivalent function raises a SchemaError.


from cerberus import Validator
class AValidator(Validator):
    def _validator_oddity(self, field, value):
        if not value & 1:
            self._error(field, "Must be an odd number")

schema = {'amount': {'validator': 'oddity'}}
v = AValidator(schema)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/bryan/anaconda3/envs/pyteck/lib/python3.5/site-packages/cerberus/validator.py", line 143, in __init__
    self.schema = kwargs.get('schema', None)
  File "/Users/bryan/anaconda3/envs/pyteck/lib/python3.5/site-packages/cerberus/validator.py", line 432, in schema
    self._schema = DefinitionSchema(self, schema)
  File "/Users/bryan/anaconda3/envs/pyteck/lib/python3.5/site-packages/cerberus/schema.py", line 67, in __init__
    self.validate(schema)
  File "/Users/bryan/anaconda3/envs/pyteck/lib/python3.5/site-packages/cerberus/schema.py", line 186, in validate
    self._validate(schema)
  File "/Users/bryan/anaconda3/envs/pyteck/lib/python3.5/site-packages/cerberus/schema.py", line 208, in _validate
    raise SchemaError(self.schema_validator.errors)
cerberus.schema.SchemaError: {'amount': [{'validator': [{'oneof': ['none or more than one rule validate', {'oneof definition 0': ['must be of callable type'], 'oneof definition 1': ['must be of list type'], 'oneof definition 2': ['unallowed value oddity']}]}]}]}

@bryanwweber bryanwweber changed the title Creating custom Validator instance with `_validator_*` function raises Schema Error Creating custom Validator instance with `_validator_*` method raises SchemaError Sep 11, 2016

@bryanwweber

This comment has been minimized.

Copy link
Contributor

bryanwweber commented Sep 11, 2016

Furthermore, changing the validator to a list in the schema raises a NotImplementedError (once #264 is merged, otherwise it raises a TypeError).

schema = {'amount': {'validator': ['oddity']}}
v = AValidator(schema)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/bryan/GitHub/cerberus/cerberus/validator.py", line 143, in __init__
    self.schema = kwargs.get('schema', None)
  File "/Users/bryan/GitHub/cerberus/cerberus/validator.py", line 432, in schema
    self._schema = DefinitionSchema(self, schema)
  File "/Users/bryan/GitHub/cerberus/cerberus/schema.py", line 67, in __init__
    self.validate(schema)
  File "/Users/bryan/GitHub/cerberus/cerberus/schema.py", line 186, in validate
    self._validate(schema)
  File "/Users/bryan/GitHub/cerberus/cerberus/schema.py", line 208, in _validate
    raise SchemaError(self.schema_validator.errors)
  File "/Users/bryan/GitHub/cerberus/cerberus/validator.py", line 360, in errors
    return self.error_handler(self._errors)
  File "/Users/bryan/GitHub/cerberus/cerberus/errors.py", line 443, in __call__
    self.extend(errors)
  File "/Users/bryan/GitHub/cerberus/cerberus/errors.py", line 372, in extend
    self.add(error)
  File "/Users/bryan/GitHub/cerberus/cerberus/errors.py", line 451, in add
    self.insert_logic_error(error)
  File "/Users/bryan/GitHub/cerberus/cerberus/errors.py", line 518, in insert_logic_error
    raise NotImplementedError
NotImplementedError
@joshbenner

This comment has been minimized.

Copy link

joshbenner commented Sep 12, 2016

I believe this is a bug.

I traced the behavior to InspectedValidator.__init__ as it is building the schema to validate a schema. It has a coded assumption that all validation methods begin with _validate_.

Upon changing the custom validator from _validator_foo to _validate_validator_foo, the schema validation now picked up my custom validator -- however, __get_rule_handler() requires that the function name be as documented (ie: _validator_foo).

So either InspectedValidator.__init__ needs to be updated to discover custom validators correctly, or the documentation and __get_rule_handler() need to be updated to match what InspectedValidator.__init__ enforces. My opinion would be to implement the former.

For now, a workaround is to create an alias of your custom validator:

class MyValidatorClass(cerberus.Validator):
    def _validator_my_validator(self, field, value):
        if my_test(value) is False:
            self._error(field, "Nope!")

    _validate_validator_my_validator = _validator_my_validator
@funkyfuture

This comment has been minimized.

Copy link
Member

funkyfuture commented Sep 12, 2016

yup, that seems correct. since validator obviously belongs to the validation realm, the prefix seems redundant.

on the other hand it's not stringent. type checks do have that realm-prefix.

a short mediation on import this backs your proposal, i guess.

@k1-hedayati

This comment has been minimized.

Copy link

k1-hedayati commented Sep 14, 2016

I encountered this issue today, it would be great to see this issue fixed

@nicolaiarocci nicolaiarocci added the bug label Sep 23, 2016

@nicolaiarocci nicolaiarocci added this to the Unreleased milestone Sep 23, 2016

@nicolaiarocci

This comment has been minimized.

Copy link
Member

nicolaiarocci commented Sep 23, 2016

@bryanwweber thanks for reporting this. Would you (or someone else) be willing to submit a fix?

funkyfuture added a commit to funkyfuture/cerberus that referenced this issue Oct 26, 2016

funkyfuture added a commit to funkyfuture/cerberus that referenced this issue Oct 26, 2016

funkyfuture added a commit to funkyfuture/cerberus that referenced this issue Oct 26, 2016

@bryanwweber

This comment has been minimized.

Copy link
Contributor

bryanwweber commented Oct 27, 2016

About a day ago, I was looking at this issue again to see if I could work out a fix. Got beaten to it! Thanks @nicolaiarocci and @funkyfuture!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment