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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
- name: Lint
run: pre-commit run --all-files
- name: Test Sync generation script
run: bash buildbots/test-sync-generation.sh
run: bash scripts/verify_api.sh
build:
name: Build
timeout-minutes: 30
Expand Down
11 changes: 3 additions & 8 deletions build_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,7 @@

from playwright.path_utils import get_file_dirname

driver_version_64 = "0.170.0-next.1605305660869"
driver_version_32 = "0.170.0-next.1605305685932"


def driver_version(platform: str) -> str:
return driver_version_32 if platform == "win32" else driver_version_64
driver_version = "0.170.0-next.1605573954344"


if not os.path.exists("driver"):
Expand All @@ -36,7 +31,7 @@ def driver_version(platform: str) -> str:
os.makedirs("playwright/driver")

for platform in ["mac", "linux", "win32", "win32_x64"]:
zip_file = f"playwright-cli-{driver_version(platform)}-{platform}.zip"
zip_file = f"playwright-cli-{driver_version}-{platform}.zip"
if not os.path.exists("driver/" + zip_file):
url = "https://playwright.azureedge.net/builds/cli/next/" + zip_file
print("Fetching ", url)
Expand Down Expand Up @@ -65,7 +60,7 @@ def driver_version(platform: str) -> str:
}

for platform in ["mac", "linux", "win32", "win32_x64"]:
zip_file = f"driver/playwright-cli-{driver_version(platform)}-{platform}.zip"
zip_file = f"driver/playwright-cli-{driver_version}-{platform}.zip"
with zipfile.ZipFile(zip_file, "r") as zip:
zip.extractall(f"driver/{platform}")
if platform_map[sys.platform] == platform:
Expand Down
29 changes: 28 additions & 1 deletion playwright/async_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
RequestFailure,
ResourceTiming,
SelectOption,
SetStorageState,
StorageState,
Viewport,
)
from playwright.input import Keyboard as KeyboardImpl
Expand Down Expand Up @@ -463,6 +465,7 @@ async def fulfill(

async def continue_(
self,
url: str = None,
method: str = None,
headers: typing.Union[typing.Dict[str, str]] = None,
postData: typing.Union[str, bytes] = None,
Expand All @@ -473,6 +476,8 @@ async def continue_(

Parameters
----------
url : Optional[str]
If set changes the request URL. New URL must have same protocol as original one.
method : Optional[str]
If set changes the request method (e.g. GET or POST)
headers : Optional[Dict[str, str]]
Expand All @@ -482,7 +487,10 @@ async def continue_(
"""
return mapping.from_maybe_impl(
await self._impl_obj.continue_(
method=method, headers=mapping.to_impl(headers), postData=postData
url=url,
method=method,
headers=mapping.to_impl(headers),
postData=postData,
)
)

Expand Down Expand Up @@ -5721,6 +5729,17 @@ async def close(self) -> NoneType:
"""
return mapping.from_maybe_impl(await self._impl_obj.close())

async def storageState(self) -> StorageState:
"""BrowserContext.storageState

Returns storage state for this browser context, contains current cookies and local storage snapshot.

Returns
-------
{"cookies": List[Dict], "origins": List[Dict]}
"""
return mapping.from_maybe_impl(await self._impl_obj.storageState())

def expect_event(
self,
event: str,
Expand Down Expand Up @@ -5889,6 +5908,7 @@ async def newContext(
videoSize: IntSize = None,
recordHar: RecordHarOptions = None,
recordVideo: RecordVideoOptions = None,
storageState: SetStorageState = None,
) -> "BrowserContext":
"""Browser.newContext

Expand Down Expand Up @@ -5939,6 +5959,8 @@ async def newContext(
Enables HAR recording for all pages into `recordHar.path` file. If not specified, the HAR is not recorded. Make sure to await `browserContext.close` for the HAR to be saved.
recordVideo : Optional[{"dir": str, "size": Optional[{"width": int, "height": int}]}]
Enables video recording for all pages into `recordVideo.dir` directory. If not specified videos are not recorded. Make sure to await `browserContext.close` for videos to be saved.
storageState : Optional[{"cookies": Optional[List[Dict]], "origins": Optional[List[Dict]]}]
Populates context with given storage state. This method can be used to initialize context with logged-in information obtained via browserContext.storageState().

Returns
-------
Expand Down Expand Up @@ -5969,6 +5991,7 @@ async def newContext(
videoSize=videoSize,
recordHar=recordHar,
recordVideo=recordVideo,
storageState=storageState,
)
)

Expand Down Expand Up @@ -5997,6 +6020,7 @@ async def newPage(
videoSize: IntSize = None,
recordHar: RecordHarOptions = None,
recordVideo: RecordVideoOptions = None,
storageState: SetStorageState = None,
) -> "Page":
"""Browser.newPage

Expand Down Expand Up @@ -6048,6 +6072,8 @@ async def newPage(
Enables HAR recording for all pages into `recordHar.path` file. If not specified, the HAR is not recorded. Make sure to await `page.close` for the HAR to be saved.
recordVideo : Optional[{"dir": str, "size": Optional[{"width": int, "height": int}]}]
Enables video recording for all pages into `recordVideo.dir` directory. If not specified videos are not recorded. Make sure to await `page.close` for videos to be saved.
storageState : Optional[{"cookies": Optional[List[Dict]], "origins": Optional[List[Dict]]}]
Populates context with given storage state. This method can be used to initialize context with logged-in information obtained via browserContext.storageState().

Returns
-------
Expand Down Expand Up @@ -6078,6 +6104,7 @@ async def newPage(
videoSize=videoSize,
recordHar=recordHar,
recordVideo=recordVideo,
storageState=storageState,
)
)

Expand Down
3 changes: 3 additions & 0 deletions playwright/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
ProxyServer,
RecordHarOptions,
RecordVideoOptions,
SetStorageState,
is_safe_close_error,
locals_to_params,
)
Expand Down Expand Up @@ -95,6 +96,7 @@ async def newContext(
videoSize: IntSize = None,
recordHar: RecordHarOptions = None,
recordVideo: RecordVideoOptions = None,
storageState: SetStorageState = None,
) -> BrowserContext:
params = locals_to_params(locals())
# Python is strict in which variables gets passed to methods. We get this
Expand Down Expand Up @@ -143,6 +145,7 @@ async def newPage(
videoSize: IntSize = None,
recordHar: RecordHarOptions = None,
recordVideo: RecordVideoOptions = None,
storageState: SetStorageState = None,
) -> Page:
params = locals_to_params(locals())
# Python is strict in which variables gets passed to methods. We get this
Expand Down
4 changes: 4 additions & 0 deletions playwright/browser_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
PendingWaitEvent,
RouteHandler,
RouteHandlerEntry,
StorageState,
TimeoutSettings,
URLMatch,
URLMatcher,
Expand Down Expand Up @@ -235,6 +236,9 @@ async def close(self) -> None:
if not is_safe_close_error(e):
raise e

async def storageState(self) -> StorageState:
return await self._channel.send_return_as_dict("storageState")

def expect_event(
self,
event: str,
Expand Down
10 changes: 10 additions & 0 deletions playwright/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ def __init__(self, connection: "Connection", guid: str) -> None:
self._object: Optional[ChannelOwner] = None

async def send(self, method: str, params: Dict = None) -> Any:
return await self.inner_send(method, params, False)

async def send_return_as_dict(self, method: str, params: Dict = None) -> Any:
return await self.inner_send(method, params, True)

async def inner_send(
self, method: str, params: Optional[Dict], return_as_dict: bool
) -> Any:
if params is None:
params = {}
callback = self._connection._send_message_to_server(self._guid, method, params)
Expand All @@ -42,6 +50,8 @@ async def send(self, method: str, params: Dict = None) -> Any:
if not result:
return None
assert isinstance(result, dict)
if return_as_dict:
return result
if len(result) == 0:
return None
assert len(result) == 1
Expand Down
17 changes: 14 additions & 3 deletions playwright/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,16 @@
MouseButton = Literal["left", "middle", "right"]


class StorageState(TypedDict):
cookies: List[Cookie]
origins: List[Dict]


class SetStorageState(TypedDict):
cookies: Optional[List[Cookie]]
origins: Optional[List[Dict]]


class MousePosition(TypedDict):
x: float
y: float
Expand Down Expand Up @@ -105,9 +115,10 @@ class Header(TypedDict):


class ContinueParameters(TypedDict, total=False):
method: str
headers: List[Header]
postData: str
url: Optional[str]
Copy link
Member

@mxschmitt mxschmitt Nov 18, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since total=False all keys inside the dict are optional, so afaik you don't have to specify it each time.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to treat it as a type, probably total=False should not be there

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think mypy then complains from the user perspective if you only specify a single property.

method: Optional[str]
headers: Optional[List[Header]]
postData: Optional[str]


class ParsedMessageParams(TypedDict):
Expand Down
3 changes: 3 additions & 0 deletions playwright/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,14 @@ async def fulfill(

async def continue_(
self,
url: str = None,
method: str = None,
headers: Dict[str, str] = None,
postData: Union[str, bytes] = None,
) -> None:
overrides: ContinueParameters = {}
if url:
overrides["url"] = url
if method:
overrides["method"] = method
if headers:
Expand Down
29 changes: 28 additions & 1 deletion playwright/sync_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
RequestFailure,
ResourceTiming,
SelectOption,
SetStorageState,
StorageState,
Viewport,
)
from playwright.input import Keyboard as KeyboardImpl
Expand Down Expand Up @@ -467,6 +469,7 @@ def fulfill(

def continue_(
self,
url: str = None,
method: str = None,
headers: typing.Union[typing.Dict[str, str]] = None,
postData: typing.Union[str, bytes] = None,
Expand All @@ -477,6 +480,8 @@ def continue_(

Parameters
----------
url : Optional[str]
If set changes the request URL. New URL must have same protocol as original one.
method : Optional[str]
If set changes the request method (e.g. GET or POST)
headers : Optional[Dict[str, str]]
Expand All @@ -487,7 +492,10 @@ def continue_(
return mapping.from_maybe_impl(
self._sync(
self._impl_obj.continue_(
method=method, headers=mapping.to_impl(headers), postData=postData
url=url,
method=method,
headers=mapping.to_impl(headers),
postData=postData,
)
)
)
Expand Down Expand Up @@ -5959,6 +5967,17 @@ def close(self) -> NoneType:
"""
return mapping.from_maybe_impl(self._sync(self._impl_obj.close()))

def storageState(self) -> StorageState:
"""BrowserContext.storageState

Returns storage state for this browser context, contains current cookies and local storage snapshot.

Returns
-------
{"cookies": List[Dict], "origins": List[Dict]}
"""
return mapping.from_maybe_impl(self._sync(self._impl_obj.storageState()))

def expect_event(
self,
event: str,
Expand Down Expand Up @@ -6129,6 +6148,7 @@ def newContext(
videoSize: IntSize = None,
recordHar: RecordHarOptions = None,
recordVideo: RecordVideoOptions = None,
storageState: SetStorageState = None,
) -> "BrowserContext":
"""Browser.newContext

Expand Down Expand Up @@ -6179,6 +6199,8 @@ def newContext(
Enables HAR recording for all pages into `recordHar.path` file. If not specified, the HAR is not recorded. Make sure to await `browserContext.close` for the HAR to be saved.
recordVideo : Optional[{"dir": str, "size": Optional[{"width": int, "height": int}]}]
Enables video recording for all pages into `recordVideo.dir` directory. If not specified videos are not recorded. Make sure to await `browserContext.close` for videos to be saved.
storageState : Optional[{"cookies": Optional[List[Dict]], "origins": Optional[List[Dict]]}]
Populates context with given storage state. This method can be used to initialize context with logged-in information obtained via browserContext.storageState().

Returns
-------
Expand Down Expand Up @@ -6210,6 +6232,7 @@ def newContext(
videoSize=videoSize,
recordHar=recordHar,
recordVideo=recordVideo,
storageState=storageState,
)
)
)
Expand Down Expand Up @@ -6239,6 +6262,7 @@ def newPage(
videoSize: IntSize = None,
recordHar: RecordHarOptions = None,
recordVideo: RecordVideoOptions = None,
storageState: SetStorageState = None,
) -> "Page":
"""Browser.newPage

Expand Down Expand Up @@ -6290,6 +6314,8 @@ def newPage(
Enables HAR recording for all pages into `recordHar.path` file. If not specified, the HAR is not recorded. Make sure to await `page.close` for the HAR to be saved.
recordVideo : Optional[{"dir": str, "size": Optional[{"width": int, "height": int}]}]
Enables video recording for all pages into `recordVideo.dir` directory. If not specified videos are not recorded. Make sure to await `page.close` for videos to be saved.
storageState : Optional[{"cookies": Optional[List[Dict]], "origins": Optional[List[Dict]]}]
Populates context with given storage state. This method can be used to initialize context with logged-in information obtained via browserContext.storageState().

Returns
-------
Expand Down Expand Up @@ -6321,6 +6347,7 @@ def newPage(
videoSize=videoSize,
recordHar=recordHar,
recordVideo=recordVideo,
storageState=storageState,
)
)
)
Expand Down
2 changes: 1 addition & 1 deletion scripts/generate_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ def return_value(value: Any) -> List[str]:
from playwright.element_handle import ElementHandle as ElementHandleImpl
from playwright.file_chooser import FileChooser as FileChooserImpl
from playwright.frame import Frame as FrameImpl
from playwright.helper import ConsoleMessageLocation, Credentials, MousePosition, Error, FilePayload, SelectOption, RequestFailure, Viewport, DeviceDescriptor, IntSize, FloatRect, Geolocation, ProxyServer, PdfMargins, ResourceTiming, RecordHarOptions, RecordVideoOptions
from playwright.helper import ConsoleMessageLocation, Credentials, MousePosition, Error, FilePayload, SelectOption, RequestFailure, Viewport, DeviceDescriptor, IntSize, FloatRect, Geolocation, ProxyServer, PdfMargins, ResourceTiming, RecordHarOptions, RecordVideoOptions, StorageState, SetStorageState
from playwright.input import Keyboard as KeyboardImpl, Mouse as MouseImpl, Touchscreen as TouchscreenImpl
from playwright.js_handle import JSHandle as JSHandleImpl
from playwright.network import Request as RequestImpl, Response as ResponseImpl, Route as RouteImpl, WebSocket as WebSocketImpl
Expand Down
Empty file modified scripts/test_to_python.js
100644 → 100755
Empty file.
File renamed without changes.
Loading