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
10 changes: 6 additions & 4 deletions playwright/_impl/_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from playwright._impl._helper import (
ColorScheme,
ReducedMotion,
async_readfile,
is_safe_close_error,
locals_to_params,
)
Expand Down Expand Up @@ -106,7 +107,7 @@ async def new_context(
storageState: Union[StorageState, str, Path] = None,
) -> BrowserContext:
params = locals_to_params(locals())
normalize_context_params(self._connection._is_sync, params)
await normalize_context_params(self._connection._is_sync, params)

channel = await self._channel.send("newContext", params)
context = from_channel(channel)
Expand Down Expand Up @@ -190,7 +191,7 @@ async def stop_tracing(self) -> bytes:
return base64.b64decode(encoded_binary)


def normalize_context_params(is_sync: bool, params: Dict) -> None:
async def normalize_context_params(is_sync: bool, params: Dict) -> None:
params["sdkLanguage"] = "python" if is_sync else "python-async"
if params.get("noViewport"):
del params["noViewport"]
Expand All @@ -214,5 +215,6 @@ def normalize_context_params(is_sync: bool, params: Dict) -> None:
if "storageState" in params:
storageState = params["storageState"]
if not isinstance(storageState, dict):
with open(storageState, "r") as f:
params["storageState"] = json.load(f)
params["storageState"] = json.loads(
(await async_readfile(storageState)).decode()
)
8 changes: 4 additions & 4 deletions playwright/_impl/_browser_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
TimeoutSettings,
URLMatch,
URLMatcher,
async_readfile,
async_writefile,
is_safe_close_error,
locals_to_params,
)
Expand Down Expand Up @@ -214,8 +216,7 @@ async def add_init_script(
self, script: str = None, path: Union[str, Path] = None
) -> None:
if path:
with open(path, "r") as file:
script = file.read()
script = (await async_readfile(path)).decode()
if not isinstance(script, str):
raise Error("Either path or script parameter must be specified")
await self._channel.send("addInitScript", dict(source=script))
Expand Down Expand Up @@ -298,8 +299,7 @@ async def _pause(self) -> None:
async def storage_state(self, path: Union[str, Path] = None) -> StorageState:
result = await self._channel.send_return_as_dict("storageState")
if path:
with open(path, "w") as f:
json.dump(result, f)
await async_writefile(path, json.dumps(result))
return result

