Skip to content

Commit

Permalink
feat(roll): roll to Playwright 1.38.0-alpha-sep-4-2023 (#2058)
Browse files Browse the repository at this point in the history
  • Loading branch information
mxschmitt authored Sep 5, 2023
1 parent 42c0bf1 commit 0e92fbc
Show file tree
Hide file tree
Showing 27 changed files with 486 additions and 187 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Playwright is a Python library to automate [Chromium](https://www.chromium.org/H

| | Linux | macOS | Windows |
| :--- | :---: | :---: | :---: |
| Chromium <!-- GEN:chromium-version -->116.0.5845.82<!-- GEN:stop --> ||||
| Chromium <!-- GEN:chromium-version -->117.0.5938.35<!-- GEN:stop --> ||||
| WebKit <!-- GEN:webkit-version -->17.0<!-- GEN:stop --> ||||
| Firefox <!-- GEN:firefox-version -->115.0<!-- GEN:stop --> ||||

Expand Down
18 changes: 15 additions & 3 deletions playwright/_impl/_api_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,23 @@

class Error(Exception):
def __init__(self, message: str) -> None:
self.message = message
self.name: Optional[str] = None
self.stack: Optional[str] = None
self._message = message
self._name: Optional[str] = None
self._stack: Optional[str] = None
super().__init__(message)

@property
def message(self) -> str:
return self._message

@property
def name(self) -> Optional[str]:
return self._name

@property
def stack(self) -> Optional[str]:
return self._stack


class TimeoutError(Error):
pass
2 changes: 2 additions & 0 deletions playwright/_impl/_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,3 +254,5 @@ async def prepare_browser_context_params(params: Dict) -> None:
params["reducedMotion"] = "no-override"
if params.get("forcedColors", None) == "null":
params["forcedColors"] = "no-override"
if "acceptDownloads" in params:
params["acceptDownloads"] = "accept" if params["acceptDownloads"] else "deny"
16 changes: 16 additions & 0 deletions playwright/_impl/_browser_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,13 @@
async_readfile,
async_writefile,
locals_to_params,
parse_error,
prepare_record_har_options,
to_impl,
)
from playwright._impl._network import Request, Response, Route, serialize_headers
from playwright._impl._page import BindingCall, Page, Worker
from playwright._impl._page_error import PageError
from playwright._impl._tracing import Tracing
from playwright._impl._wait_helper import WaitHelper

Expand All @@ -87,6 +89,7 @@ class BrowserContext(ChannelOwner):
Console="console",
Dialog="dialog",
Page="page",
PageError="pageerror",
ServiceWorker="serviceworker",
Request="request",
Response="response",
Expand Down Expand Up @@ -148,6 +151,13 @@ def __init__(
self._channel.on(
"dialog", lambda params: self._on_dialog(from_channel(params["dialog"]))
)
self._channel.on(
"pageError",
lambda params: self._on_page_error(
parse_error(params["error"]["error"]),
from_nullable_channel(params["page"]),
),
)
self._channel.on(
"request",
lambda params: self._on_request(
Expand Down Expand Up @@ -206,6 +216,7 @@ def _on_page(self, page: Page) -> None:
page._opener.emit(Page.Events.Popup, page)

async def _on_route(self, route: Route) -> None:
route._context = self
route_handlers = self._routes.copy()
for route_handler in route_handlers:
if not route_handler.matches(route.request.url):
Expand Down Expand Up @@ -555,6 +566,11 @@ def _on_dialog(self, dialog: Dialog) -> None:
else:
asyncio.create_task(dialog.dismiss())

async def _on_page_error(self, error: Error, page: Optional[Page]) -> None:
self.emit(BrowserContext.Events.PageError, PageError(self._loop, page, error))
if page:
page.emit(Page.Events.PageError, error)

def _on_request(self, request: Request, page: Optional[Page]) -> None:
self.emit(BrowserContext.Events.Request, request)
if page:
Expand Down
2 changes: 1 addition & 1 deletion playwright/_impl/_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ def dispatch(self, msg: ParsedMessagePayload) -> None:
error = msg.get("error")
if error:
parsed_error = parse_error(error["error"]) # type: ignore
parsed_error.stack = "".join(
parsed_error._stack = "".join(
traceback.format_list(callback.stack_trace)[-10:]
)
callback.future.set_exception(parsed_error)
Expand Down
22 changes: 8 additions & 14 deletions playwright/_impl/_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def __init__(
self._url = initializer["url"]
self._detached = False
self._child_frames: List[Frame] = []
self._page: "Page"
self._page: Optional[Page] = None
self._load_states: Set[str] = set(initializer["loadStates"])
self._event_emitter = EventEmitter()
self._channel.on(
Expand All @@ -105,33 +105,24 @@ def _on_load_state(
self._event_emitter.emit("loadstate", add)
elif remove and remove in self._load_states:
self._load_states.remove(remove)
if (
not self._parent_frame
and add == "load"
and hasattr(self, "_page")
and self._page
):
if not self._parent_frame and add == "load" and self._page:
self._page.emit("load", self._page)
if (
not self._parent_frame
and add == "domcontentloaded"
and hasattr(self, "_page")
and self._page
):
if not self._parent_frame and add == "domcontentloaded" and self._page:
self._page.emit("domcontentloaded", self._page)

def _on_frame_navigated(self, event: FrameNavigatedEvent) -> None:
self._url = event["url"]
self._name = event["name"]
self._event_emitter.emit("navigated", event)
if "error" not in event and hasattr(self, "_page") and self._page:
if "error" not in event and self._page:
self._page.emit("framenavigated", self)

async def _query_count(self, selector: str) -> int:
return await self._channel.send("queryCount", {"selector": selector})

@property
def page(self) -> "Page":
assert self._page
return self._page

async def goto(
Expand All @@ -151,6 +142,7 @@ async def goto(
def _setup_navigation_wait_helper(
self, wait_name: str, timeout: float = None
) -> WaitHelper:
assert self._page
wait_helper = WaitHelper(self._page, f"frame.{wait_name}")
wait_helper.reject_on_event(
self._page, "close", Error("Navigation failed because page was closed!")
Expand All @@ -175,6 +167,7 @@ def expect_navigation(
wait_until: DocumentLoadState = None,
timeout: float = None,
) -> EventContextManagerImpl[Response]:
assert self._page
if not wait_until:
wait_until = "load"

Expand Down Expand Up @@ -225,6 +218,7 @@ async def wait_for_url(
wait_until: DocumentLoadState = None,
timeout: float = None,
) -> None:
assert self._page
matcher = URLMatcher(self._page._browser_context._options.get("baseURL"), url)
if matcher.matches(self.url):
await self._wait_for_load_state_impl(state=wait_until, timeout=timeout)
Expand Down
4 changes: 2 additions & 2 deletions playwright/_impl/_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,8 @@ def parse_error(error: ErrorPayload) -> Error:
if error.get("name") == "TimeoutError":
base_error_class = TimeoutError
exc = base_error_class(cast(str, patch_error_message(error.get("message"))))
exc.name = error["name"]
exc.stack = error["stack"]
exc._name = error["name"]
exc._stack = error["stack"]
return exc


Expand Down
9 changes: 9 additions & 0 deletions playwright/_impl/_locator.py
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,15 @@ async def type(
**params,
)

async def press_sequentially(
self,
text: str,
delay: float = None,
timeout: float = None,
noWaitAfter: bool = None,
) -> None:
await self.type(text, delay=delay, timeout=timeout, noWaitAfter=noWaitAfter)

async def uncheck(
self,
position: Position = None,
Expand Down
46 changes: 34 additions & 12 deletions playwright/_impl/_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
from playwright._impl._wait_helper import WaitHelper

if TYPE_CHECKING: # pragma: no cover
from playwright._impl._browser_context import BrowserContext
from playwright._impl._fetch import APIResponse
from playwright._impl._frame import Frame
from playwright._impl._page import Page
Expand Down Expand Up @@ -191,7 +192,20 @@ async def response(self) -> Optional["Response"]:

@property
def frame(self) -> "Frame":
return from_channel(self._initializer["frame"])
if not self._initializer.get("frame"):
raise Error("Service Worker requests do not have an associated frame.")
frame = cast("Frame", from_channel(self._initializer["frame"]))
if not frame._page:
raise Error(
"\n".join(
[
"Frame for this navigation request is not available, because the request",
"was issued before the frame is created. You can check whether the request",
"is a navigation request by calling isNavigationRequest() method.",
]
)
)
return frame

def is_navigation_request(self) -> bool:
return self._initializer["isNavigationRequest"]
Expand Down Expand Up @@ -244,9 +258,15 @@ async def _actual_headers(self) -> "RawHeaders":
return await self._all_headers_future

def _target_closed_future(self) -> asyncio.Future:
if not hasattr(self.frame, "_page"):
frame = cast(
Optional["Frame"], from_nullable_channel(self._initializer.get("frame"))
)
if not frame:
return asyncio.Future()
return self.frame._page._closed_or_crashed_future
page = frame._page
if not page:
return asyncio.Future()
return page._closed_or_crashed_future


class Route(ChannelOwner):
Expand All @@ -255,6 +275,7 @@ def __init__(
) -> None:
super().__init__(parent, type, guid, initializer)
self._handling_future: Optional[asyncio.Future["bool"]] = None
self._context: "BrowserContext" = cast("BrowserContext", None)

def _start_handling(self) -> "asyncio.Future[bool]":
self._handling_future = asyncio.Future()
Expand Down Expand Up @@ -368,15 +389,16 @@ async def fetch(
maxRedirects: int = None,
timeout: float = None,
) -> "APIResponse":
page = self.request.frame._page
return await page.context.request._inner_fetch(
self.request,
url,
method,
headers,
postData,
maxRedirects=maxRedirects,
timeout=timeout,
return await self._connection.wrap_api_call(
lambda: self._context.request._inner_fetch(
self.request,
url,
method,
headers,
postData,
maxRedirects=maxRedirects,
timeout=timeout,
)
)

async def fallback(
Expand Down
8 changes: 1 addition & 7 deletions playwright/_impl/_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@
is_safe_close_error,
locals_to_params,
make_dirs_for_file,
parse_error,
serialize_error,
)
from playwright._impl._input import Keyboard, Mouse, Touchscreen
Expand Down Expand Up @@ -177,12 +176,6 @@ def __init__(
"frameDetached",
lambda params: self._on_frame_detached(from_channel(params["frame"])),
)
self._channel.on(
"pageError",
lambda params: self.emit(
Page.Events.PageError, parse_error(params["error"]["error"])
),
)
self._channel.on(
"route",
lambda params: asyncio.create_task(
Expand Down Expand Up @@ -239,6 +232,7 @@ def _on_frame_detached(self, frame: Frame) -> None:
self.emit(Page.Events.FrameDetached, frame)

async def _on_route(self, route: Route) -> None:
route._context = self.context
route_handlers = self._routes.copy()
for route_handler in route_handlers:
if not route_handler.matches(route.request.url):
Expand Down
36 changes: 36 additions & 0 deletions playwright/_impl/_page_error.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# 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.

from asyncio import AbstractEventLoop
from typing import Optional

from playwright._impl._helper import Error
from playwright._impl._page import Page


class PageError:
def __init__(
self, loop: AbstractEventLoop, page: Optional[Page], error: Error
) -> None:
self._loop = loop
self._page = page
self._error = error

@property
def page(self) -> Optional[Page]:
return self._page

@property
def error(self) -> Error:
return self._error
Loading

0 comments on commit 0e92fbc

Please sign in to comment.