Do we still need a support of non-type objects in issubclass()?
issubclass() accept types (extension types and new-style classes), classic classes and arbitrary objects with the __bases__ attribute as its arguments. The latter was added in issue464992 [1] to support the Zope extension ExtensionClass. I tested the current code of ExtensionClass [2], and seems it does not need that special support. Tests are passed on modified master which uses tp_bases instead of dynamical look up of __bases__, ExtensionClass.ExtensionClass is a subclass of type and ExtensionClass.Base is an instance of type, the code does not have the __bases__ property and does not set the __bases__ attribute explicitly. On other hand, the code in the Python core has a non-zero maintenance cost. It was rewritten several times for 19 years, there is a gigantic comment larger that the current code explaining it (and it is slightly outdated), and there was several bugs related to it [3] [4]. Should we continue to support non-type objects with __bases__ in issubclass()? If no, can we remove their support in 3.10 (it would fix a crash in issue41909) or after passing a deprecation period? [1] https://bugs.python.org/issue464992 [2] https://github.com/zopefoundation/ExtensionClass [3] https://bugs.python.org/issue39382 [4] https://bugs.python.org/issue41909
On Sat, Oct 03, 2020 at 11:41:16AM +0300, Serhiy Storchaka wrote:
issubclass() accept types (extension types and new-style classes), classic classes and arbitrary objects with the __bases__ attribute as its arguments.
I didn't think classic classes were still possible in Python 3. How do you get them? -- Steve
03.10.20 12:45, Steven D'Aprano пише:
On Sat, Oct 03, 2020 at 11:41:16AM +0300, Serhiy Storchaka wrote:
issubclass() accept types (extension types and new-style classes), classic classes and arbitrary objects with the __bases__ attribute as its arguments.
I didn't think classic classes were still possible in Python 3. How do you get them?
They were originally in Python 2.2.2 code when the support of objects with the __bases__ attribute was added. In Python 3 there are no classic classes, but some code was written to support them.
Is this the only place where a non-class object with __bases__ is accepted? Or do we have more such? I recall that long ago you could use certain non-class objects as base classes. I think all that hackery may predate (and may even have been an inspiration for features of) new-style classes. —Guido On Sat, Oct 3, 2020 at 03:12 Serhiy Storchaka <storchaka@gmail.com> wrote:
03.10.20 12:45, Steven D'Aprano пише:
On Sat, Oct 03, 2020 at 11:41:16AM +0300, Serhiy Storchaka wrote:
issubclass() accept types (extension types and new-style classes),
classic classes and arbitrary objects with the __bases__ attribute as
its arguments.
I didn't think classic classes were still possible in Python 3. How do
you get them?
They were originally in Python 2.2.2 code when the support of objects
with the __bases__ attribute was added. In Python 3 there are no classic
classes, but some code was written to support them.
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@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/LWQTXQUG...
Code of Conduct: http://python.org/psf/codeofconduct/
-- --Guido (mobile)
03.10.20 18:15, Guido van Rossum пише:
Is this the only place where a non-class object with __bases__ is accepted? Or do we have more such? I recall that long ago you could use certain non-class objects as base classes.
The only other place is object.__dir__(). It recursively iterates the __class__.__bases__ chain, and __class__ can be a non-type object. The code of object.__dir__() is very old, it predates new-style classes, and currently it gathers names using different algorithm than used in object.__getattr__(), so object.__dir__() does not always return a list of names accepted by object.__getattr__().
I think all that hackery may predate (and may even have been an inspiration for features of) new-style classes.
I wonder whether it should pass with Python 2.
On Sat, Oct 3, 2020 at 9:28 AM Serhiy Storchaka <storchaka@gmail.com> wrote:
03.10.20 18:15, Guido van Rossum пише:
Is this the only place where a non-class object with __bases__ is accepted? Or do we have more such? I recall that long ago you could use certain non-class objects as base classes.
The only other place is object.__dir__(). It recursively iterates the __class__.__bases__ chain, and __class__ can be a non-type object.
The code of object.__dir__() is very old, it predates new-style classes, and currently it gathers names using different algorithm than used in object.__getattr__(), so object.__dir__() does not always return a list of names accepted by object.__getattr__().
Would anything break if we changed `dir()` to use `__mro__` instead of `__bases__`? It would probably be simpler.
I think all that hackery may predate (and may even have been an inspiration for features of) new-style classes.
I wonder whether it should pass with Python 2.
I suppose you meant "pass" as in "die". I agree. -- --Guido van Rossum (python.org/~guido) *Pronouns: he/him **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-c...>
04.10.20 01:06, Guido van Rossum пише:
On Sat, Oct 3, 2020 at 9:28 AM Serhiy Storchaka <storchaka@gmail.com <mailto:storchaka@gmail.com>> wrote: The code of object.__dir__() is very old, it predates new-style classes, and currently it gathers names using different algorithm than used in object.__getattr__(), so object.__dir__() does not always return a list of names accepted by object.__getattr__(). Would anything break if we changed `dir()` to use `__mro__` instead of `__bases__`? It would probably be simpler.
It is what I planned to play with. Also we can consider using _PyObject_GetDictPtr() instead of resolving the __dict__ attribute and Py_TYPE() instead of resolving the __class__ attribute.
> I think all that hackery may predate (and may even have been an > inspiration for features of) new-style classes. I wonder whether it should pass with Python 2. I suppose you meant "pass" as in "die". I agree.
Do we need a deprecation period?
On Sun, Oct 4, 2020 at 1:24 AM Serhiy Storchaka <storchaka@gmail.com> wrote:
On Sat, Oct 3, 2020 at 9:28 AM Serhiy Storchaka <storchaka@gmail.com <mailto:storchaka@gmail.com>> wrote: The code of object.__dir__() is very old, it predates new-style classes, and currently it gathers names using different algorithm than used in object.__getattr__(), so object.__dir__() does not always return a
04.10.20 01:06, Guido van Rossum пише: list
of names accepted by object.__getattr__(). Would anything break if we changed `dir()` to use `__mro__` instead of `__bases__`? It would probably be simpler.
It is what I planned to play with. Also we can consider using _PyObject_GetDictPtr() instead of resolving the __dict__ attribute and Py_TYPE() instead of resolving the __class__ attribute.
> I think all that hackery may predate (and may even have been an > inspiration for features of) new-style classes. I wonder whether it should pass with Python 2. I suppose you meant "pass" as in "die". I agree.
Do we need a deprecation period?
If the code can be written such that a DeprecationWarning can be raised if the __bases__ path is taken then yes unless you ask the SC to skip it and they agree to it: https://www.python.org/dev/peps/pep-0387/#basic-policy-for-backwards-compati....
On Sat, Oct 3, 2020, at 04:41, Serhiy Storchaka wrote:
Should we continue to support non-type objects with __bases__ in issubclass()? If no, can we remove their support in 3.10 (it would fix a crash in issue41909) or after passing a deprecation period?
Er, to be clear, contrary to the subject line, you're not suggesting removing support for non-type objects altogether [i.e. with __subclasscheck__], right? Just the ability to use a non-slotted __bases__ attribute?
participants (5)
-
Brett Cannon
-
Guido van Rossum
-
Random832
-
Serhiy Storchaka
-
Steven D'Aprano