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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions