diff --git a/playwright/async_api.py b/playwright/async_api.py index c6a7bb97a..d9741c913 100644 --- a/playwright/async_api.py +++ b/playwright/async_api.py @@ -1186,7 +1186,7 @@ async def setInputFiles( Parameters ---------- - 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]}]] + files : Union[str, pathlib.Path, {"name": str, "mimeType": str, "buffer": bytes}, List[str], List[pathlib.Path], List[{"name": str, "mimeType": str, "buffer": bytes}]] timeout : Optional[int] 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. noWaitAfter : Optional[bool] @@ -1662,7 +1662,7 @@ async def setFiles( Parameters ---------- - files : Union[str, {"name": str, "mimeType": str, "buffer": Union[bytes, str]}, List[str], List[{"name": str, "mimeType": str, "buffer": Union[bytes, str]}]] + files : Union[str, {"name": str, "mimeType": str, "buffer": bytes}, List[str], List[{"name": str, "mimeType": str, "buffer": bytes}]] timeout : Optional[int] 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. noWaitAfter : Optional[bool] @@ -2588,7 +2588,7 @@ async def setInputFiles( ---------- selector : str 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. - 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]}]] + files : Union[str, pathlib.Path, {"name": str, "mimeType": str, "buffer": bytes}, List[str], List[pathlib.Path], List[{"name": str, "mimeType": str, "buffer": bytes}]] timeout : Optional[int] 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. noWaitAfter : Optional[bool] @@ -4648,7 +4648,7 @@ async def setInputFiles( ---------- selector : str 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. - files : Union[str, {"name": str, "mimeType": str, "buffer": Union[bytes, str]}, List[str], List[{"name": str, "mimeType": str, "buffer": Union[bytes, str]}]] + files : Union[str, {"name": str, "mimeType": str, "buffer": bytes}, List[str], List[{"name": str, "mimeType": str, "buffer": bytes}]] timeout : Optional[int] 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. noWaitAfter : Optional[bool] diff --git a/playwright/element_handle.py b/playwright/element_handle.py index 681a323f8..b73d62481 100644 --- a/playwright/element_handle.py +++ b/playwright/element_handle.py @@ -27,6 +27,7 @@ MouseButton, MousePosition, SelectOption, + SetFilePayload, locals_to_params, ) from playwright.js_handle import ( @@ -291,22 +292,27 @@ def convert_select_option_values(arg: ValuesToSelect) -> Any: def normalize_file_payloads( files: Union[str, Path, FilePayload, List[str], List[Path], List[FilePayload]] -) -> List[FilePayload]: +) -> List[SetFilePayload]: file_list = files if isinstance(files, list) else [files] - file_payloads: List[FilePayload] = [] + file_payloads: List[SetFilePayload] = [] for item in file_list: if isinstance(item, str) or isinstance(item, Path): with open(item, mode="rb") as fd: - file: FilePayload = { - "name": os.path.basename(item), - "mimeType": mimetypes.guess_type(str(Path(item)))[0] - or "application/octet-stream", - "buffer": base64.b64encode(fd.read()).decode(), - } - file_payloads.append(file) + file_payloads.append( + { + "name": os.path.basename(item), + "mimeType": mimetypes.guess_type(str(Path(item)))[0] + or "application/octet-stream", + "buffer": base64.b64encode(fd.read()).decode(), + } + ) else: - if isinstance(item["buffer"], bytes): - item["buffer"] = base64.b64encode(item["buffer"]).decode() - file_payloads.append(item) + file_payloads.append( + { + "name": item["name"], + "mimeType": item["mimeType"], + "buffer": base64.b64encode(item["buffer"]).decode(), + } + ) return file_payloads diff --git a/playwright/helper.py b/playwright/helper.py index a3d46df98..d26d8fe67 100644 --- a/playwright/helper.py +++ b/playwright/helper.py @@ -59,7 +59,13 @@ class MousePosition(TypedDict): class FilePayload(TypedDict): name: str mimeType: str - buffer: Union[bytes, str] + buffer: bytes + + +class SetFilePayload(TypedDict): + name: str + mimeType: str + buffer: str class SelectOption(TypedDict): diff --git a/playwright/sync_api.py b/playwright/sync_api.py index f191f00d2..189e5465d 100644 --- a/playwright/sync_api.py +++ b/playwright/sync_api.py @@ -1224,7 +1224,7 @@ def setInputFiles( Parameters ---------- - 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]}]] + files : Union[str, pathlib.Path, {"name": str, "mimeType": str, "buffer": bytes}, List[str], List[pathlib.Path], List[{"name": str, "mimeType": str, "buffer": bytes}]] timeout : Optional[int] 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. noWaitAfter : Optional[bool] @@ -1718,7 +1718,7 @@ def setFiles( Parameters ---------- - files : Union[str, {"name": str, "mimeType": str, "buffer": Union[bytes, str]}, List[str], List[{"name": str, "mimeType": str, "buffer": Union[bytes, str]}]] + files : Union[str, {"name": str, "mimeType": str, "buffer": bytes}, List[str], List[{"name": str, "mimeType": str, "buffer": bytes}]] timeout : Optional[int] 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. noWaitAfter : Optional[bool] @@ -2683,7 +2683,7 @@ def setInputFiles( ---------- selector : str 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. - 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]}]] + files : Union[str, pathlib.Path, {"name": str, "mimeType": str, "buffer": bytes}, List[str], List[pathlib.Path], List[{"name": str, "mimeType": str, "buffer": bytes}]] timeout : Optional[int] 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. noWaitAfter : Optional[bool] @@ -4835,7 +4835,7 @@ def setInputFiles( ---------- selector : str 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. - files : Union[str, {"name": str, "mimeType": str, "buffer": Union[bytes, str]}, List[str], List[{"name": str, "mimeType": str, "buffer": Union[bytes, str]}]] + files : Union[str, {"name": str, "mimeType": str, "buffer": bytes}, List[str], List[{"name": str, "mimeType": str, "buffer": bytes}]] timeout : Optional[int] 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. noWaitAfter : Optional[bool] diff --git a/scripts/expected_api_mismatch.txt b/scripts/expected_api_mismatch.txt index 1bed1ea0a..8e49efe7f 100644 --- a/scripts/expected_api_mismatch.txt +++ b/scripts/expected_api_mismatch.txt @@ -74,10 +74,10 @@ Parameter not documented: BrowserContext.addInitScript(path=) Parameter not documented: Page.addInitScript(path=) # File payload -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]}]] -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]}]] -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]}]] -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]}]] +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}]] +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}]] +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}]] +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}]] # Select option 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] diff --git a/tests/async/test_click.py b/tests/async/test_click.py index 1895e8034..c5341b6b5 100644 --- a/tests/async/test_click.py +++ b/tests/async/test_click.py @@ -809,13 +809,10 @@ async def test_fail_when_element_detaches_after_animation(page, server): promise = asyncio.create_task(handle.click()) await asyncio.sleep(0) # execute scheduled tasks, but don't await them await page.evaluate("stopButton(true)") - error = None - try: - error = await promise - except Error as e: - error = e + with pytest.raises(Error) as exc_info: + await promise assert await page.evaluate("window.clicked") is None - assert "Element is not attached to the DOM" in error.message + assert "Element is not attached to the DOM" in exc_info.value.message async def test_retry_when_element_detaches_after_animation(page, server): @@ -950,16 +947,12 @@ async def test_click_the_button_when_window_inner_width_is_corrupted(page, serve async def test_timeout_when_click_opens_alert(page, server): - dialog_promise = asyncio.create_task(page.waitForEvent("dialog")) - await asyncio.sleep(0) # execute scheduled tasks, but don't await them await page.setContent('