Repository: beartype/beartype

Issue #117: Can't mix Protocol and Abstract class
Created: 2022-03-31T21:12:55Z
The following code roars but I think it should purr :)
from abc import ABC, abstractmethod
from typing import Protocol, runtime_checkable

from beartype import beartype

@runtime_checkable
class Test(Protocol):
    something: int

class AbstractTest(Test, ABC):
    something = 1

    def foo(self):
        ...

    @abstractmethod
    def bar(self):
        ...

class NotAbstractTest(AbstractTest):
    def bar(self):
        ...

@beartype
def test(x: AbstractTest) -> None:
    ...

test(NotAbstractTest())

beartype.roar.BeartypeDecorHintPep484Exception: PEP 484 generic <class 'main.AbstractTest'> method resolution order (<class 'main.AbstractTest'>, <class 'main.Test'>, <class 'typing.Protocol'>, <class 'typing.Generic'>, <class 'abc.ABC'>, <class 'object'>) second-to-last item not <class 'typing.Generic'>.

Duplicate issue #168: Angry about method resolution order and `typing.Generic` for `gitpython` type
Created: 2022-09-18T18:22:35Z
See below.
../../conda/envs/anki/lib/python3.9/site-packages/_pytest/pathlib.py:533: in import_path
    importlib.import_module(module_name)
../../conda/envs/anki/lib/python3.9/importlib/__init__.py:127: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
<frozen importlib._bootstrap>:1030: in _gcd_import
    ???
<frozen importlib._bootstrap>:1007: in _find_and_load
    ???
<frozen importlib._bootstrap>:986: in _find_and_load_unlocked
    ???
<frozen importlib._bootstrap>:680: in _load_unlocked
    ???
../../conda/envs/anki/lib/python3.9/site-packages/_pytest/assertion/rewrite.py:168: in exec_module
    exec(co, module.__dict__)
tests/test_ki.py:31: in <module>
    import ki
ki/__init__.py:76: in <module>
    import ki.maybes as M
ki/maybes.py:18: in <module>
    import ki.functional as F
ki/functional.py:380: in <module>
    def rmsm(repo: git.Repo, sm: git.Repo) -> git.Commit:
../../conda/envs/anki/lib/python3.9/site-packages/beartype/_decor/cache/cachedecor.py:77: in beartype
    return beartype_args_mandatory(obj, conf)
../../conda/envs/anki/lib/python3.9/site-packages/beartype/_decor/_core.py:140: in beartype_args_mandatory
    return _beartype_func(func=obj, conf=conf)
../../conda/envs/anki/lib/python3.9/site-packages/beartype/_decor/_core.py:171: in _beartype_func
    func_wrapper_code = generate_code(func_data)
../../conda/envs/anki/lib/python3.9/site-packages/beartype/_decor/_code/codemain.py:226: in generate_code
    code_check_return = _code_check_return(bear_call)
../../conda/envs/anki/lib/python3.9/site-packages/beartype/_decor/_code/codemain.py:629: in _code_check_return
    reraise_exception_placeholder(
../../conda/envs/anki/lib/python3.9/site-packages/beartype/_util/error/utilerror.py:202: in reraise_exception_placeholder
    raise exception.with_traceback(exception.__traceback__)
../../conda/envs/anki/lib/python3.9/site-packages/beartype/_decor/_code/codemain.py:593: in _code_check_return
    ) = pep_code_check_hint(hint)
../../conda/envs/anki/lib/python3.9/site-packages/beartype/_util/cache/utilcachecall.py:343: in _callable_cached
    raise exception
../../conda/envs/anki/lib/python3.9/site-packages/beartype/_util/cache/utilcachecall.py:335: in _callable_cached
    return_value = params_flat_to_return_value[params_flat] = func(
../../conda/envs/anki/lib/python3.9/site-packages/beartype/_decor/_code/_pep/_pephint.py:1710: in pep_code_check_hint
    hint_childs = get_hint_pep484585_generic_bases_unerased(
../../conda/envs/anki/lib/python3.9/site-packages/beartype/_util/hint/pep/proposal/pep484585/utilpep484585generic.py:292: in get_hint_pep484585_generic_bases_unerased
    get_hint_pep484_generic_bases_unerased(hint)
../../conda/envs/anki/lib/python3.9/site-packages/beartype/_util/cache/utilcachecall.py:343: in _callable_cached
    raise exception
../../conda/envs/anki/lib/python3.9/site-packages/beartype/_util/cache/utilcachecall.py:335: in _callable_cached
    return_value = params_flat_to_return_value[params_flat] = func(
../../conda/envs/anki/lib/python3.9/site-packages/beartype/_util/hint/pep/proposal/pep484/utilpep484generic.py:451: in get_hint_pep484_generic_bases_unerased
    raise BeartypeDecorHintPep484Exception(
E   beartype.roar.BeartypeDecorHintPep484Exception: PEP 484 generic <class 'git.objects.commit.Commit'> method resolution order (<class 'git.objects.commit.Commit'>, <class 'git.objects.base.Object'>, <class 'gitdb.util.LazyMixin'>, <class 'git.objects.util.TraversableIterableObj'>, <class 'git.util.IterableObj'>, <class 'typing.Protocol'>, <class 'typing.Generic'>, <class 'git.objects.util.Traversable'>, <class 'git.diff.Diffable'>, <class 'git.objects.util.Serializable'>, <class 'abc.ABC'>, <class 'object'>) second-to-last item not <class 'typing.Generic'>.
==================================================== short test summary info =====================================================
ERROR tests/test_ki.py - beartype.roar.BeartypeDecorHintPep484Exception: PEP 484 generic <class 'git.objects.commit.Commit'> me...
ERROR tests/test_parser.py - beartype.roar.BeartypeDecorHintPep484Exception: PEP 484 generic <class 'git.objects.commit.Commit'...
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 2 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
======================================================= 2 errors in 1.43s ========================================================
make: *** [Makefile:16: unit] Error 2
I get the feeling this is somewhat expected behavior, and that @beartype is basically saying that the gitpython authors messed up their typing.Generic subclassing, i.e. it's not PEP-compliant. Does this error mean that types like git.Commit are fundamentally uncheckable? Anyone encounter this before and know of a workaround?

Closing comment (2022-09-18T19:19:03Z): Gah! Thanks so much for the rapid-fire heads up. I must confess I'd never even heard of GitPython – but now that I have I'm duly impressed. GitPython has my full attention, especially because git.Commit is the most frightening generic I've ever seen. There's like a billion different ABCs and mixins in that witch's brew, including multiple iterations of Traversable and Iterable APIs. 😱
Thankfully, I suspect this was both on @beartype's end and a duplicate of #117 from six months ago. Thankfully2, we just dropped the beartype 0.11.0 bomb finally resolving this for everyone at 3:00AM. That's why my head now feels like it's compressed in an iron vise. 
Would you mind updating @beartype on your side and giving that another go?