Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude/skills/playwright-roll/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,10 @@ Implement the change in `playwright/_impl/<module>.py`. Use the upstream JS impl

When implementing a new ChannelOwner subclass (one constructed by the protocol with `(parent, type, guid, initializer)`):
1. Register it in `playwright/_impl/_object_factory.py:create_remote_object` — otherwise the guid resolves to `DummyObject` and downstream code breaks mysteriously.
2. Nothing to do in codegen: the generator emits every Python class in the docs. If the class does not live in `_impl/_<snake_case name>.py`, add it to `implModules` in `scripts/codegen/python_rules.js`.
2. Add it to `playwright/_impl/_api_classes.py` (the import and `__all__`). The generator emits every Python class in the docs, and the generated API imports each implementation from that file. If the class is missing there, `_generated.py` fails to import.

When implementing a non-ChannelOwner wrapper class (a plain class that holds a Page/Context reference, like `Screencast`, `Clock`):
- Add it to `playwright/_impl/_api_classes.py`, as for a ChannelOwner subclass.
- Set `self._loop = parent._loop` and `self._dispatcher_fiber = parent._dispatcher_fiber` in `__init__`. The generated `AsyncBase`/`SyncBase` wrappers read these; missing them gives `AttributeError: 'X' object has no attribute '_loop'` at first use.

When the docs add a new struct (an inline `[Object]` with named fields):
Expand Down Expand Up @@ -314,7 +315,6 @@ All keys use docs names: `Class.member` or `Class.member.arg`, with the upstream
| `extraMembers`, `extraOptions` | Python-only members and hidden options; generated without docstrings. |
| `positionalOptions` | Option names that are positional everywhere (`predicate`). |
| `structTotal` | `total=` of a TypedDict, where it differs from "total=False if any field is optional". |
| `implModules` | `_impl/` module of classes not in `_<snake_case name>.py`. |

## Tips & gotchas

Expand Down
101 changes: 101 additions & 0 deletions playwright/_impl/_api_classes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Copyright (c) Microsoft Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# The implementation of every class in the generated API. The generated API
# imports them from here, so the generator does not need to know which module
# holds each class.

from playwright._impl._assertions import (
APIResponseAssertions,
LocatorAssertions,
PageAssertions,
)
from playwright._impl._browser import Browser
from playwright._impl._browser_context import BrowserContext
from playwright._impl._browser_type import BrowserType
from playwright._impl._cdp_session import CDPSession
from playwright._impl._clock import Clock
from playwright._impl._console_message import ConsoleMessage
from playwright._impl._credentials import Credentials
from playwright._impl._debugger import Debugger
from playwright._impl._dialog import Dialog
from playwright._impl._disposable import Disposable
from playwright._impl._download import Download
from playwright._impl._element_handle import ElementHandle
from playwright._impl._fetch import APIRequest, APIRequestContext, APIResponse
from playwright._impl._file_chooser import FileChooser
from playwright._impl._frame import Frame
from playwright._impl._input import Keyboard, Mouse, Touchscreen
from playwright._impl._js_handle import JSHandle
from playwright._impl._locator import FrameLocator, Locator
from playwright._impl._network import (
Request,
Response,
Route,
WebSocket,
WebSocketRoute,
)
from playwright._impl._page import Page, Worker
from playwright._impl._playwright import Playwright
from playwright._impl._screencast import Screencast
from playwright._impl._selectors import Selectors
from playwright._impl._tracing import Tracing
from playwright._impl._video import Video
from playwright._impl._web_error import WebError
from playwright._impl._web_mcp import WebMCP
from playwright._impl._web_storage import WebStorage

__all__ = [
"APIRequest",
"APIRequestContext",
"APIResponse",
"APIResponseAssertions",
"Browser",
"BrowserContext",
"BrowserType",
"CDPSession",
"Clock",
"ConsoleMessage",
"Credentials",
"Debugger",
"Dialog",
"Disposable",
"Download",
"ElementHandle",
"FileChooser",
"Frame",
"FrameLocator",
"JSHandle",
"Keyboard",
"Locator",
"LocatorAssertions",
"Mouse",
"Page",
"PageAssertions",
"Playwright",
"Request",
"Response",
"Route",
"Screencast",
"Selectors",
"Touchscreen",
"Tracing",
"Video",
"WebError",
"WebMCP",
"WebSocket",
"WebSocketRoute",
"WebStorage",
"Worker",
]
2 changes: 1 addition & 1 deletion playwright/_impl/_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
from playwright._impl._network import Response
from playwright._impl._set_input_files_helpers import convert_input_files
from playwright._impl._waiter import Waiter
from playwright._impl._webmcp import WebMCP
from playwright._impl._web_mcp import WebMCP

if TYPE_CHECKING: # pragma: no cover
from playwright._impl._page import Page
Expand Down
2 changes: 1 addition & 1 deletion playwright/_impl/_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@
from playwright._impl._signature import signature
from playwright._impl._video import Video
from playwright._impl._waiter import Waiter
from playwright._impl._web_mcp import WebMCP
from playwright._impl._web_storage import WebStorage
from playwright._impl._webmcp import WebMCP

if TYPE_CHECKING: # pragma: no cover
from playwright._impl._browser_context import BrowserContext
Expand Down
File renamed without changes.
86 changes: 43 additions & 43 deletions playwright/async_api/_generated.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,49 @@
import typing
from typing import Literal

from playwright._impl._api_classes import APIRequest as APIRequestImpl
from playwright._impl._api_classes import APIRequestContext as APIRequestContextImpl
from playwright._impl._api_classes import APIResponse as APIResponseImpl
from playwright._impl._api_classes import (
APIResponseAssertions as APIResponseAssertionsImpl,
)
from playwright._impl._api_classes import Browser as BrowserImpl
from playwright._impl._api_classes import BrowserContext as BrowserContextImpl
from playwright._impl._api_classes import BrowserType as BrowserTypeImpl
from playwright._impl._api_classes import CDPSession as CDPSessionImpl
from playwright._impl._api_classes import Clock as ClockImpl
from playwright._impl._api_classes import ConsoleMessage as ConsoleMessageImpl
from playwright._impl._api_classes import Credentials as CredentialsImpl
from playwright._impl._api_classes import Debugger as DebuggerImpl
from playwright._impl._api_classes import Dialog as DialogImpl
from playwright._impl._api_classes import Disposable as DisposableImpl
from playwright._impl._api_classes import Download as DownloadImpl
from playwright._impl._api_classes import ElementHandle as ElementHandleImpl
from playwright._impl._api_classes import FileChooser as FileChooserImpl
from playwright._impl._api_classes import Frame as FrameImpl
from playwright._impl._api_classes import FrameLocator as FrameLocatorImpl
from playwright._impl._api_classes import JSHandle as JSHandleImpl
from playwright._impl._api_classes import Keyboard as KeyboardImpl
from playwright._impl._api_classes import Locator as LocatorImpl
from playwright._impl._api_classes import LocatorAssertions as LocatorAssertionsImpl
from playwright._impl._api_classes import Mouse as MouseImpl
from playwright._impl._api_classes import Page as PageImpl
from playwright._impl._api_classes import PageAssertions as PageAssertionsImpl
from playwright._impl._api_classes import Playwright as PlaywrightImpl
from playwright._impl._api_classes import Request as RequestImpl
from playwright._impl._api_classes import Response as ResponseImpl
from playwright._impl._api_classes import Route as RouteImpl
from playwright._impl._api_classes import Screencast as ScreencastImpl
from playwright._impl._api_classes import Selectors as SelectorsImpl
from playwright._impl._api_classes import Touchscreen as TouchscreenImpl
from playwright._impl._api_classes import Tracing as TracingImpl
from playwright._impl._api_classes import Video as VideoImpl
from playwright._impl._api_classes import WebError as WebErrorImpl
from playwright._impl._api_classes import WebMCP as WebMCPImpl
from playwright._impl._api_classes import WebSocket as WebSocketImpl
from playwright._impl._api_classes import WebSocketRoute as WebSocketRouteImpl
from playwright._impl._api_classes import WebStorage as WebStorageImpl
from playwright._impl._api_classes import Worker as WorkerImpl
from playwright._impl._api_structures import (
BrowserBindResult,
ClientCertificate,
Expand Down Expand Up @@ -53,58 +96,15 @@
WebMCPTool,
WebStorageItem,
)
from playwright._impl._assertions import (
APIResponseAssertions as APIResponseAssertionsImpl,
)
from playwright._impl._assertions import LocatorAssertions as LocatorAssertionsImpl
from playwright._impl._assertions import PageAssertions as PageAssertionsImpl
from playwright._impl._async_base import (
AsyncBase,
AsyncContextManager,
AsyncEventContextManager,
mapping,
)
from playwright._impl._browser import Browser as BrowserImpl
from playwright._impl._browser_context import BrowserContext as BrowserContextImpl
from playwright._impl._browser_type import BrowserType as BrowserTypeImpl
from playwright._impl._cdp_session import CDPSession as CDPSessionImpl
from playwright._impl._clock import Clock as ClockImpl
from playwright._impl._console_message import ConsoleMessage as ConsoleMessageImpl
from playwright._impl._credentials import Credentials as CredentialsImpl
from playwright._impl._debugger import Debugger as DebuggerImpl
from playwright._impl._dialog import Dialog as DialogImpl
from playwright._impl._disposable import Disposable as DisposableImpl
from playwright._impl._download import Download as DownloadImpl
from playwright._impl._element_handle import ElementHandle as ElementHandleImpl
from playwright._impl._errors import Error
from playwright._impl._fetch import APIRequest as APIRequestImpl
from playwright._impl._fetch import APIRequestContext as APIRequestContextImpl
from playwright._impl._fetch import APIResponse as APIResponseImpl
from playwright._impl._file_chooser import FileChooser as FileChooserImpl
from playwright._impl._form_data import FormData
from playwright._impl._frame import Frame as FrameImpl
from playwright._impl._helper import to_milliseconds
from playwright._impl._input import Keyboard as KeyboardImpl
from playwright._impl._input import Mouse as MouseImpl
from playwright._impl._input import Touchscreen as TouchscreenImpl
from playwright._impl._js_handle import JSHandle as JSHandleImpl
from playwright._impl._locator import FrameLocator as FrameLocatorImpl
from playwright._impl._locator import Locator as LocatorImpl
from playwright._impl._network import Request as RequestImpl
from playwright._impl._network import Response as ResponseImpl
from playwright._impl._network import Route as RouteImpl
from playwright._impl._network import WebSocket as WebSocketImpl
from playwright._impl._network import WebSocketRoute as WebSocketRouteImpl
from playwright._impl._page import Page as PageImpl
from playwright._impl._page import Worker as WorkerImpl
from playwright._impl._playwright import Playwright as PlaywrightImpl
from playwright._impl._screencast import Screencast as ScreencastImpl
from playwright._impl._selectors import Selectors as SelectorsImpl
from playwright._impl._tracing import Tracing as TracingImpl
from playwright._impl._video import Video as VideoImpl
from playwright._impl._web_error import WebError as WebErrorImpl
from playwright._impl._web_storage import WebStorage as WebStorageImpl
from playwright._impl._webmcp import WebMCP as WebMCPImpl


class APIRequest(AsyncBase):
Expand Down
86 changes: 43 additions & 43 deletions playwright/sync_api/_generated.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,49 @@
import typing
from typing import Literal

from playwright._impl._api_classes import APIRequest as APIRequestImpl
from playwright._impl._api_classes import APIRequestContext as APIRequestContextImpl
from playwright._impl._api_classes import APIResponse as APIResponseImpl
from playwright._impl._api_classes import (
APIResponseAssertions as APIResponseAssertionsImpl,
)
from playwright._impl._api_classes import Browser as BrowserImpl
from playwright._impl._api_classes import BrowserContext as BrowserContextImpl
from playwright._impl._api_classes import BrowserType as BrowserTypeImpl
from playwright._impl._api_classes import CDPSession as CDPSessionImpl
from playwright._impl._api_classes import Clock as ClockImpl
from playwright._impl._api_classes import ConsoleMessage as ConsoleMessageImpl
from playwright._impl._api_classes import Credentials as CredentialsImpl
from playwright._impl._api_classes import Debugger as DebuggerImpl
from playwright._impl._api_classes import Dialog as DialogImpl
from playwright._impl._api_classes import Disposable as DisposableImpl
from playwright._impl._api_classes import Download as DownloadImpl
from playwright._impl._api_classes import ElementHandle as ElementHandleImpl
from playwright._impl._api_classes import FileChooser as FileChooserImpl
from playwright._impl._api_classes import Frame as FrameImpl
from playwright._impl._api_classes import FrameLocator as FrameLocatorImpl
from playwright._impl._api_classes import JSHandle as JSHandleImpl
from playwright._impl._api_classes import Keyboard as KeyboardImpl
from playwright._impl._api_classes import Locator as LocatorImpl
from playwright._impl._api_classes import LocatorAssertions as LocatorAssertionsImpl
from playwright._impl._api_classes import Mouse as MouseImpl
from playwright._impl._api_classes import Page as PageImpl
from playwright._impl._api_classes import PageAssertions as PageAssertionsImpl
from playwright._impl._api_classes import Playwright as PlaywrightImpl
from playwright._impl._api_classes import Request as RequestImpl
from playwright._impl._api_classes import Response as ResponseImpl
from playwright._impl._api_classes import Route as RouteImpl
from playwright._impl._api_classes import Screencast as ScreencastImpl
from playwright._impl._api_classes import Selectors as SelectorsImpl
from playwright._impl._api_classes import Touchscreen as TouchscreenImpl
from playwright._impl._api_classes import Tracing as TracingImpl
from playwright._impl._api_classes import Video as VideoImpl
from playwright._impl._api_classes import WebError as WebErrorImpl
from playwright._impl._api_classes import WebMCP as WebMCPImpl
from playwright._impl._api_classes import WebSocket as WebSocketImpl
from playwright._impl._api_classes import WebSocketRoute as WebSocketRouteImpl
from playwright._impl._api_classes import WebStorage as WebStorageImpl
from playwright._impl._api_classes import Worker as WorkerImpl
from playwright._impl._api_structures import (
BrowserBindResult,
ClientCertificate,
Expand Down Expand Up @@ -53,58 +96,15 @@
WebMCPTool,
WebStorageItem,
)
from playwright._impl._assertions import (
APIResponseAssertions as APIResponseAssertionsImpl,
)
from playwright._impl._assertions import LocatorAssertions as LocatorAssertionsImpl
from playwright._impl._assertions import PageAssertions as PageAssertionsImpl
from playwright._impl._browser import Browser as BrowserImpl
from playwright._impl._browser_context import BrowserContext as BrowserContextImpl
from playwright._impl._browser_type import BrowserType as BrowserTypeImpl
from playwright._impl._cdp_session import CDPSession as CDPSessionImpl
from playwright._impl._clock import Clock as ClockImpl
from playwright._impl._console_message import ConsoleMessage as ConsoleMessageImpl
from playwright._impl._credentials import Credentials as CredentialsImpl
from playwright._impl._debugger import Debugger as DebuggerImpl
from playwright._impl._dialog import Dialog as DialogImpl
from playwright._impl._disposable import Disposable as DisposableImpl
from playwright._impl._download import Download as DownloadImpl
from playwright._impl._element_handle import ElementHandle as ElementHandleImpl
from playwright._impl._errors import Error
from playwright._impl._fetch import APIRequest as APIRequestImpl
from playwright._impl._fetch import APIRequestContext as APIRequestContextImpl
from playwright._impl._fetch import APIResponse as APIResponseImpl
from playwright._impl._file_chooser import FileChooser as FileChooserImpl
from playwright._impl._form_data import FormData
from playwright._impl._frame import Frame as FrameImpl
from playwright._impl._helper import to_milliseconds
from playwright._impl._input import Keyboard as KeyboardImpl
from playwright._impl._input import Mouse as MouseImpl
from playwright._impl._input import Touchscreen as TouchscreenImpl
from playwright._impl._js_handle import JSHandle as JSHandleImpl
from playwright._impl._locator import FrameLocator as FrameLocatorImpl
from playwright._impl._locator import Locator as LocatorImpl
from playwright._impl._network import Request as RequestImpl
from playwright._impl._network import Response as ResponseImpl
from playwright._impl._network import Route as RouteImpl
from playwright._impl._network import WebSocket as WebSocketImpl
from playwright._impl._network import WebSocketRoute as WebSocketRouteImpl
from playwright._impl._page import Page as PageImpl
from playwright._impl._page import Worker as WorkerImpl
from playwright._impl._playwright import Playwright as PlaywrightImpl
from playwright._impl._screencast import Screencast as ScreencastImpl
from playwright._impl._selectors import Selectors as SelectorsImpl
from playwright._impl._sync_base import (
EventContextManager,
SyncBase,
SyncContextManager,
mapping,
)
from playwright._impl._tracing import Tracing as TracingImpl
from playwright._impl._video import Video as VideoImpl
from playwright._impl._web_error import WebError as WebErrorImpl
from playwright._impl._web_storage import WebStorage as WebStorageImpl
from playwright._impl._webmcp import WebMCP as WebMCPImpl


