4

Is there a decorator for using attrs converters?

There are decorators for validator and default, but I couldn't see anything mentioned for converter.

Is it possible?

I prefer to have the function as a "method" within the class, as opposed to global function outside the class. Decorators allow that :)

example snippet for validator.

    payload : bytes = attr.ib( default=b'', on_setattr=attr.setters.validate )

    #! NOTE: using attrs validator as a property setter function.
    @payload.validator
    def payload_setter( self, attribute : attr.Attribute, value : bytes ) -> None :
        self.payload_length = len( value )

I want to do something similar using converters. Example to trim some input bytes to an upper bound.

    data : bytes = attr.ib( default=b'', on_setattr=attr.setters.converter )

    #! NOTE: using attrs converter as a property setter function.
    @data.converter
    def data_setter( self, attribute : attr.Attribute, value : bytes ) -> None :
        trimmed_value = value[:10]
        return trimmed_value
BrendanSimon
  • 665
  • 1
  • 9
  • 23

2 Answers2

1

This is how I do it and it works well enough. However, I use attrs for very simple cases and I can't guarantee that this will behave in more complex cases.

def converter(attribute):
    def decorator(func):
        attribute.converter = func
        return staticmethod(func)
    return decorator


@attr.s
class MyAttrs:
    number = attr.ib()

    @converter(number):
    def _convert_to_int(value):
        return int(value)


>>> MyAttrs('0')
MyAttrs(number=0)
>>> MyAttrs(12.5)
MyAttrs(number=12)
warownia1
  • 2,771
  • 1
  • 22
  • 30
0

There is currently not.

There has been a bit of work concerning this but doubts came up whether or not it makes sense to pursue: https://github.com/python-attrs/attrs/pull/404

hynek
  • 3,647
  • 1
  • 18
  • 26
  • I read that PR. Not sure I fully understood the use case(s) and whether they were similar to mine. One extra requirement I have, which I omitted, is that the length for trimming is not fixed and is determine by another attribute of the same class (self.max_length), so I need the converter callback to have access to the instance (similar to validator decorator/callback). – BrendanSimon Aug 28 '20 at 12:23
  • I think I'm right in saying that attrs now supports this, as the ` attr.setters.convert(instance, attrib, new_value)` has access to the instance, which is a new feature. Yes? Though I'm not sure if a decorator is available. – BrendanSimon Sep 25 '20 at 04:53