Hey all, I recently ran into some trouble and that I think deserves some attention. Consider the following case:

    class A(ABC):
        @abstractmethod
        def __lt__(self, other):
            pass

    @dataclass(order=True)
    class B(A):
        x: int = 0

    class C(B):
        pass

Although B technically implements A's abstract methods, it is still considered an abstract class, and calling B() will fail. However, C is considered a non-abstract class and calling C() will succeed. This is because a class's "abstraction" is decided when a class is created. When B is created it does not implement __lt__, the implementation is added after creation by the dataclass decorator. Since C inherits from B after having its __lt__ set, C is considered non-abstract. This will also affect any "mixin-decorator" such as total_ordering, and also (a less-preferred use case) implementing abstract methods after class creation.

There are many solutions for this, my proposed solution is for abc.ABCMeta to implement a __setattr__, that erases unimplemented metaclasses f they are implemented after class creation, Something along these lines:
    class ABCMeta2(ABCMeta):
        def __setattr__(self, key, value):
            super().__setattr__(key, value)
            if key != '__abstractmethods__' and value is not None:
                self.__abstractmethods__ -= {key}

Obviously some additional logic is needed to handle sub-classes and such, but I think it's a good starting point.

Any thoughts?