class APIRequest(SyncBase):
Expand Down
9 changes: 2 additions & 7 deletions scripts/codegen/generate_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -821,11 +821,6 @@ const LICENSE = `# Copyright (c) Microsoft Corporation.
# limitations under the License.
`;

/** @param {string} className */
function implModule(className) {
return lookupRule('implModules', className) || `_${toSnakeCase(className)}`;
}

/** @param {any} event */
function eventPayload(clazz, event) {
let payload = docType(toPy(event.type, { dir: 'out', place: `${clazz.name}.${event.name}` }));
Expand Down Expand Up @@ -1104,7 +1099,7 @@ function emitStructs() {
}

function checkRules() {
for (const table of ['extraMembers', 'extraOptions', 'structTotal', 'implModules']) {
for (const table of ['extraMembers', 'extraOptions', 'structTotal']) {
for (const key of Object.keys(/** @type {any} */ (rules)[table])) {
if (!usedRules.has(`${table}:${key}`))
errors.push(`${table}: the entry "${key}" no longer matches anything; remove it`);
Expand All @@ -1128,7 +1123,7 @@ function main() {
if (usedStructs.size)
header.push(`from playwright._impl._api_structures import ${[...usedStructs].sort().join(', ')}`);
for (const clazz of classes)
header.push(`from playwright._impl.${implModule(clazz.name)} import ${clazz.name} as ${clazz.name}Impl`);
header.push(`from playwright._impl._api_classes import ${clazz.name} as ${clazz.name}Impl`);
header.push('from playwright._impl._errors import Error');
header.push('from playwright._impl._form_data import FormData');
header.push('from playwright._impl._helper import to_milliseconds');
Expand Down
Loading
Loading