Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 110 additions & 23 deletions playwright/async_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
from playwright.browser_context import BrowserContext as BrowserContextImpl
from playwright.browser_server import BrowserServer as BrowserServerImpl
from playwright.browser_type import BrowserType as BrowserTypeImpl
from playwright.cdp_session import CDPSession as CDPSessionImpl
from playwright.chromium_browser_context import (
ChromiumBrowserContext as ChromiumBrowserContextImpl,
)
from playwright.console_message import ConsoleMessage as ConsoleMessageImpl
from playwright.dialog import Dialog as DialogImpl
from playwright.download import Download as DownloadImpl
Expand Down Expand Up @@ -647,7 +651,7 @@ def __init__(self, obj: JSHandleImpl):
super().__init__(obj)

async def evaluate(
self, expression: str, arg: typing.Any = None, force_expr: bool = False
self, expression: str, arg: typing.Any = None, force_expr: bool = None
) -> typing.Any:
"""JSHandle.evaluate

Expand Down Expand Up @@ -676,7 +680,7 @@ async def evaluate(
)

async def evaluateHandle(
self, expression: str, arg: typing.Any = None, force_expr: bool = False
self, expression: str, arg: typing.Any = None, force_expr: bool = None
) -> "JSHandle":
"""JSHandle.evaluateHandle

Expand Down Expand Up @@ -1034,7 +1038,7 @@ async def selectOption(
typing.List[str],
typing.List["ElementHandle"],
typing.List[SelectOption],
],
] = None,
timeout: int = None,
noWaitAfter: bool = None,
) -> typing.List[str]:
Expand Down Expand Up @@ -1336,7 +1340,7 @@ async def evalOnSelector(
selector: str,
expression: str,
arg: typing.Any = None,
force_expr: bool = False,
force_expr: bool = None,
) -> typing.Any:
"""ElementHandle.evalOnSelector

Expand Down Expand Up @@ -1374,7 +1378,7 @@ async def evalOnSelectorAll(
selector: str,
expression: str,
arg: typing.Any = None,
force_expr: bool = False,
force_expr: bool = None,
) -> typing.Any:
"""ElementHandle.evalOnSelectorAll

Expand Down Expand Up @@ -1699,7 +1703,7 @@ async def frameElement(self) -> "ElementHandle":
return mapping.from_impl(await self._impl_obj.frameElement())

async def evaluate(
self, expression: str, arg: typing.Any = None, force_expr: bool = False
self, expression: str, arg: typing.Any = None, force_expr: bool = None
) -> typing.Any:
"""Frame.evaluate

Expand Down Expand Up @@ -1729,7 +1733,7 @@ async def evaluate(
)

async def evaluateHandle(
self, expression: str, arg: typing.Any = None, force_expr: bool = False
self, expression: str, arg: typing.Any = None, force_expr: bool = None
) -> "JSHandle":
"""Frame.evaluateHandle

Expand Down Expand Up @@ -1878,7 +1882,7 @@ async def evalOnSelector(
selector: str,
expression: str,
arg: typing.Any = None,
force_expr: bool = False,
force_expr: bool = None,
) -> typing.Any:
"""Frame.evalOnSelector

Expand Down Expand Up @@ -1916,7 +1920,7 @@ async def evalOnSelectorAll(
selector: str,
expression: str,
arg: typing.Any = None,
force_expr: bool = False,
force_expr: bool = None,
) -> typing.Any:
"""Frame.evalOnSelectorAll

Expand Down Expand Up @@ -2334,7 +2338,7 @@ async def selectOption(
typing.List[str],
typing.List["ElementHandle"],
typing.List[SelectOption],
],
] = None,
timeout: int = None,
noWaitAfter: bool = None,
) -> typing.List[str]:
Expand Down Expand Up @@ -2556,7 +2560,7 @@ async def waitForFunction(
self,
expression: str,
arg: typing.Any = None,
force_expr: bool = False,
force_expr: bool = None,
timeout: int = None,
polling: typing.Union[int, Literal["raf"]] = None,
) -> "JSHandle":
Expand Down Expand Up @@ -2640,7 +2644,7 @@ def url(self) -> str:
return mapping.from_maybe_impl(self._impl_obj.url)

async def evaluate(
self, expression: str, arg: typing.Any = None, force_expr: bool = False
self, expression: str, arg: typing.Any = None, force_expr: bool = None
) -> typing.Any:
"""Worker.evaluate

Expand Down Expand Up @@ -2668,7 +2672,7 @@ async def evaluate(
)

async def evaluateHandle(
self, expression: str, arg: typing.Any = None, force_expr: bool = False
self, expression: str, arg: typing.Any = None, force_expr: bool = None
) -> "JSHandle":
"""Worker.evaluateHandle

Expand Down Expand Up @@ -2704,7 +2708,11 @@ def __init__(self, obj: SelectorsImpl):
super().__init__(obj)

async def register(
self, name: str, source: str = "", path: str = None, contentScript: bool = False
self,
name: str,
source: str = None,
path: str = None,
contentScript: bool = None,
) -> NoneType:
"""Selectors.register

Expand All @@ -2714,9 +2722,9 @@ async def register(
----------
name : str
Name that is used in selectors as a prefix, e.g. `{name: 'foo'}` enables `foo=myselectorbody` selectors. May only contain `[a-zA-Z0-9_]` characters.
source : str
source : Optional[str]
Script that evaluates to a selector engine instance.
contentScript : bool
contentScript : Optional[bool]
Whether to run this selector engine in isolated JavaScript environment. This environment has access to the same DOM, but not any JavaScript objects from the frame's scripts. Defaults to `false`. Note that running as a content script is not guaranteed when this engine is used together with other registered engines.
"""
return mapping.from_maybe_impl(
Expand Down Expand Up @@ -3198,7 +3206,7 @@ async def dispatchEvent(
)

async def evaluate(
self, expression: str, arg: typing.Any = None, force_expr: bool = False
self, expression: str, arg: typing.Any = None, force_expr: bool = None
) -> typing.Any:
"""Page.evaluate

Expand Down Expand Up @@ -3230,7 +3238,7 @@ async def evaluate(
)

async def evaluateHandle(
self, expression: str, arg: typing.Any = None, force_expr: bool = False
self, expression: str, arg: typing.Any = None, force_expr: bool = None
) -> "JSHandle":
"""Page.evaluateHandle

Expand Down Expand Up @@ -3264,7 +3272,7 @@ async def evalOnSelector(
selector: str,
expression: str,
arg: typing.Any = None,
force_expr: bool = False,
force_expr: bool = None,
) -> typing.Any:
"""Page.evalOnSelector

Expand Down Expand Up @@ -3303,7 +3311,7 @@ async def evalOnSelectorAll(
selector: str,
expression: str,
arg: typing.Any = None,
force_expr: bool = False,
force_expr: bool = None,
) -> typing.Any:
"""Page.evalOnSelectorAll

Expand Down Expand Up @@ -4281,7 +4289,7 @@ async def selectOption(
typing.List[str],
typing.List["ElementHandle"],
typing.List[SelectOption],
],
] = None,
timeout: int = None,
noWaitAfter: bool = None,
) -> typing.List[str]:
Expand Down Expand Up @@ -4505,7 +4513,7 @@ async def waitForFunction(
self,
expression: str,
arg: typing.Any = None,
force_expr: bool = False,
force_expr: bool = None,
timeout: int = None,
polling: typing.Union[int, Literal["raf"]] = None,
) -> "JSHandle":
Expand Down Expand Up @@ -4913,7 +4921,7 @@ async def clearPermissions(self) -> NoneType:
"""
return mapping.from_maybe_impl(await self._impl_obj.clearPermissions())

async def setGeolocation(self, geolocation: typing.Dict) -> NoneType:
async def setGeolocation(self, geolocation: typing.Dict = None) -> NoneType:
"""BrowserContext.setGeolocation

