Skip to content

[Bug]: add_locator_handler with a handler that takes optional arguments with a type other than Locator does not cause a type error and crashes at runtime #3067

@DetachHead

Description

@DetachHead

Version

1.59.0

Steps to reproduce

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    page = p.chromium.launch(headless=False).new_page()

    input_field = page.locator("input")
    page.add_locator_handler(page.locator("div"), input_field.blur)
    page.set_content("<input></input><div>asdf</div>")
    page.click("div")

Expected behavior

either:

  • a type checker error
    • not sure if this is possible, would need to somehow ban certain subtypes of Callable[[], Any], may be achievable with overloads
    • perhaps add_locator_handler can be updated to enforce that the Locator argument is mandatory, and users who don't need to use the argument can simply use a _, for example:
      page.add_locator_handler(locator, lambda _: locator.click())
      this is a common pattern for event listeners, however it would be a breaking change
  • at runtime, SyncBase._wrap_handler should more accurately detect whether the function takes a positional argument of type Locator. currently it only checks the length of parameters, which is inaccurate:
    arg_count = len(inspect.signature(handler).parameters)
    return handler(
    *list(map(lambda a: self.from_maybe_impl(a), args))[:arg_count]
    )

Actual behavior

runtime error:

TypeError: Locator.blur() takes 1 positional argument but 2 were given

this is because Locator.blur takes an optional timeout keyword argument, which playwright incorrectly assumes is a positional argument that accepts a Locator.

there's no type error because a function where all its arguments are optional is a subtype of Callable[[], Any]

Additional context

ruff's unnecessary-lambda rule flags code like this:

page.add_locator_handler(page.locator("div"), lambda: input_field.blur())

when the user follows the suggestion to inline it, they'll encounter this issue.

Environment

- Python Version: 3.14

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions