3

I have a class A in a foreign library.

class A:
    def __init__(self, a: int):
        self.a = a

I would like to extend a class B with A like:

import attr

@attr.s
class B(A):
    b: int = attr.ib()

The code seems to work:

import attr

class A:
    def __init__(self, a: int):
        self.a = a

attr.s(these={
    "a": attr.ib(type=str)
}, init=True)(A)

@attr.s(kw_only=True)
class B(A):
    b: int = attr.ib()

if __name__ == "__main__":
    a = A(1)
    b = B(a=1, b=2)
    print(a)  # output: A(a=1) 
    print(b)  # output: B(a=1, b=2)

but mypy/pyright is unhappy.

> mypy file.py
error: Unexpected keyword argument "a" for "B"
Alex Waygood
  • 6,304
  • 3
  • 24
  • 46
Nico W.
  • 338
  • 3
  • 12

1 Answers1

1

I’m reasonably sure that the MyPy attrs plugin doesn’t support these.

Since you’re not calling super, the idiomatic way would be to just define a as an attribute on B so that attrs takes care of it.


JFTR: if you use @attr.define or @attr.s(auto_attribs=True), you can leave out the attr.ib() call(s).

hynek
  • 3,647
  • 1
  • 18
  • 26
  • Thanks, @hynek. This was an important hint. Erroneously I thought that `attrs` doing some magic to make a `super()` behind the scenes. In the meantime I changed it to `@attr.define`. Pretty sad that mypy doesn't support it properly. – Nico W. Oct 16 '21 at 19:48
  • `attrs` does _never_ super (each method is optimized for each case). If _you_ need to call super, there’s ways to achieve that: https://www.attrs.org/en/stable/init.html#hooking-yourself-into-initialization – hynek Oct 17 '21 at 08:27