Skip to content
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
Closed
Labels

Comments

@bryanwweber
Copy link
Contributor

@bryanwweber 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
Copy link
Contributor Author

@bryanwweber 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
Copy link

@joshbenner 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
Copy link
Member

@funkyfuture 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.

@ghost
Copy link

@ghost ghost commented Sep 14, 2016

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

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

@nicolaiarocci 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
Copy link
Contributor Author

@bryanwweber 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
Labels
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
4 participants