Sets the context's geolocation. Passing `null` or `undefined` emulates position unavailable.
Expand Down Expand Up @@ -5133,6 +5141,85 @@ def expect_page(
mapping.register(BrowserContextImpl, BrowserContext)


class CDPSession(AsyncBase):
def __init__(self, obj: CDPSessionImpl):
super().__init__(obj)

async def send(self, method: str, params: typing.Dict = None) -> typing.Dict:
"""CDPSession.send

Parameters
----------
method : str
protocol method name
params : Optional[typing.Dict]
Optional method parameters

Returns
-------
typing.Dict
"""
return mapping.from_maybe_impl(
await self._impl_obj.send(method=method, params=params)
)

async def detach(self) -> NoneType:
"""CDPSession.detach

Detaches the CDPSession from the target. Once detached, the CDPSession object won't emit any events and can't be used
to send messages.
"""
return mapping.from_maybe_impl(await self._impl_obj.detach())


mapping.register(CDPSessionImpl, CDPSession)


class ChromiumBrowserContext(BrowserContext):
def __init__(self, obj: ChromiumBrowserContextImpl):
super().__init__(obj)

def backgroundPages(self) -> typing.List["Page"]:
"""ChromiumBrowserContext.backgroundPages

Returns
-------
typing.List[Page]
All existing background pages in the context.
"""
return mapping.from_impl_list(self._impl_obj.backgroundPages())

def serviceWorkers(self) -> typing.List["Worker"]:
"""ChromiumBrowserContext.serviceWorkers

Returns
-------
typing.List[Worker]
All existing service workers in the context.
"""
return mapping.from_impl_list(self._impl_obj.serviceWorkers())

async def newCDPSession(self, page: "Page") -> "CDPSession":
"""ChromiumBrowserContext.newCDPSession

Parameters
----------
page : Page
Page to create new session for.

Returns
-------
CDPSession
Promise that resolves to the newly created session.
"""
return mapping.from_impl(
await self._impl_obj.newCDPSession(page=page._impl_obj)
)


mapping.register(ChromiumBrowserContextImpl, ChromiumBrowserContext)


class Browser(AsyncBase):
def __init__(self, obj: BrowserImpl):
super().__init__(obj)
Expand Down
8 changes: 6 additions & 2 deletions playwright/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

import sys
from types import SimpleNamespace
from typing import Dict, List, Union
from typing import TYPE_CHECKING, Dict, List, Union

from playwright.browser_context import BrowserContext
from playwright.connection import ChannelOwner, from_channel
Expand All @@ -27,15 +27,19 @@
else: # pragma: no cover
from typing_extensions import Literal

if TYPE_CHECKING: # pragma: no cover
from playwright.browser_type import BrowserType


class Browser(ChannelOwner):

Events = SimpleNamespace(Disconnected="disconnected",)

def __init__(
self, parent: ChannelOwner, type: str, guid: str, initializer: Dict
self, parent: "BrowserType", type: str, guid: str, initializer: Dict
) -> None:
super().__init__(parent, type, guid, initializer)
self._browser_type = parent
self._is_connected = True
self._is_closed_or_closing = False

Expand Down
39 changes: 39 additions & 0 deletions playwright/cdp_session.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Copyright (c) Microsoft Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Any, Dict

from playwright.connection import ChannelOwner
from playwright.js_handle import parse_result, serialize_argument


class CDPSession(ChannelOwner):
def __init__(
self, parent: ChannelOwner, type: str, guid: str, initializer: Dict
) -> None:
super().__init__(parent, type, guid, initializer)
self._channel.on("event", lambda params: self._on_event(params))

def _on_event(self, params: Any) -> None:
self.emit(params["method"], parse_result(params["params"]))

async def send(self, method: str, params: Dict = None) -> Dict:
payload = {"method": method}
if params:
payload["params"] = serialize_argument(params)["value"]
result = await self._channel.send("send", payload)
return parse_result(result)

async def detach(self) -> None:
await self._channel.send("detach")
Loading