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

Field validator regression on dependent fields #586

Open
rlupton20 opened this issue Feb 26, 2019 · 2 comments
Open

Field validator regression on dependent fields #586

rlupton20 opened this issue Feb 26, 2019 · 2 comments

Comments

@rlupton20
Copy link

rlupton20 commented Feb 26, 2019

#497 found a regression in validator function of fields in 2.0.1 dependent on prior fields. #499 purported to both fix this, and add tests to prevent future regressions.

I've produced a similar issue for dependent fields in 2.1.0. The docs here
https://schematics.readthedocs.io/en/latest/usage/validation.html#model-level-validation
suggest this should be handled.

from schematics.models import Model
from schematics.types import StringType
from schematics.exceptions import ValidationError
import schematics

class TestModel(Model):
    field1 = StringType(required=True)
    field2 = StringType()

    def validate_field2(self, data, value):
        if data['field1'] == "" and data['field2'] == "":
            raise ValidationError("Invalid values")
        return field2


print("Schematics version:", schematics.__version__)

TestModel({
    'field2': 'foo'
}).validate()

produces

Schematics version: 2.1.0
Traceback (most recent call last):
  File "schematics_test.py", line 18, in <module>
    'field2': 'foo'
  File "/usr/local/lib/python3.7/site-packages/schematics/models.py", line 258, in validate
    partial=partial, convert=convert, app_data=app_data, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/schematics/models.py", line 299, in _convert
    return func(self._schema, self, raw_data=raw_data, oo=True, context=context, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/schematics/validate.py", line 64, in validate
    errors.update(_validate_model(schema, mutable, data, context))
  File "/usr/local/lib/python3.7/site-packages/schematics/validate.py", line 95, in _validate_model
    schema._validator_functions[field_name](mutable, data, value, context)
  File "/usr/local/lib/python3.7/site-packages/schematics/validate.py", line 128, in newfunc
    return func(*args, **kwargs)
  File "schematics_test.py", line 11, in validate_field2
    if data['field1'] == "":
KeyError: 'field1'

Tested in the python:3.7 docker container - just pip install schematics and run the above to reproduce.

@rlupton20
Copy link
Author

rlupton20 commented Feb 26, 2019

Actually what I've found is slightly different (i.e. not a re-regression), but the docs suggest should be fine. I'll update. It looks like it's all in the same vein.

@rlupton20 rlupton20 changed the title Field validator re-regression Field validator regression on dependent fields Feb 26, 2019
@rlupton20
Copy link
Author

rlupton20 commented Feb 26, 2019

The problem seems to be in this logic in validate.py

    errors = {}               
    try:                             
        data = import_loop(schema, mutable, raw_data, trusted_data=trusted_data,
            context=context, **kwargs)
    except DataError as exc:            
        errors = dict(exc.errors)
        data = exc.partial_data
                       
    errors.update(_validate_model(schema, mutable, data, context))

    if errors:
        raise DataError(errors, data)

In the above case we do populate error dictionary with an error to say field1 isn't set, but run _validate_model for field2 anyway, despite the fact there may be some dependency on something we already errored on.

Some ideas

  • error before running the _validate_model functions if some data doesn't have the required properties. Then we lose having all errors at once.
  • Become aware of dependencies in the _validate_models function. Perhaps handle failed data key lookups by cross-referencing with the current error dictionary? It all seems a bit gross.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant