Skip to content

[Bug]: Type Hinting for BrowserContext.__aexit__ Incompatible with AbstractAsyncContextManager #2856

Open
@nva14

Description

@nva14

Version

1.52

Steps to reproduce

In Playwright v1.52.0, the effective type signature for playwright.async_api.BrowserContext.__aexit__ does not seem to mark its exception-related parameters (exc_type, exc_val, traceback) as Optional (e.g., Type[BaseException] | None).

This causes type checking issues with static analyzers like Pylance when BrowserContext instances are used with constructs expecting typing.AbstractAsyncContextManager, such as contextlib.AsyncExitStack().enter_async_context().

Pylance Inferred Signature:

(method) def __aexit__(
    exc_type: type[BaseException],
    exc_val: BaseException,
    traceback: TracebackType
) -> Coroutine[Any, Any, None]

Expected behavior

for AbstractAsyncContextManager compatibility:

(method) async def __aexit__(
    self,
    exc_type: type[BaseException] | None,
    exc_val: BaseException | None,
    traceback: TracebackType | None
) -> Coroutine[Any, Any, bool | None] # Or just None for return

Actual behavior

Static type checkers report complaints because the non-optional parameters are incompatible with the protocol, which expects None to be passed for these arguments on normal context exit.

I'm currently using typing.cast(AsyncContextManager[BrowserContext], browser_context_instance) allows type checkers to proceed.

Additional context

Reproducible example:

import asyncio
from contextlib import AsyncExitStack
from playwright.async_api import async_playwright, BrowserContext

async def main():
    async with AsyncExitStack() as stack:
        pw_manager = async_playwright()
        playwright = await stack.enter_async_context(pw_manager)
        browser_ctx_instance: BrowserContext = await playwright.firefox.launch_persistent_context()
        await stack.enter_async_context(browser_ctx_instance) # <-- Pylance complaint here

        print("Context entered")
        # ...
        await browser.close() # clean up browser launched outside stack for this example

# asyncio.run(main())

Environment

- Operating System: Debian 12
- CPU: [arm64]
- Browser: [All, Chromium, Firefox, WebKit]
- Python Version: [3.13]
- Other info: I'm using DevContainer in VS Code with Pylance. It's on macOS but effective OS is Debian because i'm running image based on `mcr.microsoft.com/devcontainers/python:3-bookworm`

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions