From f4b4635d8720a45966d10457349a0e3fdea088e0 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Wed, 11 Oct 2023 14:43:20 +0200 Subject: [PATCH] chore(roll): roll Playwright to 1.39.0-alpha-oct-10-2023 --- README.md | 12 +- playwright/_impl/_assertions.py | 2 +- playwright/_impl/_browser_context.py | 5 +- playwright/_impl/_connection.py | 6 +- playwright/_impl/_console_message.py | 30 +++-- playwright/_impl/_js_handle.py | 10 -- playwright/_impl/_local_utils.py | 15 +++ playwright/_impl/_object_factory.py | 3 - playwright/_impl/_playwright.py | 19 +--- playwright/async_api/_generated.py | 157 +++++++++++++++++++-------- playwright/sync_api/_generated.py | 157 +++++++++++++++++++-------- setup.py | 2 +- tests/async/test_evaluate.py | 8 -- 13 files changed, 263 insertions(+), 163 deletions(-) diff --git a/README.md b/README.md index eaf9a473a..c8f53740a 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ -# 🎭 [Playwright](https://playwright.dev) for Python [![PyPI version](https://badge.fury.io/py/playwright.svg)](https://pypi.python.org/pypi/playwright/) [![Anaconda version](https://img.shields.io/conda/v/microsoft/playwright)](https://anaconda.org/Microsoft/playwright) [![Join Slack](https://img.shields.io/badge/join-slack-infomational)](https://aka.ms/playwright-slack) +# 🎭 [Playwright](https://playwright.dev) for Python [![PyPI version](https://badge.fury.io/py/playwright.svg)](https://pypi.python.org/pypi/playwright/) [![Anaconda version](https://img.shields.io/conda/v/microsoft/playwright)](https://anaconda.org/Microsoft/playwright) [![Join Discord](https://img.shields.io/badge/join-discord-infomational)](https://aka.ms/playwright/discord) Playwright is a Python library to automate [Chromium](https://www.chromium.org/Home), [Firefox](https://www.mozilla.org/en-US/firefox/new/) and [WebKit](https://webkit.org/) browsers with a single API. Playwright delivers automation that is **ever-green**, **capable**, **reliable** and **fast**. [See how Playwright is better](https://playwright.dev/python/docs/why-playwright). | | Linux | macOS | Windows | | :--- | :---: | :---: | :---: | -| Chromium 117.0.5938.62 | ✅ | ✅ | ✅ | +| Chromium 119.0.6045.9 | ✅ | ✅ | ✅ | | WebKit 17.0 | ✅ | ✅ | ✅ | -| Firefox 117.0 | ✅ | ✅ | ✅ | +| Firefox 118.0.1 | ✅ | ✅ | ✅ | ## Documentation @@ -49,6 +49,6 @@ asyncio.run(main()) ## Other languages More comfortable in another programming language? [Playwright](https://playwright.dev) is also available in -- [Node.js (JavaScript / TypeScript)](https://playwright.dev/docs/intro) -- [.NET](https://playwright.dev/dotnet/docs/intro) -- [Java](https://playwright.dev/java/docs/intro) +- [Node.js (JavaScript / TypeScript)](https://playwright.dev/docs/intro), +- [.NET](https://playwright.dev/dotnet/docs/intro), +- [Java](https://playwright.dev/java/docs/intro). diff --git a/playwright/_impl/_assertions.py b/playwright/_impl/_assertions.py index 46e54a9f3..f54a672e1 100644 --- a/playwright/_impl/_assertions.py +++ b/playwright/_impl/_assertions.py @@ -220,7 +220,7 @@ async def to_have_attribute( __tracebackhide__ = True expected_text = to_expected_text_values([value]) await self._expect_impl( - "to.have.attribute", + "to.have.attribute.value", FrameExpectOptions( expressionArg=name, expectedText=expected_text, timeout=timeout ), diff --git a/playwright/_impl/_browser_context.py b/playwright/_impl/_browser_context.py index ddb8ac41a..1c7c546fe 100644 --- a/playwright/_impl/_browser_context.py +++ b/playwright/_impl/_browser_context.py @@ -145,7 +145,7 @@ def __init__( ) self._channel.on( "console", - lambda params: self._on_console_message(from_channel(params["message"])), + lambda event: self._on_console_message(event), ) self._channel.on( @@ -545,7 +545,8 @@ def _on_request_finished( if response: response._finished_future.set_result(True) - def _on_console_message(self, message: ConsoleMessage) -> None: + def _on_console_message(self, event: Dict) -> None: + message = ConsoleMessage(event, self._loop, self._dispatcher_fiber) self.emit(BrowserContext.Events.Console, message) page = message.page if page: diff --git a/playwright/_impl/_connection.py b/playwright/_impl/_connection.py index 45e80b003..e11612fcf 100644 --- a/playwright/_impl/_connection.py +++ b/playwright/_impl/_connection.py @@ -345,12 +345,12 @@ def _send_message_to_server( "internal": not stack_trace_information["apiName"], }, } - self._transport.send(message) - self._callbacks[id] = callback - if self._tracing_count > 0 and frames and guid != "localUtils": self.local_utils.add_stack_to_tracing_no_reply(id, frames) + self._transport.send(message) + self._callbacks[id] = callback + return callback def dispatch(self, msg: ParsedMessagePayload) -> None: diff --git a/playwright/_impl/_console_message.py b/playwright/_impl/_console_message.py index 9bed32ac8..ba8fc0a38 100644 --- a/playwright/_impl/_console_message.py +++ b/playwright/_impl/_console_message.py @@ -12,29 +12,25 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import TYPE_CHECKING, Dict, List, Optional +from asyncio import AbstractEventLoop +from typing import TYPE_CHECKING, Any, Dict, List, Optional from playwright._impl._api_structures import SourceLocation -from playwright._impl._connection import ( - ChannelOwner, - from_channel, - from_nullable_channel, -) +from playwright._impl._connection import from_channel, from_nullable_channel from playwright._impl._js_handle import JSHandle if TYPE_CHECKING: # pragma: no cover from playwright._impl._page import Page -class ConsoleMessage(ChannelOwner): +class ConsoleMessage: def __init__( - self, parent: ChannelOwner, type: str, guid: str, initializer: Dict + self, event: Dict, loop: AbstractEventLoop, dispatcher_fiber: Any ) -> None: - super().__init__(parent, type, guid, initializer) - # Note: currently, we only report console messages for pages and they always have a page. - # However, in the future we might report console messages for service workers or something else, - # where page() would be null. - self._page: Optional["Page"] = from_nullable_channel(initializer.get("page")) + self._event = event + self._loop = loop + self._dispatcher_fiber = dispatcher_fiber + self._page: Optional["Page"] = from_nullable_channel(event.get("page")) def __repr__(self) -> str: return f"" @@ -44,19 +40,19 @@ def __str__(self) -> str: @property def type(self) -> str: - return self._initializer["type"] + return self._event["type"] @property def text(self) -> str: - return self._initializer["text"] + return self._event["text"] @property def args(self) -> List[JSHandle]: - return list(map(from_channel, self._initializer["args"])) + return list(map(from_channel, self._event["args"])) @property def location(self) -> SourceLocation: - return self._initializer["location"] + return self._event["location"] @property def page(self) -> Optional["Page"]: diff --git a/playwright/_impl/_js_handle.py b/playwright/_impl/_js_handle.py index 374f37f74..b23b61ced 100644 --- a/playwright/_impl/_js_handle.py +++ b/playwright/_impl/_js_handle.py @@ -195,16 +195,6 @@ def parse_value(value: Any, refs: Optional[Dict[int, Any]] = None) -> Any: if "bi" in value: return int(value["bi"]) - if "m" in value: - v = {} - refs[value["m"]["id"]] = v - return v - - if "se" in value: - v = set() - refs[value["se"]["id"]] = v - return v - if "a" in value: a: List = [] refs[value["id"]] = a diff --git a/playwright/_impl/_local_utils.py b/playwright/_impl/_local_utils.py index af0683ed2..7172ee58a 100644 --- a/playwright/_impl/_local_utils.py +++ b/playwright/_impl/_local_utils.py @@ -25,6 +25,10 @@ def __init__( self, parent: ChannelOwner, type: str, guid: str, initializer: Dict ) -> None: super().__init__(parent, type, guid, initializer) + self.devices = { + device["name"]: parse_device_descriptor(device["descriptor"]) + for device in initializer["deviceDescriptors"] + } async def zip(self, params: Dict) -> None: await self._channel.send("zip", params) @@ -75,3 +79,14 @@ def add_stack_to_tracing_no_reply(self, id: int, frames: List[StackFrame]) -> No } }, ) + + +def parse_device_descriptor(dict: Dict) -> Dict: + return { + "user_agent": dict["userAgent"], + "viewport": dict["viewport"], + "device_scale_factor": dict["deviceScaleFactor"], + "is_mobile": dict["isMobile"], + "has_touch": dict["hasTouch"], + "default_browser_type": dict["defaultBrowserType"], + } diff --git a/playwright/_impl/_object_factory.py b/playwright/_impl/_object_factory.py index f6dc4a260..2652e41fe 100644 --- a/playwright/_impl/_object_factory.py +++ b/playwright/_impl/_object_factory.py @@ -20,7 +20,6 @@ from playwright._impl._browser_type import BrowserType from playwright._impl._cdp_session import CDPSession from playwright._impl._connection import ChannelOwner -from playwright._impl._console_message import ConsoleMessage from playwright._impl._dialog import Dialog from playwright._impl._element_handle import ElementHandle from playwright._impl._fetch import APIRequestContext @@ -60,8 +59,6 @@ def create_remote_object( return BrowserContext(parent, type, guid, initializer) if type == "CDPSession": return CDPSession(parent, type, guid, initializer) - if type == "ConsoleMessage": - return ConsoleMessage(parent, type, guid, initializer) if type == "Dialog": return Dialog(parent, type, guid, initializer) if type == "ElementHandle": diff --git a/playwright/_impl/_playwright.py b/playwright/_impl/_playwright.py index d3edfacc1..c02e73316 100644 --- a/playwright/_impl/_playwright.py +++ b/playwright/_impl/_playwright.py @@ -17,7 +17,6 @@ from playwright._impl._browser_type import BrowserType from playwright._impl._connection import ChannelOwner, from_channel from playwright._impl._fetch import APIRequest -from playwright._impl._local_utils import LocalUtils from playwright._impl._selectors import Selectors, SelectorsOwner @@ -48,12 +47,7 @@ def __init__( self._connection.on( "close", lambda: self.selectors._remove_channel(selectors_owner) ) - self.devices = {} - self.devices = { - device["name"]: parse_device_descriptor(device["descriptor"]) - for device in initializer["deviceDescriptors"] - } - self._utils: LocalUtils = from_channel(initializer["utils"]) + self.devices = self._connection.local_utils.devices def __getitem__(self, value: str) -> "BrowserType": if value == "chromium": @@ -72,14 +66,3 @@ def _set_selectors(self, selectors: Selectors) -> None: async def stop(self) -> None: pass - - -def parse_device_descriptor(dict: Dict) -> Dict: - return { - "user_agent": dict["userAgent"], - "viewport": dict["viewport"], - "device_scale_factor": dict["deviceScaleFactor"], - "is_mobile": dict["isMobile"], - "has_touch": dict["hasTouch"], - "default_browser_type": dict["defaultBrowserType"], - } diff --git a/playwright/async_api/_generated.py b/playwright/async_api/_generated.py index baebb4265..0b08eb102 100644 --- a/playwright/async_api/_generated.py +++ b/playwright/async_api/_generated.py @@ -2206,7 +2206,7 @@ async def select_option( **Usage** ```py - # single selection matching the value + # Single selection matching the value or label await handle.select_option(\"blue\") # single selection matching the label await handle.select_option(label=\"blue\") @@ -2215,7 +2215,7 @@ async def select_option( ``` ```py - # single selection matching the value + # Single selection matching the value or label handle.select_option(\"blue\") # single selection matching both the label handle.select_option(label=\"blue\") @@ -3804,9 +3804,9 @@ async def wait_for_selector( ```py import asyncio - from playwright.async_api import async_playwright + from playwright.async_api import async_playwright, Playwright - async def run(playwright): + async def run(playwright: Playwright): chromium = playwright.chromium browser = await chromium.launch() page = await browser.new_page() @@ -3823,9 +3823,9 @@ async def main(): ``` ```py - from playwright.sync_api import sync_playwright + from playwright.sync_api import sync_playwright, Playwright - def run(playwright): + def run(playwright: Playwright): chromium = playwright.chromium browser = chromium.launch() page = browser.new_page() @@ -5597,7 +5597,7 @@ async def select_option( **Usage** ```py - # single selection matching the value + # Single selection matching the value or label await frame.select_option(\"select#colors\", \"blue\") # single selection matching the label await frame.select_option(\"select#colors\", label=\"blue\") @@ -5606,7 +5606,7 @@ async def select_option( ``` ```py - # single selection matching the value + # Single selection matching the value or label frame.select_option(\"select#colors\", \"blue\") # single selection matching both the label frame.select_option(\"select#colors\", label=\"blue\") @@ -6029,9 +6029,9 @@ async def wait_for_function( ```py import asyncio - from playwright.async_api import async_playwright + from playwright.async_api import async_playwright, Playwright - async def run(playwright): + async def run(playwright: Playwright): webkit = playwright.webkit browser = await webkit.launch() page = await browser.new_page() @@ -6046,9 +6046,9 @@ async def main(): ``` ```py - from playwright.sync_api import sync_playwright + from playwright.sync_api import sync_playwright, Playwright - def run(playwright): + def run(playwright: Playwright): webkit = playwright.webkit browser = webkit.launch() page = browser.new_page() @@ -6927,9 +6927,9 @@ async def register( ```py import asyncio - from playwright.async_api import async_playwright + from playwright.async_api import async_playwright, Playwright - async def run(playwright): + async def run(playwright: Playwright): tag_selector = \"\"\" { // Returns the first element matching given selector in the root's subtree. @@ -6965,9 +6965,9 @@ async def main(): ``` ```py - from playwright.sync_api import sync_playwright + from playwright.sync_api import sync_playwright, Playwright - def run(playwright): + def run(playwright: Playwright): tag_selector = \"\"\" { // Returns the first element matching given selector in the root's subtree. @@ -8245,9 +8245,9 @@ async def wait_for_selector( ```py import asyncio - from playwright.async_api import async_playwright + from playwright.async_api import async_playwright, Playwright - async def run(playwright): + async def run(playwright: Playwright): chromium = playwright.chromium browser = await chromium.launch() page = await browser.new_page() @@ -8264,9 +8264,9 @@ async def main(): ``` ```py - from playwright.sync_api import sync_playwright + from playwright.sync_api import sync_playwright, Playwright - def run(playwright): + def run(playwright: Playwright): chromium = playwright.chromium browser = chromium.launch() page = browser.new_page() @@ -8923,14 +8923,14 @@ async def expose_function(self, name: str, callback: typing.Callable) -> None: ```py import asyncio import hashlib - from playwright.async_api import async_playwright + from playwright.async_api import async_playwright, Playwright def sha256(text): m = hashlib.sha256() m.update(bytes(text, \"utf8\")) return m.hexdigest() - async def run(playwright): + async def run(playwright: Playwright): webkit = playwright.webkit browser = await webkit.launch(headless=False) page = await browser.new_page() @@ -8954,14 +8954,14 @@ async def main(): ```py import hashlib - from playwright.sync_api import sync_playwright + from playwright.sync_api import sync_playwright, Playwright def sha256(text): m = hashlib.sha256() m.update(bytes(text, \"utf8\")) return m.hexdigest() - def run(playwright): + def run(playwright: Playwright): webkit = playwright.webkit browser = webkit.launch(headless=False) page = browser.new_page() @@ -9021,9 +9021,9 @@ async def expose_binding( ```py import asyncio - from playwright.async_api import async_playwright + from playwright.async_api import async_playwright, Playwright - async def run(playwright): + async def run(playwright: Playwright): webkit = playwright.webkit browser = await webkit.launch(headless=false) context = await browser.new_context() @@ -9047,9 +9047,9 @@ async def main(): ``` ```py - from playwright.sync_api import sync_playwright + from playwright.sync_api import sync_playwright, Playwright - def run(playwright): + def run(playwright: Playwright): webkit = playwright.webkit browser = webkit.launch(headless=false) context = browser.new_context() @@ -11267,7 +11267,7 @@ async def select_option( **Usage** ```py - # single selection matching the value + # Single selection matching the value or label await page.select_option(\"select#colors\", \"blue\") # single selection matching the label await page.select_option(\"select#colors\", label=\"blue\") @@ -11276,7 +11276,7 @@ async def select_option( ``` ```py - # single selection matching the value + # Single selection matching the value or label page.select_option(\"select#colors\", \"blue\") # single selection matching both the label page.select_option(\"select#colors\", label=\"blue\") @@ -11740,9 +11740,9 @@ async def wait_for_function( ```py import asyncio - from playwright.async_api import async_playwright + from playwright.async_api import async_playwright, Playwright - async def run(playwright): + async def run(playwright: Playwright): webkit = playwright.webkit browser = await webkit.launch() page = await browser.new_page() @@ -11757,9 +11757,9 @@ async def main(): ``` ```py - from playwright.sync_api import sync_playwright + from playwright.sync_api import sync_playwright, Playwright - def run(playwright): + def run(playwright: Playwright): webkit = playwright.webkit browser = webkit.launch() page = browser.new_page() @@ -13299,9 +13299,9 @@ async def expose_binding( ```py import asyncio - from playwright.async_api import async_playwright + from playwright.async_api import async_playwright, Playwright - async def run(playwright): + async def run(playwright: Playwright): webkit = playwright.webkit browser = await webkit.launch(headless=false) context = await browser.new_context() @@ -13325,9 +13325,9 @@ async def main(): ``` ```py - from playwright.sync_api import sync_playwright + from playwright.sync_api import sync_playwright, Playwright - def run(playwright): + def run(playwright: Playwright): webkit = playwright.webkit browser = webkit.launch(headless=false) context = browser.new_context() @@ -13412,14 +13412,14 @@ async def expose_function(self, name: str, callback: typing.Callable) -> None: ```py import asyncio import hashlib - from playwright.async_api import async_playwright + from playwright.async_api import async_playwright, Playwright - def sha256(text): + def sha256(text: str) -> str: m = hashlib.sha256() m.update(bytes(text, \"utf8\")) return m.hexdigest() - async def run(playwright): + async def run(playwright: Playwright): webkit = playwright.webkit browser = await webkit.launch(headless=False) context = await browser.new_context() @@ -13446,12 +13446,12 @@ async def main(): import hashlib from playwright.sync_api import sync_playwright - def sha256(text): + def sha256(text: str) -> str: m = hashlib.sha256() m.update(bytes(text, \"utf8\")) return m.hexdigest() - def run(playwright): + def run(playwright: Playwright): webkit = playwright.webkit browser = webkit.launch(headless=False) context = browser.new_context() @@ -15141,9 +15141,9 @@ def devices(self) -> typing.Dict: ```py import asyncio - from playwright.async_api import async_playwright + from playwright.async_api import async_playwright, Playwright - async def run(playwright): + async def run(playwright: Playwright): webkit = playwright.webkit iphone = playwright.devices[\"iPhone 6\"] browser = await webkit.launch() @@ -15160,9 +15160,9 @@ async def main(): ``` ```py - from playwright.sync_api import sync_playwright + from playwright.sync_api import sync_playwright, Playwright - def run(playwright): + def run(playwright: Playwright): webkit = playwright.webkit iphone = playwright.devices[\"iPhone 6\"] browser = webkit.launch() @@ -16926,6 +16926,9 @@ async def count(self) -> int: Returns the number of elements matching the locator. + **NOTE** If you need to assert the number of elements on the page, prefer `locator_assertions.to_have_count()` + to avoid flakiness. See [assertions guide](https://playwright.dev/python/docs/test-assertions) for more details. + **Usage** ```py @@ -17034,6 +17037,9 @@ async def get_attribute( Returns the matching element's attribute value. + **NOTE** If you need to assert an element's attribute, prefer `locator_assertions.to_have_attribute()` to + avoid flakiness. See [assertions guide](https://playwright.dev/python/docs/test-assertions) for more details. + Parameters ---------- name : str @@ -17146,6 +17152,9 @@ async def inner_text(self, *, timeout: typing.Optional[float] = None) -> str: Returns the [`element.innerText`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText). + **NOTE** If you need to assert text on the page, prefer `locator_assertions.to_have_text()` with + `useInnerText` option to avoid flakiness. See [assertions guide](https://playwright.dev/python/docs/test-assertions) for more details. + Parameters ---------- timeout : Union[float, None] @@ -17164,6 +17173,9 @@ async def input_value(self, *, timeout: typing.Optional[float] = None) -> str: Returns the value for the matching `` or `