Skip to content

Commit d332719

Browse files
authored
chore(roll): roll Playwright to 1.40.0 (#2170)
1 parent 9271ab9 commit d332719

17 files changed

+288
-126
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ Playwright is a Python library to automate [Chromium](https://www.chromium.org/H
44

55
| | Linux | macOS | Windows |
66
| :--- | :---: | :---: | :---: |
7-
| Chromium <!-- GEN:chromium-version -->119.0.6045.21<!-- GEN:stop --> ||||
7+
| Chromium <!-- GEN:chromium-version -->120.0.6099.28<!-- GEN:stop --> ||||
88
| WebKit <!-- GEN:webkit-version -->17.4<!-- GEN:stop --> ||||
9-
| Firefox <!-- GEN:firefox-version -->118.0.1<!-- GEN:stop --> ||||
9+
| Firefox <!-- GEN:firefox-version -->119.0<!-- GEN:stop --> ||||
1010

1111
## Documentation
1212

playwright/_impl/_assertions.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,11 @@ async def to_have_attribute(
215215
self,
216216
name: str,
217217
value: Union[str, Pattern[str]],
218+
ignore_case: bool = None,
218219
timeout: float = None,
219220
) -> None:
220221
__tracebackhide__ = True
221-
expected_text = to_expected_text_values([value])
222+
expected_text = to_expected_text_values([value], ignore_case=ignore_case)
222223
await self._expect_impl(
223224
"to.have.attribute.value",
224225
FrameExpectOptions(
@@ -235,7 +236,7 @@ async def not_to_have_attribute(
235236
timeout: float = None,
236237
) -> None:
237238
__tracebackhide__ = True
238-
await self._not.to_have_attribute(name, value, timeout)
239+
await self._not.to_have_attribute(name, value, timeout=timeout)
239240

240241
async def to_have_class(
241242
self,

playwright/_impl/_browser_type.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ async def launch_persistent_context(
137137
acceptDownloads: bool = None,
138138
tracesDir: Union[pathlib.Path, str] = None,
139139
chromiumSandbox: bool = None,
140+
firefoxUserPrefs: Dict[str, Union[str, float, bool]] = None,
140141
recordHarPath: Union[Path, str] = None,
141142
recordHarOmitContent: bool = None,
142143
recordVideoDir: Union[Path, str] = None,

playwright/_impl/_element_handle.py

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@
1818
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Union, cast
1919

2020
from playwright._impl._api_structures import FilePayload, FloatRect, Position
21-
from playwright._impl._connection import ChannelOwner, from_nullable_channel
21+
from playwright._impl._connection import (
22+
ChannelOwner,
23+
filter_none,
24+
from_nullable_channel,
25+
)
2226
from playwright._impl._helper import (
2327
Error,
2428
KeyboardModifier,
@@ -191,20 +195,17 @@ async def set_input_files(
191195
timeout: float = None,
192196
noWaitAfter: bool = None,
193197
) -> None:
194-
params = locals_to_params(locals())
195198
frame = await self.owner_frame()
196199
if not frame:
197200
raise Error("Cannot set input files to detached element")
198201
converted = await convert_input_files(files, frame.page.context)
199-
if converted["files"] is not None:
200-
await self._channel.send(
201-
"setInputFiles", {**params, "files": converted["files"]}
202-
)
203-
else:
204-
await self._channel.send(
205-
"setInputFilePaths",
206-
locals_to_params({**params, **converted, "files": None}),
207-
)
202+
await self._channel.send(
203+
"setInputFiles",
204+
{
205+
**filter_none({"timeout": timeout, "noWaitAfter": noWaitAfter}),
206+
**converted,
207+
},
208+
)
208209

209210
async def focus(self) -> None:
210211
await self._channel.send("focus")
@@ -407,14 +408,4 @@ def convert_select_option_values(
407408
element = [element]
408409
elements = list(map(lambda e: e._channel, element))
409410

410-
return filter_out_none(dict(options=options, elements=elements))
411-
412-
413-
def filter_out_none(args: Dict) -> Any:
414-
copy = {}
415-
for key in args:
416-
if key == "self":
417-
continue
418-
if args[key] is not None:
419-
copy[key] = args[key]
420-
return copy
411+
return filter_none(dict(options=options, elements=elements))

playwright/_impl/_frame.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from playwright._impl._api_structures import AriaRole, FilePayload, Position
2323
from playwright._impl._connection import (
2424
ChannelOwner,
25+
filter_none,
2526
from_channel,
2627
from_nullable_channel,
2728
)
@@ -689,17 +690,21 @@ async def set_input_files(
689690
timeout: float = None,
690691
noWaitAfter: bool = None,
691692
) -> None:
692-
params = locals_to_params(locals())
693693
converted = await convert_input_files(files, self.page.context)
694-
if converted["files"] is not None:
695-
await self._channel.send(
696-
"setInputFiles", {**params, "files": converted["files"]}
697-
)
698-
else:
699-
await self._channel.send(
700-
"setInputFilePaths",
701-
locals_to_params({**params, **converted, "files": None}),
702-
)
694+
await self._channel.send(
695+
"setInputFiles",
696+
{
697+
**filter_none(
698+
{
699+
"selector": selector,
700+
"strict": strict,
701+
"timeout": timeout,
702+
"noWaitAfter": noWaitAfter,
703+
}
704+
),
705+
**converted,
706+
},
707+
)
703708

704709
async def type(
705710
self,

playwright/_impl/_set_input_files_helpers.py

Lines changed: 41 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@
1515
import os
1616
import sys
1717
from pathlib import Path
18-
from typing import TYPE_CHECKING, List, Optional, Union
18+
from typing import TYPE_CHECKING, Dict, List, Optional, Union, cast
1919

2020
if sys.version_info >= (3, 8): # pragma: no cover
2121
from typing import TypedDict
2222
else: # pragma: no cover
2323
from typing_extensions import TypedDict
2424

2525
from playwright._impl._connection import Channel, from_channel
26-
from playwright._impl._helper import Error, async_readfile
26+
from playwright._impl._helper import Error
2727
from playwright._impl._writable_stream import WritableStream
2828

2929
if TYPE_CHECKING: # pragma: no cover
@@ -34,81 +34,61 @@
3434
SIZE_LIMIT_IN_BYTES = 50 * 1024 * 1024
3535

3636

37-
class InputFilesList(TypedDict):
37+
class InputFilesList(TypedDict, total=False):
3838
streams: Optional[List[Channel]]
3939
localPaths: Optional[List[str]]
40-
files: Optional[List[FilePayload]]
40+
payloads: Optional[List[Dict[str, Union[str, bytes]]]]
4141

4242

4343
async def convert_input_files(
4444
files: Union[str, Path, FilePayload, List[Union[str, Path]], List[FilePayload]],
4545
context: "BrowserContext",
4646
) -> InputFilesList:
47-
file_list = files if isinstance(files, list) else [files]
47+
items = files if isinstance(files, list) else [files]
4848

49-
total_buffer_size_exceeds_limit = (
50-
sum(
51-
[
52-
len(f.get("buffer", ""))
53-
for f in file_list
54-
if not isinstance(f, (str, Path))
55-
]
56-
)
57-
> SIZE_LIMIT_IN_BYTES
58-
)
59-
if total_buffer_size_exceeds_limit:
60-
raise Error(
61-
"Cannot set buffer larger than 50Mb, please write it to a file and pass its path instead."
62-
)
63-
64-
total_file_size_exceeds_limit = (
65-
sum([os.stat(f).st_size for f in file_list if isinstance(f, (str, Path))])
66-
> SIZE_LIMIT_IN_BYTES
67-
)
68-
if total_file_size_exceeds_limit:
49+
if any([isinstance(item, (str, Path)) for item in items]):
50+
if not all([isinstance(item, (str, Path)) for item in items]):
51+
raise Error("File paths cannot be mixed with buffers")
6952
if context._channel._connection.is_remote:
7053
streams = []
71-
for file in file_list:
72-
assert isinstance(file, (str, Path))
54+
for item in items:
55+
assert isinstance(item, (str, Path))
56+
last_modified_ms = int(os.path.getmtime(item) * 1000)
7357
stream: WritableStream = from_channel(
7458
await context._channel.send(
75-
"createTempFile", {"name": os.path.basename(file)}
59+
"createTempFile",
60+
{
61+
"name": os.path.basename(item),
62+
"lastModifiedMs": last_modified_ms,
63+
},
7664
)
7765
)
78-
await stream.copy(file)
66+
await stream.copy(item)
7967
streams.append(stream._channel)
80-
return InputFilesList(streams=streams, localPaths=None, files=None)
81-
local_paths = []
82-
for p in file_list:
83-
assert isinstance(p, (str, Path))
84-
local_paths.append(str(Path(p).absolute().resolve()))
85-
return InputFilesList(streams=None, localPaths=local_paths, files=None)
68+
return InputFilesList(streams=streams)
69+
return InputFilesList(
70+
localPaths=[
71+
str(Path(cast(Union[str, Path], item)).absolute().resolve())
72+
for item in items
73+
]
74+
)
8675

87-
return InputFilesList(
88-
streams=None, localPaths=None, files=await _normalize_file_payloads(files)
76+
file_payload_exceeds_size_limit = (
77+
sum([len(f.get("buffer", "")) for f in items if not isinstance(f, (str, Path))])
78+
> SIZE_LIMIT_IN_BYTES
8979
)
80+
if file_payload_exceeds_size_limit:
81+
raise Error(
82+
"Cannot set buffer larger than 50Mb, please write it to a file and pass its path instead."
83+
)
9084

91-
92-
async def _normalize_file_payloads(
93-
files: Union[str, Path, FilePayload, List[Union[str, Path]], List[FilePayload]]
94-
) -> List:
95-
file_list = files if isinstance(files, list) else [files]
96-
file_payloads: List = []
97-
for item in file_list:
98-
if isinstance(item, (str, Path)):
99-
file_payloads.append(
100-
{
101-
"name": os.path.basename(item),
102-
"buffer": base64.b64encode(await async_readfile(item)).decode(),
103-
}
104-
)
105-
else:
106-
file_payloads.append(
107-
{
108-
"name": item["name"],
109-
"mimeType": item["mimeType"],
110-
"buffer": base64.b64encode(item["buffer"]).decode(),
111-
}
112-
)
113-
114-
return file_payloads
85+
return InputFilesList(
86+
payloads=[
87+
{
88+
"name": item["name"],
89+
"mimeType": item["mimeType"],
90+
"buffer": base64.b64encode(item["buffer"]).decode(),
91+
}
92+
for item in cast(List[FilePayload], items)
93+
]
94+
)

0 commit comments

Comments
 (0)