Skip to main content

Lib/abc.py

cpython 3.14 @ ab2d84fe1023/Lib/abc.py

Lib/abc.py is the pure-Python surface of Python's Abstract Base Class machinery. Most of the heavy lifting runs inside the _abc C extension; this file wires it together, exposes the public decorators, and provides the ABC convenience base class.

Map

SymbolLinesKindNotes
abstractmethod7-25decoratorSets __isabstractmethod__ = True on a callable
abstractclassmethod28-45classDeprecated; combines classmethod + abstract flag
abstractstaticmethod48-65classDeprecated; combines staticmethod + abstract flag
abstractproperty68-82classDeprecated; combines property + abstract flag
ABCMeta.__new__105-108metaclass methodCalls _abc_init to set up per-class ABC state
ABCMeta.register110-115methodDelegates to _abc_register; returns subclass
ABCMeta.__instancecheck__117-119methodOverrides isinstance via _abc_instancecheck
ABCMeta.__subclasscheck__121-123methodOverrides issubclass via _abc_subclasscheck
ABCMeta._dump_registry125-135debug helperPrints cache state via _get_dump
update_abstractmethods146-181functionRecalculates __abstractmethods__ after patching
ABC184-188classZero-slot base; uses ABCMeta as its metaclass

Reading

The abstractmethod decorator

The decorator is intentionally minimal. It does exactly one thing: brand the callable with a sentinel attribute that type.__new__ checks when building __abstractmethods__.

# CPython: Lib/abc.py:7 abstractmethod
def abstractmethod(funcobj):
funcobj.__isabstractmethod__ = True
return funcobj

type.__new__ (in Objects/typeobject.c) scans the new class's namespace for any attribute whose __isabstractmethod__ is true and builds the frozenset stored in __abstractmethods__. Instantiating a class with a non-empty __abstractmethods__ raises TypeError.

The three deprecated variants (abstractclassmethod, abstractstaticmethod, abstractproperty) set the same sentinel both on the wrapper and on the wrapped callable, because wrapping can otherwise hide the flag from the scanner.

ABCMeta and the _abc C extension

When _abc is available (it almost always is), ABCMeta.__new__ calls _abc_init to attach four per-class C-level fields: a weak-reference registry of virtual subclasses, a positive cache, a negative cache, and a version counter.

# CPython: Lib/abc.py:105 ABCMeta.__new__
def __new__(mcls, name, bases, namespace, /, **kwargs):
cls = super().__new__(mcls, name, bases, namespace, **kwargs)
_abc_init(cls)
return cls

register and the two check hooks (__instancecheck__, __subclasscheck__) are thin one-liners that forward directly into C. The cache invalidation token returned by get_cache_token() increments globally each time any ABC's registry changes; this lets the negative cache be discarded cheaply across the whole interpreter.

The fallback path (lines 89-90) imports _py_abc.ABCMeta from a pure-Python implementation used in testing environments where the C extension is absent.

update_abstractmethods

Added in Python 3.10, this function handles a gap in the original design: if you monkey-patch a method onto a class after it was created, the __abstractmethods__ set is stale. update_abstractmethods rebuilds it by walking __bases__ and the class's own __dict__.

# CPython: Lib/abc.py:168 update_abstractmethods
abstracts = set()
for scls in cls.__bases__:
for name in getattr(scls, '__abstractmethods__', ()):
value = getattr(cls, name, None)
if getattr(value, "__isabstractmethod__", False):
abstracts.add(name)
for name, value in cls.__dict__.items():
if getattr(value, "__isabstractmethod__", False):
abstracts.add(name)
cls.__abstractmethods__ = frozenset(abstracts)

It is a no-op on classes that do not have __abstractmethods__ at all (C types, for instance).

gopy notes

Status: not yet ported.

Planned package path: module/abc/.

The pure decorator (abstractmethod) and the ABC base class can be implemented immediately as Python-level objects. ABCMeta requires the four C-level per-class fields; the natural home for those in gopy is a side-table keyed on the type pointer, parallel to how _abc allocates them via _PyABCData in Modules/_abc.c. The _py_abc fallback path is the right starting point for a first pass before the C extension is ported.