inspect.isabstract returns false on an abstract class

Viewed 438

I need to determine if a class is abstract. The documentation of the inspect module indicates that inspect.isabstract should do this: https://docs.python.org/3/library/inspect.html

However, in python 3.8.6 I find that inspect.isabstract doesn't work the way I expect.

For instance, the following code, copied with slight modifications from https://github.com/python/cpython/blob/master/Lib/test/test_inspect.py:

import inspect
from abc import ABCMeta, abstractmethod

class AbstractClassExample(object):
    __metaclass__ = ABCMeta

    @abstractmethod
    def foo(self):
        pass

# Fails here
assert inspect.isabstract(AbstractClassExample)

The above code does work in python 2.7, but fails in python 3.8.6. Is this a bug in python 3.8.6, or did something change in how inspect.isabstract works?

1 Answers

You're using metaclasses incorrectly (in the Python 2 way, which is silently ignored on Python 3), so your class isn't actually an ABC (isabstract is reporting this correctly). Change:

class AbstractClassExample(object):  # There is no need to inherit from object on Py3 (it's automatic)
    __metaclass__ = ABCMeta  # This means nothing on Py3, it's just some random class attribute

to:

class MyABC(metaclass=ABCMeta):  # How you explicitly declare your metaclass on Py3

or just inherit from ABC, which is an otherwise empty class that has ABCMeta as a metaclass, which, unlike explicitly specifying a metaclass, allows you to use the same syntax in Python 2 and Python 3:

from abc import ABC

class MyABC(ABC):  # Inheriting from a class with the desired metaclass is simplest
Related