cerberus icon indicating copy to clipboard operation
cerberus copied to clipboard

Allow None values in anyof

Open elben10 opened this issue 6 years ago • 2 comments

Use-case abstract

To allow None values using anyof it seems that is required to add the key 'nullable'=True at the second upper level of the schema dictionary as well as within the allof schemavalues list. I would expect that if the key 'nullable'=True was present in the second upper level it would validate None values to True when using schema3 (see code line 52-53, below).


Bug report / Feature request

schema1 shows how I was able to allow None values together with allof, but I got a bit confused with the behaviour. If there exists an nullable key in both test, and in the valuelist of anyof a None value will be validated to True (See code line 48-49). In schema2, I removed the nullable key in test which resulted in False when validating (See code line 50-51). If we again consider schema1 and then remove the nullable key within the anyof list (schema3) it will again be validated to False.

To me it seems reasonable that schema3 is validated to True instead of False as it is right now.

1. Python 3.6.5 (default, Jun 11 2018, 16:45:16) 
2. [GCC 7.3.0] on linux
3. Type "help", "copyright", "credits" or "license" for more information.
4. >>> import cerberus
5. >>> schema1 = {
6. ...     'test': {
7. ...         'anyof': [
8. ...             {
9. ...                 'type': 'string',
10. ...                 'nullable': True
11. ...             },
12. ...             {
13. ...                 'type': 'list',
14. ...             }
15. ...         ],
16. ...         'nullable': True
17. ...     }
18. ... }
19. >>> 
20. >>> schema2 = {
21. ...     'test': {
22. ...         'anyof': [
23. ...             {
24. ...                 'type': 'string',
25. ...                 'nullable': True
26. ...             },
27. ...             {
28. ...                 'type': 'list'
29. ...             }
30. ...         ],
31. ...     }
32. ... }
33. >>> 
34. >>> schema3 = {
35. ...     'test': {
36. ...         'anyof': [
37. ...             {
38. ...                 'type': 'string',
39. ...             },
40. ...             {
41. ...                 'type': 'list'
42. ...             }
43. ...         ],
44. ...         'nullable': True
45. ...     }
46. ... }
47. >>> v = cerberus.Validator()
48. >>> v.validate({'test': None}, schema1) 
49. True
50. >>> v.validate({'test': None}, schema2) 
51. False
52. >>> v.validate({'test': None}, schema3) 
53. False

elben10 avatar Jun 13 '18 11:06 elben10

Seems to be pretty closely connected to this issue #373. Should I close this Issue?

elben10 avatar Jun 13 '18 12:06 elben10

it's close and it's not. it is generally related as it opens up the question how 'smart' Cerberus should be to complete a schema (in the other question nullable implies None as transient constraint for allowed).

but here it's whether rules for a field should also be included in constraints for *of-rules of the same field. from my experience that'd be too smart as it opens expectations and edge-cases that make Cerberus complicated for a little convenience (yes, convenience is a main feature of Cerberus :-/).

i'd say you're better off with verbose, but explicit schemas. my assessment may be wrong as i got cautious about some rules and their bearings.

funkyfuture avatar Jun 18 '18 20:06 funkyfuture