basedmypy icon indicating copy to clipboard operation
basedmypy copied to clipboard

sound reach-ability on context managers

Open KotlinIsland opened this issue 2 years ago • 2 comments

The current solution is heuristic based and highly unsound.

This will require reworking AbstractContextManager to know about the types of Exception and return type of __exit__

class Base:
    def __enter__(self): ...
class A(Base):
    def __exit__(self, exc_type: object, exc_val: object, exc_tb: object) -> True: ...
class B(Base):
    def __exit__(self, exc_type: object, exc_val: object, exc_tb: object) -> False | None:

with A():
    raise Exception
print("hi")  # should not see a reach-ability error

with B():
    pass
print("hi")  # should not see a reach-ability error

with B():
    raise Exception
print("hi")  # should see a reach-ability error

But return should always report unreachable.

  • upstream at https://github.com/python/mypy/issues/8766

KotlinIsland avatar Sep 28 '23 07:09 KotlinIsland

Will have to update the type of: AbstractContextManager to have three params:

class AbstractContextManager[TEnter, TException: BaseException, TReturn: bool | None](ABC):

    def __enter__(self) -> TEnter: ...
    def __exit__(self, exc: TException) -> TReturn: ...

contextlib.contextmanager to capture the return type of the generator:

@overload
def contextmanager(func: Callable[_P, Generator[_T_co, object, True]]) -> Callable[_P, _GeneratorContextManager[_T_co, BaseException,True]]: ...
@overload
def contextmanager(func: Callable[_P, Iterator[_T_co]]) -> Callable[_P, _GeneratorContextManager[_T_co, object, bool | None]]: ...

And suppress:

class suppress[in_T_BaseException](AbstractContextManager[None, in_T_BaseException, True | None]): 
     def __init__(self, *exceptions: type[in_T_BaseExcaption]) -> None: ... 
     @overload
     def __exit__( 
         self, exctype: type[in_T_BaseException], excinst: in_T_BaseException, exctb: TracebackType
     ) -> True: ...
     @overload
     def __exit__( 
         self, exctype: type[BaseException] | None, excinst: BaseException | None, exctb: TracebackType | None 
     ) -> None: ...

KotlinIsland avatar Sep 29 '23 14:09 KotlinIsland

related #522

KotlinIsland avatar Oct 09 '23 08:10 KotlinIsland