async def wait_for_event(
Expand Down
2 changes: 1 addition & 1 deletion playwright/_impl/_browser_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ async def launch_persistent_context(
) -> BrowserContext:
userDataDir = str(Path(userDataDir))
params = locals_to_params(locals())
normalize_context_params(self._connection._is_sync, params)
await normalize_context_params(self._connection._is_sync, params)
normalize_launch_params(params)
try:
context = from_channel(
Expand Down
6 changes: 3 additions & 3 deletions playwright/_impl/_element_handle.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from playwright._impl._helper import (
KeyboardModifier,
MouseButton,
async_writefile,
locals_to_params,
make_dirs_for_file,
)
Expand Down Expand Up @@ -179,7 +180,7 @@ async def set_input_files(
noWaitAfter: bool = None,
) -> None:
params = locals_to_params(locals())
params["files"] = normalize_file_payloads(files)
params["files"] = await normalize_file_payloads(files)
await self._channel.send("setInputFiles", params)

async def focus(self) -> None:
Expand Down Expand Up @@ -241,8 +242,7 @@ async def screenshot(
decoded_binary = base64.b64decode(encoded_binary)
if path:
make_dirs_for_file(path)
with open(path, "wb") as fd:
fd.write(decoded_binary)
await async_writefile(path, decoded_binary)
return decoded_binary

async def query_selector(self, selector: str) -> Optional["ElementHandle"]:
Expand Down
18 changes: 9 additions & 9 deletions playwright/_impl/_file_chooser.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from typing import TYPE_CHECKING, List, Union

from playwright._impl._api_structures import FilePayload
from playwright._impl._helper import async_readfile

if TYPE_CHECKING: # pragma: no cover
from playwright._impl._element_handle import ElementHandle
Expand Down Expand Up @@ -57,20 +58,19 @@ async def set_files(
await self._element_handle.set_input_files(files, timeout, noWaitAfter)


def normalize_file_payloads(
async def normalize_file_payloads(
files: Union[str, Path, FilePayload, List[Union[str, Path]], List[FilePayload]]
) -> List:
file_list = files if isinstance(files, list) else [files]
file_payloads: List = []
for item in file_list:
if isinstance(item, str) or isinstance(item, Path):
with open(item, mode="rb") as fd:
file_payloads.append(
{
"name": os.path.basename(item),
"buffer": base64.b64encode(fd.read()).decode(),
}
)
if isinstance(item, (str, Path)):
file_payloads.append(
{
"name": os.path.basename(item),
"buffer": base64.b64encode(await async_readfile(item)).decode(),
}
)
else:
file_payloads.append(
{
Expand Down
24 changes: 15 additions & 9 deletions playwright/_impl/_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
MouseButton,
URLMatch,
URLMatcher,
async_readfile,
locals_to_params,
monotonic_time,
)
Expand Down Expand Up @@ -360,21 +361,26 @@ async def add_script_tag(
) -> ElementHandle:
params = locals_to_params(locals())
if path:
with open(path, "r") as file:
params["content"] = file.read() + "\n//# sourceURL=" + str(Path(path))
del params["path"]
params["content"] = (
(await async_readfile(path)).decode()
+ "\n//# sourceURL="
+ str(Path(path))
)
del params["path"]
return from_channel(await self._channel.send("addScriptTag", params))

async def add_style_tag(
self, url: str = None, path: Union[str, Path] = None, content: str = None
) -> ElementHandle:
params = locals_to_params(locals())
if path:
with open(path, "r") as file:
params["content"] = (
file.read() + "\n/*# sourceURL=" + str(Path(path)) + "*/"
)
del params["path"]
params["content"] = (
(await async_readfile(path)).decode()
+ "\n/*# sourceURL="
+ str(Path(path))
+ "*/"
)
del params["path"]
return from_channel(await self._channel.send("addStyleTag", params))

async def click(
Expand Down Expand Up @@ -479,7 +485,7 @@ async def set_input_files(
noWaitAfter: bool = None,
) -> None:
params = locals_to_params(locals())
params["files"] = normalize_file_payloads(files)
params["files"] = await normalize_file_payloads(files)
await self._channel.send("setInputFiles", params)

async def type(
Expand Down
20 changes: 19 additions & 1 deletion playwright/_impl/_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# 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.

import asyncio
import fnmatch
import math
import os
Expand Down Expand Up @@ -231,3 +231,21 @@ def make_dirs_for_file(path: Union[Path, str]) -> None:
if not os.path.isabs(path):
path = Path.cwd() / path
os.makedirs(os.path.dirname(path), exist_ok=True)


async def async_writefile(file: Union[str, Path], data: Union[str, bytes]) -> None:
def inner() -> None:
with open(file, "w" if isinstance(data, str) else "wb") as fh:
fh.write(data)

loop = asyncio.get_running_loop()
await loop.run_in_executor(None, inner)


async def async_readfile(file: Union[str, Path]) -> bytes:
def inner() -> bytes:
with open(file, "rb") as fh:
return fh.read()

loop = asyncio.get_running_loop()
return await loop.run_in_executor(None, inner)
11 changes: 5 additions & 6 deletions playwright/_impl/_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
URLMatcher,
URLMatchRequest,
URLMatchResponse,
async_readfile,
async_writefile,
is_safe_close_error,
locals_to_params,
make_dirs_for_file,
Expand Down Expand Up @@ -498,8 +500,7 @@ async def add_init_script(
self, script: str = None, path: Union[str, Path] = None
) -> None:
if path:
with open(path, "r") as file:
script = file.read()
script = (await async_readfile(path)).decode()
if not isinstance(script, str):
raise Error("Either path or script parameter must be specified")
await self._channel.send("addInitScript", dict(source=script))
Expand Down Expand Up @@ -542,8 +543,7 @@ async def screenshot(
decoded_binary = base64.b64decode(encoded_binary)
if path:
make_dirs_for_file(path)
with open(path, "wb") as fd:
fd.write(decoded_binary)
await async_writefile(path, decoded_binary)
return decoded_binary

async def title(self) -> str:
Expand Down Expand Up @@ -741,8 +741,7 @@ async def pdf(
decoded_binary = base64.b64decode(encoded_binary)
if path:
make_dirs_for_file(path)
with open(path, "wb") as fd:
fd.write(decoded_binary)
await async_writefile(path, decoded_binary)
return decoded_binary

@property
Expand Down
4 changes: 2 additions & 2 deletions playwright/_impl/_selectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

from playwright._impl._api_types import Error
from playwright._impl._connection import ChannelOwner
from playwright._impl._helper import async_readfile


class Selectors(ChannelOwner):
Expand All @@ -35,8 +36,7 @@ async def register(
if not script and not path:
raise Error("Either source or path should be specified")
if path:
with open(path, "r") as file:
script = file.read()
script = (await async_readfile(path)).decode()
params: Dict = dict(name=name, source=script)
if contentScript:
params["contentScript"] = True
Expand Down
15 changes: 9 additions & 6 deletions playwright/_impl/_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@ def __init__(
super().__init__(parent, type, guid, initializer)

async def save_as(self, path: Union[str, Path]) -> None:
with open(path, mode="wb") as file:
while True:
binary = await self._channel.send("read")
if not binary:
break
file.write(base64.b64decode(binary))
file = await self._loop.run_in_executor(None, lambda: open(path, "wb"))
while True:
binary = await self._channel.send("read")
if not binary:
break
await self._loop.run_in_executor(
None, lambda: file.write(base64.b64decode(binary))
)
await self._loop.run_in_executor(None, lambda: file.close())