classification
Title: inspect.isabstract does not work on abstract base classes during __init_subclass__
Type: behavior Stage: backport needed
Components: Library (Lib) Versions: Python 3.7, Python 3.6
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: So8res, levkivskyi, ncoghlan, serhiy.storchaka, yselivanov
Priority: normal Keywords:

Created on 2017-03-15 17:06 by So8res, last changed 2017-04-24 17:09 by serhiy.storchaka.

Pull Requests
URL Status Linked Edit
PR 678 merged So8res, 2017-03-15 18:50
Messages (6)
msg289682 - (view) Author: Nate Soares (So8res) * Date: 2017-03-15 17:06
Here's an example test that fails:

def test_isabstract_during_init_subclass(self):
    from abc import ABCMeta, abstractmethod

    isabstract_checks = []

    class AbstractChecker(metaclass=ABCMeta):
        def __init_subclass__(cls):
            abstract_checks.append(inspect.isabstract(cls))

    class AbstractClassExample(AbstractChecker):

        @abstractmethod
        def foo(self):
            pass

    class ClassExample(AbstractClassExample):
        def foo(self):
            pass

    self.assertEqual(isabstract_checks, [True, False])

To run the test, you'll need to be on a version of python where bpo-29581 is fixed (e.g., a cpython branch with https://github.com/python/cpython/pull/527 merged) in order for __init_subclass__ to work with ABCMeta at all in the first place. I have a simple patch to inspect.isabstract that fixes this, and will make a PR shortly.
msg289788 - (view) Author: Ivan Levkivskyi (levkivskyi) * Date: 2017-03-18 01:09
Serhiy, sorry for a distraction, but it looks like here is one more situation where inspect.isabstract is problematic, similar to what was discussed in http://bugs.python.org/issue29638 recently.
msg289793 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-03-18 05:46
Is this an alternate fix of issue29638?
msg289794 - (view) Author: Nate Soares (So8res) * Date: 2017-03-18 07:04
I didn't know about issue29638, and I'm not sure whether my PR fixes it. Looking at that bug, I don't think that my PR would fix it, because I still trust TPFLAGS_IS_ABSTRACT when __abstractmethods__ exists. That said, I'm not clear on how the cache works, so it's possible that my PR would fix 29638.

My issue appears when one uses py3.6's new __init_subclass__ hook with an ABC. __init_subclass__ is run by type.__new__, which means that, as of py3.6, users can (in a natural/reasonable way) inspect ABCMeta classes before ABCMeta.__new__ finishes executing. I didn't see any reasonable way to have ABCMeta.__new__ finish setting up the ABC before calling super().__new__, so I figured the fix should go into inspect.isabstract. But there may be better solutions I just didn't think of.
msg289823 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-03-18 17:52
LGTM, but would be nice if Yury and Nick take a look.
msg292231 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-04-24 17:06
New changeset fcfe80ec2592fed8b3941c79056a8737abef7d3b by Serhiy Storchaka (Nate) in branch 'master':
bpo-29822: Make inspect.isabstract() work during __init_subclass__. (#678)
https://github.com/python/cpython/commit/fcfe80ec2592fed8b3941c79056a8737abef7d3b
History
Date User Action Args
2017-04-24 17:09:07serhiy.storchakasetstage: patch review -> backport needed
versions: - Python 3.5
2017-04-24 17:06:19serhiy.storchakasetmessages: + msg292231
2017-03-18 17:52:51serhiy.storchakasetmessages: + msg289823
2017-03-18 13:57:08serhiy.storchakasetnosy: + ncoghlan
2017-03-18 07:04:13So8ressetmessages: + msg289794
2017-03-18 05:46:49serhiy.storchakasettype: behavior
components: + Library (Lib)
versions: + Python 3.5, Python 3.6
nosy: + yselivanov

messages: + msg289793
stage: patch review
2017-03-18 01:09:13levkivskyisetnosy: + serhiy.storchaka, levkivskyi
messages: + msg289788
2017-03-15 18:50:05So8ressetpull_requests: + pull_request556
2017-03-15 17:06:09So8rescreate