diff options
author | Philipp Hahn <hahn@univention.de> | 2020-08-28 18:34:10 +0200 |
---|---|---|
committer | Philipp Hahn <hahn@univention.de> | 2020-08-28 18:42:48 +0200 |
commit | 8c800b0adf4849aeb94cb712192dba82fa4720d3 (patch) | |
tree | 89919af32d8b32c152d53ab4c23da7afaac24a61 /libvirtaio.py | |
parent | d8d55b17e227f0ce829e709966f580861186f8ab (diff) | |
download | libvirt-python-8c800b0adf4849aeb94cb712192dba82fa4720d3.tar.gz |
Revert "libvirtaio: Drop object(*args, **kwargs)"v6.7.0
This reverts commit f4be03b330125ab1e5a2bb10b4f12674aeff4691.
While object.__init__() does not expect any additional arguments, this
construct is required for Pythons multiple inheritance implementation.
The original author Wojtek Porczyk <woju@invisiblethingslab.com>
explained is this way:
> I'm sorry I didn't notice this earlier, but the commit f4be03b3 dated
> 2020-04-20 [0] is wrong. The super().__init__(*args, **kwargs) in
> Callback.__init__ was there on purpose, because of how Python's inheritance in
> new-style classes works.
>
> Let me explain this a bit, because it is not obvious.
>
> Suppose you had diamond inheritance like this:
>
> class A(object): pass
> class B(A): pass
> class C(A): pass
> class D(B,C): pass
>
> And those classes needed a common function with varying arguments:
>
> class A(object):
> def spam(self, a): print(f'A: {a}')
> class B(A):
> def spam(self, b): print(f'B: {b}')
> class C(A):
> def spam(self, c): print(f'C: {c}')
> class D(B,C):
> def spam(self, d): print(f'D: {d}')
>
> The way to call all parent's functions exactly once (as per MRO) and accept
> all arguments and also forbid unknown arguments is to accept **kwargs
> everywhere and pass them to super().spam():
>
> class A:
> def spam(self, a):
> print(f'A: {a}')
> class B(A):
> def spam(self, b, **kwargs):
> print(f'B: {b}')
> super().spam(**kwargs)
> class C(A):
> def spam(self, c, **kwargs):
> print(f'C: {c}')
> super().spam(**kwargs)
> class D(B, C):
> def spam(self, d, **kwargs):
> print(f'D: {d}')
> super().spam(**kwargs)
>
> Let's run this:
>
> >>> B().spam(a=1, b=2)
> B: 2
> A: 1
> >>> D().spam(a=1, b=2, c=3, d=4)
> D: 4
> B: 2
> C: 3
> A: 1
>
> You may notice that super() in B.spam refers to two different classes, either
> A or C, depending on inheritance order in yet undefined classes (as of B's
> definition).
>
> That's why the conclusion that super() in Callback.__init__ refers to object
> is wrong. In this example, spam=__init__, A=object, B=Callback and C and D are
> not yet written, but theoretically possible classes that could be written by
> someone else. Why would they be needed, I don't know, but if someone writes
> them, s/he would be out of options to invent new arguments to C.__init__.
>
> Note that super().__init__(*args, **kwargs) when super() refers to object
> isn't harmful, and just ensures that args and kwargs are empty (i.e. no
> unknown arguments were passed). In fact, this is exactly why object.__init__()
> takes no arguments since Python 2.6 [1][2], as you correctly point out in the
> commit message.
>
> I don't think this breaks anything (I very much doubt anyone would need to
> write code that would trigger this), nevertheless, as the commit is both
> pointless and wrong, and as the original author of libvirtaio I'd like to ask
> for this commit to be reverted. If this breaks some static analysis tool,
> could you just suppress it for this particular line?
>
>
> [0] https://gitlab.com/libvirt/libvirt-python/-/commit/f4be03b330125ab1e5a2bb10b4f12674aeff4691
> [1] https://bugs.python.org/issue1683368
> [2] https://docs.python.org/3/whatsnew/2.6.html#porting-to-python-2-6
> (fourth point)
>
Signed-off-by: Philipp Hahn <hahn@univention.de>
Diffstat (limited to 'libvirtaio.py')
-rw-r--r-- | libvirtaio.py | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/libvirtaio.py b/libvirtaio.py index efee0ee..a2abf0c 100644 --- a/libvirtaio.py +++ b/libvirtaio.py @@ -66,7 +66,8 @@ class Callback(object): _iden_counter = itertools.count() - def __init__(self, impl: "virEventAsyncIOImpl", cb: Callable[[int, _T], None], opaque: _T, ) -> None: + def __init__(self, impl: "virEventAsyncIOImpl", cb: Callable[[int, _T], None], opaque: _T, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) # type: ignore self.iden = next(self._iden_counter) self.impl = impl self.cb = cb |