From efa71e05b8d8d06821577aa86fb25f0288a54d08 Mon Sep 17 00:00:00 2001 From: Nate Date: Mon, 24 Apr 2017 10:06:15 -0700 Subject: [PATCH 1/4] Resolved the merge conflict in Misc/NEWS. Probably. --- Lib/inspect.py | 23 ++++++++++++++++++++++- Lib/test/test_inspect.py | 24 ++++++++++++++++++++++++ Misc/NEWS | 6 ++++++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/Lib/inspect.py b/Lib/inspect.py index a2dcb888a0c609..2894672f501e8b 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -31,6 +31,7 @@ __author__ = ('Ka-Ping Yee ', 'Yury Selivanov ') +import abc import ast import dis import collections.abc @@ -291,7 +292,27 @@ def isroutine(object): def isabstract(object): """Return true if the object is an abstract base class (ABC).""" - return bool(isinstance(object, type) and object.__flags__ & TPFLAGS_IS_ABSTRACT) + if not isinstance(object, type): + return False + if object.__flags__ & TPFLAGS_IS_ABSTRACT: + return True + if not issubclass(type(object), abc.ABCMeta): + return False + if hasattr(object, '__abstractmethods__'): + # It looks like ABCMeta.__new__ has finished running; + # TPFLAGS_IS_ABSTRACT should have been accurate. + return False + # It looks like ABCMeta.__new__ has not finished running yet; we're + # probably in __init_subclass__. We'll look for abstractmethods manually. + for name, value in object.__dict__.items(): + if getattr(value, "__isabstractmethod__", False): + return True + for base in object.__bases__: + for name in getattr(base, "__abstractmethods__", ()): + value = getattr(object, name, None) + if getattr(value, "__isabstractmethod__", False): + return True + return False def getmembers(object, predicate=None): """Return all members of an object as (name, value) pairs sorted by name. diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index cfea281c70db11..37e451188a97be 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -232,6 +232,30 @@ def foo(self): self.assertFalse(inspect.isabstract(int)) self.assertFalse(inspect.isabstract(5)) + def test_isabstract_during_init_subclass(self): + from abc import ABCMeta, abstractmethod + isabstract_checks = [] + class AbstractChecker(metaclass=ABCMeta): + def __init_subclass__(cls): + isabstract_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]) + + isabstract_checks.clear() + class AbstractChild(AbstractClassExample): + pass + class AbstractGrandchild(AbstractChild): + pass + class ConcreteGrandchild(ClassExample): + pass + self.assertEqual(isabstract_checks, [True, True, False]) + class TestInterpreterStack(IsTestBase): def __init__(self, *args, **kwargs): diff --git a/Misc/NEWS b/Misc/NEWS index 6177ee40ab6577..12368a7dd34cd7 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -45,6 +45,9 @@ Core and Builtins Library ------- +- bpo-29822: inspect.isabstract() now works during __init_subclass__. Patch + by Nate Soares. + - bpo-30557: faulthandler now correctly filters and displays exception codes on Windows @@ -97,6 +100,9 @@ Library - bpo-30205: Fix getsockname() for unbound AF_UNIX sockets on Linux. +- bpo-29960: Preserve generator state when _random.Random.setstate() + raises an exception. Patch by Bryan Olson. + - bpo-30070: Fixed leaks and crashes in errors handling in the parser module. - bpo-30061: Fixed crashes in IOBase methods __next__() and readlines() when From 0ea7e8e93ec1818102db4e94af4f8ee43e981cd2 Mon Sep 17 00:00:00 2001 From: Nate Soares Date: Tue, 6 Jun 2017 17:16:24 -0700 Subject: [PATCH 2/4] [3.6] bpo-29822: Make inspect.isabstract() work during __init_subclass__. (GH-678) At the time when an abstract base class' __init_subclass__ runs, ABCMeta.__new__ has not yet finished running, so in the presence of __init_subclass__, inspect.isabstract() can no longer depend only on TPFLAGS_IS_ABSTRACT.. (cherry picked from commit fcfe80ec2592fed8b3941c79056a8737abef7d3b) From bdf3a103923a55e39246bb2c228b4c6767396689 Mon Sep 17 00:00:00 2001 From: Nate Date: Tue, 6 Jun 2017 17:21:44 -0700 Subject: [PATCH 3/4] Removed apparently-spurious news item This PR was generated by cherry_picker.py. There was a merge conflict in Misc/NEWS that I thought I resolved correctly, but the diff of this branch with master shows that the news item is new-to-this-PR. I'm not sure what's going on, but this commit removes the news item. I'd appreciate a second pair of eyes making sure that I'm doing things right. --- Misc/NEWS | 3 --- 1 file changed, 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS index 12368a7dd34cd7..6ea8b3aa61b7a8 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -54,9 +54,6 @@ Library - bpo-30378: Fix the problem that logging.handlers.SysLogHandler cannot handle IPv6 addresses. -- bpo-29960: Preserve generator state when _random.Random.setstate() - raises an exception. Patch by Bryan Olson. - - bpo-30414: multiprocessing.Queue._feed background running thread do not break from main loop on exception. From f5f0a82537440a1fd179846c2a570a9af02613f3 Mon Sep 17 00:00:00 2001 From: Nate Date: Tue, 6 Jun 2017 17:25:22 -0700 Subject: [PATCH 4/4] Un-did the shifting of a NEWS item The cherry-pick apparently introduced a duplicate item in Misc/NEWS, not sure exactly how. The previous commit removed one copy, but I accidentally removed the spurious copy. I *think* this commit will set things right. --- Misc/NEWS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS index 6ea8b3aa61b7a8..efcad87dcded99 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -54,6 +54,9 @@ Library - bpo-30378: Fix the problem that logging.handlers.SysLogHandler cannot handle IPv6 addresses. +- bpo-29960: Preserve generator state when _random.Random.setstate() + raises an exception. Patch by Bryan Olson. + - bpo-30414: multiprocessing.Queue._feed background running thread do not break from main loop on exception. @@ -97,9 +100,6 @@ Library - bpo-30205: Fix getsockname() for unbound AF_UNIX sockets on Linux. -- bpo-29960: Preserve generator state when _random.Random.setstate() - raises an exception. Patch by Bryan Olson. - - bpo-30070: Fixed leaks and crashes in errors handling in the parser module. - bpo-30061: Fixed crashes in IOBase methods __next__() and readlines() when