faust-streaming/faust

Model Validation is not working as expected

Opened this issue · 2 comments

Steps to reproduce

class Metadata(Record, validation=True, serializer='json'):
  desc:str=StringField(coerce=False)
  lolo:Optional[float]
  low:Optional[float]
  high:Optional[float]
  hihi:Optional[float]
  units:Optional[str]
  prec:Optional[int]

then try to initialise an instance with anything other than a string for the desc field. I tried a different model, but it doesn't matter what you choose so long as it's not a string

Expected behavior

I would expect that anything other than a string would fail if coerce is set to False.
If coerce was set to True I would expect it to attempt to force the value to the required type and error if not possible.

Actual behavior

Any data type input into the desc field is accepted.
If you input a text string (i.e. not "3") into a float field, it is rejected as it's not the correct type, but "3" is, regardless of whether coerce is set to true or false.

If this isn't how it should be used, then I'll need to use another model/record system.

This seems somewhat intended. In the docstring of the FieldDescriptor class, it specifically says here, that "If coerce is not enabled you can store any type of value."

But I agree, that this clashes somewhat with the validation function of records, which in itself will already coerce values if possible, even if coerce is set to false for the field descriptor.

Regarding the usage of StringField, @GiuliaCaglia is correct, this coerce=False works as-intended. Regarding validation, you are seeing the effects of using StringField, which overrides the typical validation behavior as noted in https://faust-streaming.github.io/faust/userguide/models.html#validation:

If you have a field you want validation for, you may explicitly define the field descriptor for the field you want validation on (note: this will override the built-in validation for that field).

Since you're using StringField, I recommend this guidance:

So in web views we suggest disabling automatic validation, and instead manually validating the model by calling model.validate(). to get a list of ValidationError instances.