Skip to content

Deriving builtins from ABCs implies incorrect and problematic metaclass structure #1595

Closed as not planned
@elazarg

Description

@elazarg

typeshed claims that str derives from Sequence and therefore indirectly from collections_abc.Sized whose metaclass is declared to be ABCMeta. This is done as a type-checkable alternative to Sequence.register(str) which handles isinstance and issubclass calls.

However derivation and register are not indistinguishable, since the metaclass structure is different. issubclass(type(str), ABCMeta) should be False, otherwise the definition class A(str, Enum): pass would fail at runtime due to inconsistent metaclass structure:

>>> from collections import Sized
>>> from enum import Enum
>>> class A(Sized, Enum): pass
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

The error is that type(Enum) is EnumMeta and type(Sized) is ABCMeta and they are unrelated.

This bug has at least the following implications:

  • It obviously implies that a: ABCMeta = str typechecks.
  • It makes it harder to warn about inconsistent metaclass structure without false positives. This is why mypy only catches specific cases.
  • As exemplified above, class A(str, Enum) appears to have inconsistent metaclass structure, even though this is the recommended way of making an enum of strings. It might also be the case with some other builtins.

Metadata

Metadata

Assignees

No one assigned

    Labels

    stubs: false negativeType checkers do not report an error, but should

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions