Skip to content

Commit 6cccab5

Browse files
committed
api: use bytes, not string|bytes for file input buffers
1 parent f565f59 commit 6cccab5

File tree

6 files changed

+60
-25
lines changed

6 files changed

+60
-25
lines changed

playwright/async_api.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,7 +1186,7 @@ async def setInputFiles(
11861186
11871187
Parameters
11881188
----------
1189-
files : Union[str, pathlib.Path, {"name": str, "mimeType": str, "buffer": Union[bytes, str]}, List[str], List[pathlib.Path], List[{"name": str, "mimeType": str, "buffer": Union[bytes, str]}]]
1189+
files : Union[str, pathlib.Path, {"name": str, "mimeType": str, "buffer": bytes}, List[str], List[pathlib.Path], List[{"name": str, "mimeType": str, "buffer": bytes}]]
11901190
timeout : Optional[int]
11911191
Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by using the browserContext.setDefaultTimeout(timeout) or page.setDefaultTimeout(timeout) methods.
11921192
noWaitAfter : Optional[bool]
@@ -1662,7 +1662,7 @@ async def setFiles(
16621662
16631663
Parameters
16641664
----------
1665-
files : Union[str, {"name": str, "mimeType": str, "buffer": Union[bytes, str]}, List[str], List[{"name": str, "mimeType": str, "buffer": Union[bytes, str]}]]
1665+
files : Union[str, {"name": str, "mimeType": str, "buffer": bytes}, List[str], List[{"name": str, "mimeType": str, "buffer": bytes}]]
16661666
timeout : Optional[int]
16671667
Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by using the browserContext.setDefaultTimeout(timeout) or page.setDefaultTimeout(timeout) methods.
16681668
noWaitAfter : Optional[bool]
@@ -2588,7 +2588,7 @@ async def setInputFiles(
25882588
----------
25892589
selector : str
25902590
A selector to search for element to click. If there are multiple elements satisfying the selector, the first will be clicked. See working with selectors for more details.
2591-
files : Union[str, pathlib.Path, {"name": str, "mimeType": str, "buffer": Union[bytes, str]}, List[str], List[pathlib.Path], List[{"name": str, "mimeType": str, "buffer": Union[bytes, str]}]]
2591+
files : Union[str, pathlib.Path, {"name": str, "mimeType": str, "buffer": bytes}, List[str], List[pathlib.Path], List[{"name": str, "mimeType": str, "buffer": bytes}]]
25922592
timeout : Optional[int]
25932593
Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by using the browserContext.setDefaultTimeout(timeout) or page.setDefaultTimeout(timeout) methods.
25942594
noWaitAfter : Optional[bool]
@@ -4648,7 +4648,7 @@ async def setInputFiles(
46484648
----------
46494649
selector : str
46504650
A selector to search for element to click. If there are multiple elements satisfying the selector, the first will be clicked. See working with selectors for more details.
4651-
files : Union[str, {"name": str, "mimeType": str, "buffer": Union[bytes, str]}, List[str], List[{"name": str, "mimeType": str, "buffer": Union[bytes, str]}]]
4651+
files : Union[str, {"name": str, "mimeType": str, "buffer": bytes}, List[str], List[{"name": str, "mimeType": str, "buffer": bytes}]]
46524652
timeout : Optional[int]
46534653
Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by using the browserContext.setDefaultTimeout(timeout) or page.setDefaultTimeout(timeout) methods.
46544654
noWaitAfter : Optional[bool]

playwright/element_handle.py

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
MouseButton,
2828
MousePosition,
2929
SelectOption,
30+
SetFilePayload,
3031
locals_to_params,
3132
)
3233
from playwright.js_handle import (
@@ -291,22 +292,27 @@ def convert_select_option_values(arg: ValuesToSelect) -> Any:
291292

292293
def normalize_file_payloads(
293294
files: Union[str, Path, FilePayload, List[str], List[Path], List[FilePayload]]
294-
) -> List[FilePayload]:
295+
) -> List[SetFilePayload]:
295296
file_list = files if isinstance(files, list) else [files]
296-
file_payloads: List[FilePayload] = []
297+
file_payloads: List[SetFilePayload] = []
297298
for item in file_list:
298299
if isinstance(item, str) or isinstance(item, Path):
299300
with open(item, mode="rb") as fd:
300-
file: FilePayload = {
301-
"name": os.path.basename(item),
302-
"mimeType": mimetypes.guess_type(str(Path(item)))[0]
303-
or "application/octet-stream",
304-
"buffer": base64.b64encode(fd.read()).decode(),
305-
}
306-
file_payloads.append(file)
301+
file_payloads.append(
302+
{
303+
"name": os.path.basename(item),
304+
"mimeType": mimetypes.guess_type(str(Path(item)))[0]
305+
or "application/octet-stream",
306+
"buffer": base64.b64encode(fd.read()).decode(),
307+
}
308+
)
307309
else:
308-
if isinstance(item["buffer"], bytes):
309-
item["buffer"] = base64.b64encode(item["buffer"]).decode()
310-
file_payloads.append(item)
310+
file_payloads.append(
311+
{
312+
"name": item["name"],
313+
"mimeType": item["mimeType"],
314+
"buffer": base64.b64encode(item["buffer"]).decode(),
315+
}
316+
)
311317

312318
return file_payloads

playwright/helper.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,13 @@ class MousePosition(TypedDict):
5959
class FilePayload(TypedDict):
6060
name: str
6161
mimeType: str
62-
buffer: Union[bytes, str]
62+
buffer: bytes
63+
64+
65+
class SetFilePayload(TypedDict):
66+
name: str
67+
mimeType: str
68+
buffer: str
6369

6470

6571
class SelectOption(TypedDict):

playwright/sync_api.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,7 +1224,7 @@ def setInputFiles(
12241224
12251225
Parameters
12261226
----------
1227-
files : Union[str, pathlib.Path, {"name": str, "mimeType": str, "buffer": Union[bytes, str]}, List[str], List[pathlib.Path], List[{"name": str, "mimeType": str, "buffer": Union[bytes, str]}]]
1227+
files : Union[str, pathlib.Path, {"name": str, "mimeType": str, "buffer": bytes}, List[str], List[pathlib.Path], List[{"name": str, "mimeType": str, "buffer": bytes}]]
12281228
timeout : Optional[int]
12291229
Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by using the browserContext.setDefaultTimeout(timeout) or page.setDefaultTimeout(timeout) methods.
12301230
noWaitAfter : Optional[bool]
@@ -1718,7 +1718,7 @@ def setFiles(
17181718
17191719
Parameters
17201720
----------
1721-
files : Union[str, {"name": str, "mimeType": str, "buffer": Union[bytes, str]}, List[str], List[{"name": str, "mimeType": str, "buffer": Union[bytes, str]}]]
1721+
files : Union[str, {"name": str, "mimeType": str, "buffer": bytes}, List[str], List[{"name": str, "mimeType": str, "buffer": bytes}]]
17221722
timeout : Optional[int]
17231723
Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by using the browserContext.setDefaultTimeout(timeout) or page.setDefaultTimeout(timeout) methods.
17241724
noWaitAfter : Optional[bool]
@@ -2683,7 +2683,7 @@ def setInputFiles(
26832683
----------
26842684
selector : str
26852685
A selector to search for element to click. If there are multiple elements satisfying the selector, the first will be clicked. See working with selectors for more details.
2686-
files : Union[str, pathlib.Path, {"name": str, "mimeType": str, "buffer": Union[bytes, str]}, List[str], List[pathlib.Path], List[{"name": str, "mimeType": str, "buffer": Union[bytes, str]}]]
2686+
files : Union[str, pathlib.Path, {"name": str, "mimeType": str, "buffer": bytes}, List[str], List[pathlib.Path], List[{"name": str, "mimeType": str, "buffer": bytes}]]
26872687
timeout : Optional[int]
26882688
Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by using the browserContext.setDefaultTimeout(timeout) or page.setDefaultTimeout(timeout) methods.
26892689
noWaitAfter : Optional[bool]
@@ -4835,7 +4835,7 @@ def setInputFiles(
48354835
----------
48364836
selector : str
48374837
A selector to search for element to click. If there are multiple elements satisfying the selector, the first will be clicked. See working with selectors for more details.
4838-
files : Union[str, {"name": str, "mimeType": str, "buffer": Union[bytes, str]}, List[str], List[{"name": str, "mimeType": str, "buffer": Union[bytes, str]}]]
4838+
files : Union[str, {"name": str, "mimeType": str, "buffer": bytes}, List[str], List[{"name": str, "mimeType": str, "buffer": bytes}]]
48394839
timeout : Optional[int]
48404840
Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by using the browserContext.setDefaultTimeout(timeout) or page.setDefaultTimeout(timeout) methods.
48414841
noWaitAfter : Optional[bool]

scripts/expected_api_mismatch.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,10 @@ Parameter not documented: BrowserContext.addInitScript(path=)
7474
Parameter not documented: Page.addInitScript(path=)
7575

7676
# File payload
77-
Parameter type mismatch in FileChooser.setFiles(files=): documented as Union[str, List[str], Dict, List[Dict]], code has Union[str, {"name": str, "mimeType": str, "buffer": Union[bytes, str]}, List[str], List[{"name": str, "mimeType": str, "buffer": Union[bytes, str]}]]
78-
Parameter type mismatch in Page.setInputFiles(files=): documented as Union[str, List[str], Dict, List[Dict]], code has Union[str, {"name": str, "mimeType": str, "buffer": Union[bytes, str]}, List[str], List[{"name": str, "mimeType": str, "buffer": Union[bytes, str]}]]
79-
Parameter type mismatch in ElementHandle.setInputFiles(files=): documented as Union[str, List[str], Dict, List[Dict]], code has Union[str, pathlib.Path, {"name": str, "mimeType": str, "buffer": Union[bytes, str]}, List[str], List[pathlib.Path], List[{"name": str, "mimeType": str, "buffer": Union[bytes, str]}]]
80-
Parameter type mismatch in Frame.setInputFiles(files=): documented as Union[str, List[str], Dict, List[Dict]], code has Union[str, pathlib.Path, {"name": str, "mimeType": str, "buffer": Union[bytes, str]}, List[str], List[pathlib.Path], List[{"name": str, "mimeType": str, "buffer": Union[bytes, str]}]]
77+
Parameter type mismatch in FileChooser.setFiles(files=): documented as Union[str, List[str], Dict, List[Dict]], code has Union[str, {"name": str, "mimeType": str, "buffer": bytes}, List[str], List[{"name": str, "mimeType": str, "buffer": bytes}]]
78+
Parameter type mismatch in Page.setInputFiles(files=): documented as Union[str, List[str], Dict, List[Dict]], code has Union[str, {"name": str, "mimeType": str, "buffer": bytes}, List[str], List[{"name": str, "mimeType": str, "buffer": bytes}]]
79+
Parameter type mismatch in ElementHandle.setInputFiles(files=): documented as Union[str, List[str], Dict, List[Dict]], code has Union[str, pathlib.Path, {"name": str, "mimeType": str, "buffer": bytes}, List[str], List[pathlib.Path], List[{"name": str, "mimeType": str, "buffer": bytes}]]
80+
Parameter type mismatch in Frame.setInputFiles(files=): documented as Union[str, List[str], Dict, List[Dict]], code has Union[str, pathlib.Path, {"name": str, "mimeType": str, "buffer": bytes}, List[str], List[pathlib.Path], List[{"name": str, "mimeType": str, "buffer": bytes}]]
8181

8282
# Select option
8383
Parameter type mismatch in ElementHandle.selectOption(values=): documented as Union[str, ElementHandle, List[str], Dict, List[ElementHandle], List[Dict], NoneType], code has Union[str, ElementHandle, {"value": Optional[str], "label": Optional[str], "index": Optional[str]}, List[str], List[ElementHandle], List[{"value": Optional[str], "label": Optional[str], "index": Optional[str]}], NoneType]

tests/sync/test_input.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Copyright (c) Microsoft Corporation.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
16+
def test_expect_file_chooser(page, server):
17+
page.setContent("<input type=file></input>")
18+
with page.expect_file_chooser() as fc_info:
19+
page.click('input[type="file"]')
20+
fc = fc_info.value
21+
fc.setFiles(
22+
{"name": "test.txt", "mimeType": "text/plain", "buffer": b"Hello World"}
23+
)

0 commit comments

Comments
 (0)