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
2 changes: 1 addition & 1 deletion api.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions build_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@

from playwright.path_utils import get_file_dirname

driver_version_64 = "0.160.0-next.1604019206789"
driver_version_32 = "0.160.0-next.1604019246361"
driver_version_64 = "0.160.0-next.1604373941495"
driver_version_32 = "0.160.0-next.1604373978475"


def driver_version(platform: str) -> str:
Expand Down
4 changes: 2 additions & 2 deletions playwright/async_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -5880,7 +5880,7 @@ async def newContext(
acceptDownloads : Optional[bool]
Whether to automatically download all the attachments. Defaults to `false` where all the downloads are canceled.
proxy : Optional[{"server": str, "bypass": Optional[str], "username": Optional[str], "password": Optional[str]}]
Network proxy settings to use with this context. Note that browser needs to be launched with the global proxy for this option to work. If all contexts override the proxy, global proxy will be never used and can be any string, for example `launch({ proxy: { server: 'per-proxy' } })`.
Network proxy settings to use with this context. Note that browser needs to be launched with the global proxy for this option to work. If all contexts override the proxy, global proxy will be never used and can be any string, for example `launch({ proxy: { server: 'per-context' } })`.
videosPath : Optional[str]
Enables video recording for all pages to `videosPath` folder. If not specified, videos are not recorded. Make sure to await `browserContext.close` for videos to be saved.
videoSize : Optional[{"width": int, "height": int}]
Expand Down Expand Up @@ -5985,7 +5985,7 @@ async def newPage(
acceptDownloads : Optional[bool]
Whether to automatically download all the attachments. Defaults to `false` where all the downloads are canceled.
proxy : Optional[{"server": str, "bypass": Optional[str], "username": Optional[str], "password": Optional[str]}]
Network proxy settings to use with this context. Note that browser needs to be launched with the global proxy for this option to work. If all contexts override the proxy, global proxy will be never used and can be any string, for example `launch({ proxy: { server: 'per-proxy' } })`.
Network proxy settings to use with this context. Note that browser needs to be launched with the global proxy for this option to work. If all contexts override the proxy, global proxy will be never used and can be any string, for example `launch({ proxy: { server: 'per-context' } })`.
videosPath : Optional[str]
Enables video recording for all pages to `videosPath` folder. If not specified, videos are not recorded. Make sure to await `page.close` for videos to be saved.
videoSize : Optional[{"width": int, "height": int}]
Expand Down
7 changes: 6 additions & 1 deletion playwright/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
IntSize,
ProxyServer,
RecordHarOptions,
is_safe_close_error,
locals_to_params,
)
from playwright.network import serialize_headers
Expand Down Expand Up @@ -150,7 +151,11 @@ async def close(self) -> None:
if self._is_closed_or_closing:
return
self._is_closed_or_closing = True
await self._channel.send("close")
try:
await self._channel.send("close")
except Exception as e:
if not is_safe_close_error(e):
raise e

@property
def version(self) -> str:
Expand Down
7 changes: 6 additions & 1 deletion playwright/browser_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
TimeoutSettings,
URLMatch,
URLMatcher,
is_safe_close_error,
locals_to_params,
)
from playwright.network import Request, Route, serialize_headers
Expand Down Expand Up @@ -228,7 +229,11 @@ async def close(self) -> None:
if self._is_closed_or_closing:
return
self._is_closed_or_closing = True
await self._channel.send("close")
try:
await self._channel.send("close")
except Exception as e:
if not is_safe_close_error(e):
raise e

def expect_event(
self,
Expand Down
7 changes: 7 additions & 0 deletions playwright/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,13 @@ def __init__(self, matcher: URLMatcher, handler: RouteHandler):
self.handler = handler


def is_safe_close_error(error: Exception) -> bool:
message = str(error)
return message.endswith("Browser has been closed") or message.endswith(
"Target page, context or browser has been closed"
)


def not_installed_error(message: str) -> Exception:
return Exception(
f"""
Expand Down
11 changes: 8 additions & 3 deletions playwright/page.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
URLMatcher,
Viewport,
is_function_body,
is_safe_close_error,
locals_to_params,
parse_error,
serialize_error,
Expand Down Expand Up @@ -622,9 +623,13 @@ async def title(self) -> str:
return await self._main_frame.title()

async def close(self, runBeforeUnload: bool = None) -> None:
await self._channel.send("close", locals_to_params(locals()))
if self._owned_context:
await self._owned_context.close()
try:
await self._channel.send("close", locals_to_params(locals()))
if self._owned_context:
await self._owned_context.close()
except Exception as e:
if not is_safe_close_error(e):
raise e

def isClosed(self) -> bool:
return self._is_closed
Expand Down
4 changes: 2 additions & 2 deletions playwright/sync_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6116,7 +6116,7 @@ def newContext(
acceptDownloads : Optional[bool]
Whether to automatically download all the attachments. Defaults to `false` where all the downloads are canceled.
proxy : Optional[{"server": str, "bypass": Optional[str], "username": Optional[str], "password": Optional[str]}]
Network proxy settings to use with this context. Note that browser needs to be launched with the global proxy for this option to work. If all contexts override the proxy, global proxy will be never used and can be any string, for example `launch({ proxy: { server: 'per-proxy' } })`.
Network proxy settings to use with this context. Note that browser needs to be launched with the global proxy for this option to work. If all contexts override the proxy, global proxy will be never used and can be any string, for example `launch({ proxy: { server: 'per-context' } })`.
videosPath : Optional[str]
Enables video recording for all pages to `videosPath` folder. If not specified, videos are not recorded. Make sure to await `browserContext.close` for videos to be saved.
videoSize : Optional[{"width": int, "height": int}]
Expand Down Expand Up @@ -6223,7 +6223,7 @@ def newPage(
acceptDownloads : Optional[bool]
Whether to automatically download all the attachments. Defaults to `false` where all the downloads are canceled.
proxy : Optional[{"server": str, "bypass": Optional[str], "username": Optional[str], "password": Optional[str]}]
Network proxy settings to use with this context. Note that browser needs to be launched with the global proxy for this option to work. If all contexts override the proxy, global proxy will be never used and can be any string, for example `launch({ proxy: { server: 'per-proxy' } })`.
Network proxy settings to use with this context. Note that browser needs to be launched with the global proxy for this option to work. If all contexts override the proxy, global proxy will be never used and can be any string, for example `launch({ proxy: { server: 'per-context' } })`.
videosPath : Optional[str]
Enables video recording for all pages to `videosPath` folder. If not specified, videos are not recorded. Make sure to await `page.close` for videos to be saved.
videoSize : Optional[{"width": int, "height": int}]
Expand Down
18 changes: 10 additions & 8 deletions scripts/documentation_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,15 @@ def print_entry(
self.printed_entries.append(f"ElementHandle.{method_name}")
clazz = self.api[class_name]
super_clazz = self.api.get(clazz.get("extends"))
method = clazz["members"].get(method_name) or super_clazz["members"].get(
method_name
method = (
clazz["methods"].get(method_name)
or clazz["properties"].get(method_name)
or super_clazz["methods"].get(method_name)
)
fqname = f"{class_name}.{method_name}"
indent = " " * 8
print(f'{indent}"""{class_name}.{original_method_name}')
if method["comment"]:
if method.get("comment"):
print(f"{indent}{self.beautify_method_comment(method['comment'], indent)}")
signature_no_return = {**signature} if signature else None
if signature_no_return and "return" in signature_no_return:
Expand Down Expand Up @@ -134,7 +136,7 @@ def print_entry(
code_type = self.serialize_python_type(value)

print(f"{indent}{original_name} : {code_type}")
if doc_value["comment"]:
if doc_value.get("comment"):
print(
f"{indent} {self.indent_paragraph(doc_value['comment'], f'{indent} ')}"
)
Expand All @@ -156,7 +158,7 @@ def print_entry(
print(" Returns")
print(" -------")
print(f" {self.serialize_python_type(value)}")
if method["returnComment"]:
if method.get("returnComment"):
print(
f" {self.indent_paragraph(method['returnComment'], ' ')}"
)
Expand Down Expand Up @@ -393,9 +395,9 @@ def print_remainder(self) -> None:
class_name = re.sub(r"Chromium(.*)", r"\1", class_name)
class_name = re.sub(r"WebKit(.*)", r"\1", class_name)
class_name = re.sub(r"Firefox(.*)", r"\1", class_name)
for [method_name, method] in value["members"].items():
if method["kind"] == "event":
continue
for [method_name, method] in list(value["methods"].items()) + list(
value["properties"].items()
):
entry = f"{class_name}.{method_name}"
if entry not in self.printed_entries:
self.errors.add(f"Method not implemented: {entry}")
Expand Down
2 changes: 2 additions & 0 deletions scripts/expected_api_mismatch.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Method not implemented: Download.createReadStream
Method not implemented: Logger.isEnabled
Method not implemented: Logger.log
Method not implemented: Page.coverage
Method not implemented: WebSocket.isClosed
Method not implemented: WebSocket.waitForEvent

# Parameter overloads
Parameter not documented: BrowserContext.waitForEvent(predicate=)
Expand Down
2 changes: 1 addition & 1 deletion tests/async/test_cdp_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ async def test_should_be_able_to_detach_session(page):
await client.send(
"Runtime.evaluate", {"expression": "3 + 1", "returnByValue": True}
)
assert "Target browser or context has been closed" in exc_info.value.message
assert "Target page, context or browser has been closed" in exc_info.value.message


@pytest.mark.only_browser("chromium")
Expand Down