cerberus icon indicating copy to clipboard operation
cerberus copied to clipboard

Unable to use Custom Coercers

Open irmo322 opened this issue 3 years ago • 1 comments

I'm trying to extend cerberus behavior as it is done with custom coercers in documentation: https://docs.python-cerberus.org/en/stable/customize.html#custom-coercers

The example given in documentation fails if the schema contains a list.

Here is a simple script that show the problem:

import cerberus


print('cerberus version :', cerberus.__version__)


class MyNormalizer(cerberus.Validator):
    def __init__(self, multiplier, *args, **kwargs):
        super(MyNormalizer, self).__init__(*args, **kwargs)
        self.multiplier = multiplier

    def _normalize_coerce_multiply(self, value):
        return value * self.multiplier


schema = {
    'foo': {
        'type': 'integer'
    }
}
document = {'foo': 2}
print(MyNormalizer(2).normalized(document, schema))

schema = {
    'foo': {
        'type': 'list',
        'schema': {
            'type': 'integer'
        }
    }
}
document = {'foo': [2]}
print(MyNormalizer(2).normalized(document, schema))

And here is the console output:

cerberus version : 1.3.4
{'foo': 2}
Traceback (most recent call last):
  File "issue.py", line 33, in <module>
    print(MyNormalizer(2).normalized(document, schema))
  File "C:\Users\irmo\Anaconda3\lib\site-packages\cerberus\validator.py", line 693, in normalized
    self.__normalize_mapping(self.document, self.schema)
  File "C:\Users\irmo\Anaconda3\lib\site-packages\cerberus\validator.py", line 718, in __normalize_mapping
    self.__normalize_containers(mapping, schema)
  File "C:\Users\irmo\Anaconda3\lib\site-packages\cerberus\validator.py", line 806, in __normalize_containers
    self.__normalize_sequence_per_schema(field, mapping, schema)
  File "C:\Users\irmo\Anaconda3\lib\site-packages\cerberus\validator.py", line 871, in __normalize_sequence_per_schema
    validator = self._get_child_validator(
  File "C:\Users\irmo\Anaconda3\lib\site-packages\cerberus\validator.py", line 354, in _get_child_validator
    child_validator = self.__class__(**child_config)
TypeError: __init__() missing 1 required positional argument: 'multiplier'

I have not found a way to deal with this issue.

irmo322 avatar Mar 25 '22 01:03 irmo322

Following https://docs.python-cerberus.org/en/stable/customize.html#attaching-configuration-data-and-instantiating-custom-validators, I was able to make it work. See above example:

import cerberus


print('cerberus version :', cerberus.__version__)


class MyNormalizer(cerberus.Validator):
    def __init__(self, *args, **kwargs):
        super(MyNormalizer, self).__init__(*args, **kwargs)
        self.multiplier = kwargs["multiplier"]

    def _normalize_coerce_multiply(self, value):
        return value * self.multiplier


schema = {
    'foo': {
        'type': 'integer',
        'coerce': 'multiply'
    }
}
document = {'foo': 2}
print(MyNormalizer(multiplier=2).normalized(document, schema))

schema = {
    'foo': {
        'type': 'list',
        'schema': {
            'type': 'integer',
            'coerce': 'multiply'
        }
    }
}
document = {'foo': [2]}
print(MyNormalizer(multiplier=2).normalized(document, schema))

which gives the following output:

cerberus version : 1.3.4
{'foo': 4}
{'foo': [4]}

So finally, only the documentation needs a correction ?

irmo322 avatar Mar 25 '22 01:03 irmo322

indeed, i did this in a638a2e2df4583834e0aed4303694370bdcbda80.

funkyfuture avatar Jul 25 '23 17:07 funkyfuture