'Cerberus: unexpected normalization behavior with anyof_schema

The following code validates the dictionary {'a_dict': {}} with the schema A and the schema any of A or B. The problem is that in the second case the dictionary is not being normalized as expected.

Running the code:

from cerberus import Validator


A = {'key': {'type': 'string', 'required': False, 'default': 'X', }}
B = {'key': {'type': 'integer', 'required': False, 'default': 1, }}

v1 = Validator({
    'a_dict': {
        'type': 'dict',
        'schema': A,
    },
})

v2 = Validator({
    'a_dict': {
        'type': 'dict',
        'anyof_schema': [A, B]
    },
})

x = {'a_dict': {}}

print(v1.validated(x))
print(v2.validated(x))

the result is

{'a_dict': {'key': 'X'}}
{'a_dict': {}}

I would expect the result to be

{'a_dict': {'key': 'X'}}
{'a_dict': {'key': 'X'}}

Is there a bug here or something that I don't understand?

I am using Python 3.9 and Cerberus 1.3.4



Solution 1:[1]

z has the last value of completed_data, thus you only get one match (the id 174).

You should test bucket_data22[i]['id'] in completed_data

for i in bucket_data22:
    if (bucket_data22[i]['id'] in completed_data):
        print((completed_data[z]/bucket_data22[i]['value'])*100)

Output:

5.0
3.3333333333333335

Solution 2:[2]

It appears that the second loop only begins after the first one is already finished.
Therefore, the second loop always gets the same value of 'z', which equals 174.
If you want to iterate all the values of 'z', you must move the second loop into the first loop.

bucket_data22={1: {'key': 'Security Awareness Overview', 'value': 20, 'start_date': '13/07/2021', 'end_date': '12/08/2021', 'id': 155}, 
         2: {'key': 'Security Awareness Overview', 'value': 0, 'start_date': '13/07/2021', 'end_date': '12/08/2021', 'id': 159}, 
         3:  {'key': 'Security Awareness Overview', 'value': 30, 'start_date': '24/09/2021', 'end_date': '27/09/2021', 'id': 174}}
completed_data={155: 1, 174: 1}

for z in completed_data:
    for i in bucket_data22:
        if (bucket_data22[i]['id']==z):
          print((completed_data[z]/bucket_data22[i]['value'])*100)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 mozway
Solution 2