[PATCH 3/3] Don't call object's (as a class) __new__ with extra arguments

David Shea dshea at redhat.com
Wed Feb 18 15:02:43 UTC 2015


On 02/18/2015 03:19 AM, Vratislav Podzimek wrote:
> On Tue, 2015-02-17 at 17:09 -0500, David Shea wrote:
>> On 02/17/2015 09:30 AM, Vratislav Podzimek wrote:
>>> The Python 3 version of the 'object' class raises an exception otherwise, the
>>> Python 2 version of the class ignores them anyway.
>>>
>>> Signed-off-by: Vratislav Podzimek <vpodzime at redhat.com>
>>> ---
>>>    blivet/util.py | 2 +-
>>>    1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/blivet/util.py b/blivet/util.py
>>> index ecd3693..5d830df 100644
>>> --- a/blivet/util.py
>>> +++ b/blivet/util.py
>>> @@ -373,7 +373,7 @@ class ObjectID(object):
>>>        _newid_gen = functools.partial(next, itertools.count())
>>>    
>>>        def __new__(cls, *args, **kwargs):
>>> -        self = super(ObjectID, cls).__new__(cls, *args, **kwargs)
>>> +        self = super(ObjectID, cls).__new__(cls)
>>>            self.id = self._newid_gen() # pylint: disable=attribute-defined-outside-init
>>>            return self
>>>    
>> I don't like this, because it breaks the case where object is not the
>> next thing in the MRO. Like in this convoluted example:
>>
>> class Thing1(object):
>> ...
>> class Thing2(ObjectID, Thing1):
>> ...
>>
>> Assuming both Thing1 and Thing2 start by calling super().__new__, the
>> __new__ calls would be Thing2, ObjectID, Thing1, object.
>>
>> But I also don't have a solution for it, since the preferable thing
>> would be for each class to remove its specific arguments before passing
>> down to the next class, but since we're overriding __new__ that means
>> that a class not involved in ObjectID at all (Thing1) has to override
>> __new__. Ugh, multiple inheritance is weird. I think the preferable
>> thing would be to replace the super call with an explicit
>> object.__new__(cls) and note in the doc comment ObjectID's limited
>> utility as a mixin. Unless we can convert ObjectID to a metaclass or
>> something.
> To be honest, I've never fully understood why Python has both __new__
> and __init__, but I don't see a reason why we need to pass the args to
> the __new__ methods as I don't see any class in our code that would make
> use of them.
>
> Also, am I right that we have this implemented as part of the __new__
> method just because this way the self.id is set even if the child class
> doesn't call its parent's (ObjectID's) __init__? Wouldn't it be better
> to use a class decorator for this?
>

The only reason it uses __new__ instead of __init__ was because we had 
classes using .id during __init__, and I don't think anything needs that 
anymore. So maybe we can just convert ObjectID.__new__ to __init__ and 
remove a bit of weirdness.




More information about the anaconda-patches mailing list