On 1/5/21 10:25 AM, Guido van Rossum wrote:
> On Tue, Jan 5, 2021 at 8:50 AM Ethan Furman wrote:

>> [...]
>> Perhaps `ABCMeta` can be easily fixed -- it is calling the function that
>> records all abstract methods, etc., after the `type.__new__` call; can
>> it be called before?
>
> Why do you keep insisting that this is "broken"?

Because `__init_subclass__` is getting a new class object that is not ready to 
be gotten.

> Yes, you have identified a way that an abstract class can be instantiated
> *by its own constructor* despite being abstract.

It doesn't feel that way to me. Referring to the code below [1], the constructor for `MyPlugin` is `abc.ABCMeta`, but `PluginBase.__init_subclass__` is getting `MyPlugin` before `abc.ABCMeta` has finished doing its job.

> I think that's not something to get worked up about. As the doctor in the
> old joke said, "then don't do that." Or perhaps this is one of those
> situations where we're all still considered to be consenting adults --
> surely abstract classes and methods are meant as a way to help users do
> the right thing, not as an absolute guarantee.

According to the documentation:
> This module provides abstract base classes that can be used to test whether
> a class provides a particular interface; for example, whether it is hashable
> or whether it is a mapping.

Do we need to add a warning to that?

> except inside `__init_subclass__` as the class has not been fully initialized.

For that matter, if we are not going to address this issue with code, we should definitely update the `__init_subclass__` and `__set_name__` documentation:

> Note: custom metaclasses must have all changes needed already in the class
> namespace before calling `type.__new__`, as `type.__new__` will invoke
> `__init_subclass__` and `__set_name__` before returning.  Any modifications
> made to the class after that point will not be available to those two methods.
>
> Note: because of the above, any `__init_subclass__` used with `Enum` classes 
will
> not see any members as members are added after the call to `type.__new__`.
>
> Note: because of the above, any `__init_subclass__` used with `ABC` classes 
will
> have to determine for itself if the class is abstract or concrete as that is
> determined after the call to `type.__new__`.

As I said before, perhaps `_abc_init` can be called before `type.__new__`, 
which would make that last note unnecessary.

That would not solve the problem for `Enum`, though, nor for any other metaclass that cannot complete its customization before calling `type.__new__`.

--
~Ethan~


[1]
class PluginBase(abc.ABC):

    # base class for plugins
    # must override `do_something`

    def __init_subclass__(cls, **kwargs):

        instance = cls()
        print(f"Created instance of {cls} easily: {instance}")


    @abc.abstractmethod
    def do_something(self):
        pass


class MyPlugin(PluginBase):
    pass



[2] https://docs.python.org/3/library/collections.abc.html
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/KE3ZJEDFMZT4TXTTHXMVGEZSLX2HDUSZ/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to