Skip to content

Commit

Permalink
chore(roll): roll Playwright to v1.46 (#2499)
Browse files Browse the repository at this point in the history
  • Loading branch information
mxschmitt authored Jul 31, 2024
1 parent c13cd03 commit 6565810
Show file tree
Hide file tree
Showing 22 changed files with 1,174 additions and 364 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ Playwright is a Python library to automate [Chromium](https://www.chromium.org/H

| | Linux | macOS | Windows |
| :--- | :---: | :---: | :---: |
| Chromium <!-- GEN:chromium-version -->127.0.6533.17<!-- GEN:stop --> ||||
| WebKit <!-- GEN:webkit-version -->17.4<!-- GEN:stop --> ||||
| Firefox <!-- GEN:firefox-version -->127.0<!-- GEN:stop --> ||||
| Chromium <!-- GEN:chromium-version -->128.0.6613.7<!-- GEN:stop --> ||||
| WebKit <!-- GEN:webkit-version -->18.0<!-- GEN:stop --> ||||
| Firefox <!-- GEN:firefox-version -->128.0<!-- GEN:stop --> ||||

## Documentation

Expand Down
9 changes: 9 additions & 0 deletions playwright/_impl/_api_structures.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from pathlib import Path
from typing import Any, Dict, List, Literal, Optional, Sequence, TypedDict, Union

# These are the structures that we like keeping in a JSON form for their potential
Expand Down Expand Up @@ -100,6 +101,14 @@ class StorageState(TypedDict, total=False):
origins: List[OriginState]


class ClientCertificate(TypedDict, total=False):
origin: str
certPath: Optional[Union[str, Path]]
keyPath: Optional[Union[str, Path]]
pfxPath: Optional[Union[str, Path]]
passphrase: Optional[str]


class ResourceTiming(TypedDict):
startTime: float
domainLookupStart: float
Expand Down
10 changes: 9 additions & 1 deletion playwright/_impl/_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from typing import TYPE_CHECKING, Dict, List, Optional, Pattern, Sequence, Union, cast

from playwright._impl._api_structures import (
ClientCertificate,
Geolocation,
HttpCredentials,
ProxySettings,
Expand All @@ -41,7 +42,7 @@
make_dirs_for_file,
prepare_record_har_options,
)
from playwright._impl._network import serialize_headers
from playwright._impl._network import serialize_headers, to_client_certificates_protocol
from playwright._impl._page import Page

if TYPE_CHECKING: # pragma: no cover
Expand Down Expand Up @@ -120,6 +121,7 @@ async def new_context(
recordHarUrlFilter: Union[Pattern[str], str] = None,
recordHarMode: HarMode = None,
recordHarContent: HarContentPolicy = None,
clientCertificates: List[ClientCertificate] = None,
) -> BrowserContext:
params = locals_to_params(locals())
await prepare_browser_context_params(params)
Expand Down Expand Up @@ -165,6 +167,7 @@ async def new_page(
recordHarUrlFilter: Union[Pattern[str], str] = None,
recordHarMode: HarMode = None,
recordHarContent: HarContentPolicy = None,
clientCertificates: List[ClientCertificate] = None,
) -> Page:
params = locals_to_params(locals())

Expand Down Expand Up @@ -253,3 +256,8 @@ async def prepare_browser_context_params(params: Dict) -> None:
params["forcedColors"] = "no-override"
if "acceptDownloads" in params:
params["acceptDownloads"] = "accept" if params["acceptDownloads"] else "deny"

if "clientCertificates" in params:
params["clientCertificates"] = await to_client_certificates_protocol(
params["clientCertificates"]
)
4 changes: 3 additions & 1 deletion playwright/_impl/_browser_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
import asyncio
import pathlib
from pathlib import Path
from typing import TYPE_CHECKING, Dict, Optional, Pattern, Sequence, Union, cast
from typing import TYPE_CHECKING, Dict, List, Optional, Pattern, Sequence, Union, cast

from playwright._impl._api_structures import (
ClientCertificate,
Geolocation,
HttpCredentials,
ProxySettings,
Expand Down Expand Up @@ -147,6 +148,7 @@ async def launch_persistent_context(
recordHarUrlFilter: Union[Pattern[str], str] = None,
recordHarMode: HarMode = None,
recordHarContent: HarContentPolicy = None,
clientCertificates: List[ClientCertificate] = None,
) -> BrowserContext:
userDataDir = str(Path(userDataDir)) if userDataDir else ""
params = locals_to_params(locals())
Expand Down
26 changes: 25 additions & 1 deletion playwright/_impl/_fetch.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import playwright._impl._network as network
from playwright._impl._api_structures import (
ClientCertificate,
FilePayload,
FormField,
Headers,
Expand All @@ -42,7 +43,7 @@
object_to_array,
to_impl,
)
from playwright._impl._network import serialize_headers
from playwright._impl._network import serialize_headers, to_client_certificates_protocol
from playwright._impl._tracing import Tracing

if typing.TYPE_CHECKING:
Expand Down Expand Up @@ -71,6 +72,7 @@ async def new_context(
userAgent: str = None,
timeout: float = None,
storageState: Union[StorageState, str, Path] = None,
clientCertificates: List[ClientCertificate] = None,
) -> "APIRequestContext":
params = locals_to_params(locals())
if "storageState" in params:
Expand All @@ -81,6 +83,9 @@ async def new_context(
)
if "extraHTTPHeaders" in params:
params["extraHTTPHeaders"] = serialize_headers(params["extraHTTPHeaders"])
params["clientCertificates"] = await to_client_certificates_protocol(
params.get("clientCertificates")
)
context = cast(
APIRequestContext,
from_channel(await self.playwright._channel.send("newRequest", params)),
Expand Down Expand Up @@ -118,6 +123,7 @@ async def delete(
failOnStatusCode: bool = None,
ignoreHTTPSErrors: bool = None,
maxRedirects: int = None,
maxRetries: int = None,
) -> "APIResponse":
return await self.fetch(
url,
Expand All @@ -131,6 +137,7 @@ async def delete(
failOnStatusCode=failOnStatusCode,
ignoreHTTPSErrors=ignoreHTTPSErrors,
maxRedirects=maxRedirects,
maxRetries=maxRetries,
)

async def head(
Expand All @@ -145,6 +152,7 @@ async def head(
failOnStatusCode: bool = None,
ignoreHTTPSErrors: bool = None,
maxRedirects: int = None,
maxRetries: int = None,
) -> "APIResponse":
return await self.fetch(
url,
Expand All @@ -158,6 +166,7 @@ async def head(
failOnStatusCode=failOnStatusCode,
ignoreHTTPSErrors=ignoreHTTPSErrors,
maxRedirects=maxRedirects,
maxRetries=maxRetries,
)

async def get(
Expand All @@ -172,6 +181,7 @@ async def get(
failOnStatusCode: bool = None,
ignoreHTTPSErrors: bool = None,
maxRedirects: int = None,
maxRetries: int = None,
) -> "APIResponse":
return await self.fetch(
url,
Expand All @@ -185,6 +195,7 @@ async def get(
failOnStatusCode=failOnStatusCode,
ignoreHTTPSErrors=ignoreHTTPSErrors,
maxRedirects=maxRedirects,
maxRetries=maxRetries,
)

async def patch(
Expand All @@ -199,6 +210,7 @@ async def patch(
failOnStatusCode: bool = None,
ignoreHTTPSErrors: bool = None,
maxRedirects: int = None,
maxRetries: int = None,
) -> "APIResponse":
return await self.fetch(
url,
Expand All @@ -212,6 +224,7 @@ async def patch(
failOnStatusCode=failOnStatusCode,
ignoreHTTPSErrors=ignoreHTTPSErrors,
maxRedirects=maxRedirects,
maxRetries=maxRetries,
)

async def put(
Expand All @@ -226,6 +239,7 @@ async def put(
failOnStatusCode: bool = None,
ignoreHTTPSErrors: bool = None,
maxRedirects: int = None,
maxRetries: int = None,
) -> "APIResponse":
return await self.fetch(
url,
Expand All @@ -239,6 +253,7 @@ async def put(
failOnStatusCode=failOnStatusCode,
ignoreHTTPSErrors=ignoreHTTPSErrors,
maxRedirects=maxRedirects,
maxRetries=maxRetries,
)

async def post(
Expand All @@ -253,6 +268,7 @@ async def post(
failOnStatusCode: bool = None,
ignoreHTTPSErrors: bool = None,
maxRedirects: int = None,
maxRetries: int = None,
) -> "APIResponse":
return await self.fetch(
url,
Expand All @@ -266,6 +282,7 @@ async def post(
failOnStatusCode=failOnStatusCode,
ignoreHTTPSErrors=ignoreHTTPSErrors,
maxRedirects=maxRedirects,
maxRetries=maxRetries,
)

async def fetch(
Expand All @@ -281,6 +298,7 @@ async def fetch(
failOnStatusCode: bool = None,
ignoreHTTPSErrors: bool = None,
maxRedirects: int = None,
maxRetries: int = None,
) -> "APIResponse":
url = urlOrRequest if isinstance(urlOrRequest, str) else None
request = (
Expand All @@ -304,6 +322,7 @@ async def fetch(
failOnStatusCode,
ignoreHTTPSErrors,
maxRedirects,
maxRetries,
)

async def _inner_fetch(
Expand All @@ -320,6 +339,7 @@ async def _inner_fetch(
failOnStatusCode: bool = None,
ignoreHTTPSErrors: bool = None,
maxRedirects: int = None,
maxRetries: int = None,
) -> "APIResponse":
if self._close_reason:
raise TargetClosedError(self._close_reason)
Expand All @@ -329,6 +349,9 @@ async def _inner_fetch(
assert (
maxRedirects is None or maxRedirects >= 0
), "'max_redirects' must be greater than or equal to '0'"
assert (
maxRetries is None or maxRetries >= 0
), "'max_retries' must be greater than or equal to '0'"
url = url or (request.url if request else url)
method = method or (request.method if request else "GET")
# Cannot call allHeaders() here as the request may be paused inside route handler.
Expand Down Expand Up @@ -392,6 +415,7 @@ async def _inner_fetch(
"failOnStatusCode": failOnStatusCode,
"ignoreHTTPSErrors": ignoreHTTPSErrors,
"maxRedirects": maxRedirects,
"maxRetries": maxRetries,
},
)
return APIResponse(self, response)
Expand Down
23 changes: 22 additions & 1 deletion playwright/_impl/_js_handle.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@
import collections.abc
import datetime
import math
import traceback
from pathlib import Path
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
from urllib.parse import ParseResult, urlparse, urlunparse

from playwright._impl._connection import Channel, ChannelOwner, from_channel
from playwright._impl._errors import is_target_closed_error
from playwright._impl._errors import Error, is_target_closed_error
from playwright._impl._map import Map

if TYPE_CHECKING: # pragma: no cover
Expand Down Expand Up @@ -140,6 +141,20 @@ def serialize_value(
value.astimezone(datetime.timezone.utc), "%Y-%m-%dT%H:%M:%S.%fZ"
)
}
if isinstance(value, Exception):
return {
"e": {
"m": str(value),
"n": (value.name or "")
if isinstance(value, Error)
else value.__class__.__name__,
"s": (value.stack or "")
if isinstance(value, Error)
else "".join(
traceback.format_exception(type(value), value=value, tb=None)
),
}
}
if isinstance(value, bool):
return {"b": value}
if isinstance(value, (int, float)):
Expand Down Expand Up @@ -207,6 +222,12 @@ def parse_value(value: Any, refs: Optional[Dict[int, Any]] = None) -> Any:
if "bi" in value:
return int(value["bi"])

if "e" in value:
error = Error(value["e"]["m"])
error._name = value["e"]["n"]
error._stack = value["e"]["s"]
return error

if "a" in value:
a: List = []
refs[value["id"]] = a
Expand Down
33 changes: 32 additions & 1 deletion playwright/_impl/_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from urllib import parse

from playwright._impl._api_structures import (
ClientCertificate,
Headers,
HeadersArray,
RemoteAddr,
Expand All @@ -50,7 +51,7 @@
)
from playwright._impl._errors import Error
from playwright._impl._event_context_manager import EventContextManagerImpl
from playwright._impl._helper import locals_to_params
from playwright._impl._helper import async_readfile, locals_to_params
from playwright._impl._waiter import Waiter

if TYPE_CHECKING: # pragma: no cover
Expand Down Expand Up @@ -83,6 +84,34 @@ def serialize_headers(headers: Dict[str, str]) -> HeadersArray:
]


async def to_client_certificates_protocol(
clientCertificates: Optional[List[ClientCertificate]],
) -> Optional[List[Dict[str, str]]]:
if not clientCertificates:
return None
out = []
for clientCertificate in clientCertificates:
out_record = {
"origin": clientCertificate["origin"],
}
if passphrase := clientCertificate.get("passphrase"):
out_record["passphrase"] = passphrase
if pfx_path := clientCertificate.get("pfxPath"):
out_record["pfx"] = base64.b64encode(
await async_readfile(pfx_path)
).decode()
if cert_path := clientCertificate.get("certPath"):
out_record["cert"] = base64.b64encode(
await async_readfile(cert_path)
).decode()
if key_path := clientCertificate.get("keyPath"):
out_record["key"] = base64.b64encode(
await async_readfile(key_path)
).decode()
out.append(out_record)
return out


class Request(ChannelOwner):
def __init__(
self, parent: ChannelOwner, type: str, guid: str, initializer: Dict
Expand Down Expand Up @@ -410,6 +439,7 @@ async def fetch(
headers: Dict[str, str] = None,
postData: Union[Any, str, bytes] = None,
maxRedirects: int = None,
maxRetries: int = None,
timeout: float = None,
) -> "APIResponse":
return await self._connection.wrap_api_call(
Expand All @@ -420,6 +450,7 @@ async def fetch(
headers,
postData,
maxRedirects=maxRedirects,
maxRetries=maxRetries,
timeout=timeout,
)
)
Expand Down
Loading

0 comments on commit 6565810

Please sign in to comment.