attrs icon indicating copy to clipboard operation
attrs copied to clipboard

TypeError when calling super() in decorated method

Open kdebrab opened this issue 1 year ago • 2 comments

Following code:

import attrs


def decorated(method):
    def wrapped(self, *args, **kwargs):
        return method(self, *args, **kwargs)

    return wrapped


@attrs.define()
class A:
    def f(self):
        pass


@attrs.define()
class B(A):
    @decorated
    def f(self):
        super().f()


B().f()

raises following error

TypeError: super(type, obj): obj must be an instance or subtype of type

If I use super(B, self), everything works just fine.

kdebrab avatar Oct 06 '22 07:10 kdebrab

This problem is related to cell rewriting for slotted classes. Put simply we have to cheat a bit to make them work by rewriting method contents.

You get the same behavior with dataclasses:

@dataclasses.dataclass(slots=True)
@attrs.define
class C:
    @decorated
    def f(self):
        super().f()
TypeError: super(type, obj): obj must be an instance or subtype of type

Short fixes:

  • don't use super that way
  • disable slots (@attrs.define(slots=False))

Long-term fixes:

  • open a bug on CPython for the dataclasses case and we'll steal it from them
  • convince @Tinche to fix it for attrs right away ;)

I'm a bit dubious if it's actually possible to fix tho. :-/ Maybe, if functools.wraps is used and we follow the __wrapped__ attributes?

hynek avatar Oct 06 '22 08:10 hynek

Thanks for the quick response! I'll use super(B, self) for now.

kdebrab avatar Oct 06 '22 08:10 kdebrab