playwright-roll
Rolling Playwright Python
The goal of a roll is to move the driver pin in DRIVER_VERSION to a new release, port every public API change introduced upstream during that interval, and suppress the rest, so that ./scripts/update_api.sh and mypy playwright run clean and the test suite still passes.
The previous human-facing summary lives in ../../../ROLLING.md. This skill is the operational playbook — read it end to end before starting.
Mental model
The Python port is hand-written code in playwright/_impl/, plus a generator (scripts/codegen/generate_api.js) that:
- parses the upstream docs (
$PW_SRC_DIR/docs/src/api) with the upstream parser and filters them for Python, - applies the Python facts that the docs do not contain, from
scripts/codegen/python_rules.js, and - emits the whole public API into
playwright/{async,sync}_api/_generated.py: signatures, types, docstrings, event overloads, and the call into_impl/for every member.
The generator never reads _impl/. A new member or option in the docs therefore shows up in _generated.py right away, as a call into _impl/ that does not exist yet. Each generated class types its _impl_obj, so mypy playwright lists every such gap as an error in _generated.py. Three resolutions:
- PORT — the new API is intended for Python (no
langs.onlyfilter, orlangs.onlyincludes"python"). Implement it in_impl/until mypy is clean. - MISMATCH — the shipped Python API differs from the docs (a callback signature uses unions, a kwarg uses a legacy name, etc.). The shipped implementation wins. Add an entry to
scripts/codegen/python_rules.jswith a comment explaining why, and propose the upstream docs change that would make the entry unnecessary. - N/A — the commit only touches docs, has
* langs: js(or any other filter that excludes Python), is server-side, Electron-only, or was reverted later in the same release. No action; the generator already leaves it out.