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 playwright/_impl/_accessibility.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,5 +65,5 @@ async def snapshot(
params = locals_to_params(locals())
if root:
params["root"] = root._channel
result = await self._channel.send("accessibilitySnapshot", params)
result = await self._channel.send("accessibilitySnapshot", None, params)
return _ax_node_from_protocol(result) if result else None
40 changes: 34 additions & 6 deletions playwright/_impl/_artifact.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -33,27 +33,55 @@ async def path_after_finished(self) -> pathlib.Path:
raise Error(
"Path is not available when using browser_type.connect(). Use save_as() to save a local copy."
)
path = await self._channel.send("pathAfterFinished")
path = await self._channel.send(
"pathAfterFinished",
None,
)
return pathlib.Path(path)

async def save_as(self, path: Union[str, Path]) -> None:
stream = cast(Stream, from_channel(await self._channel.send("saveAsStream")))
stream = cast(
Stream,
from_channel(
await self._channel.send(
"saveAsStream",
None,
)
),
)
make_dirs_for_file(path)
await stream.save_as(path)

async def failure(self) -> Optional[str]:
reason = await self._channel.send("failure")
reason = await self._channel.send(
"failure",
None,
)
if reason is None:
return None
return patch_error_message(reason)

async def delete(self) -> None:
await self._channel.send("delete")
await self._channel.send(
"delete",
None,
)

async def read_info_buffer(self) -> bytes:
stream = cast(Stream, from_channel(await self._channel.send("stream")))
stream = cast(
Stream,
from_channel(
await self._channel.send(
"stream",
None,
)
),
)
buffer = await stream.read_all()
return buffer

async def cancel(self) -> None: # pyright: ignore[reportIncompatibleMethodOverride]
await self._channel.send("cancel")
await self._channel.send(
"cancel",
None,
)
12 changes: 7 additions & 5 deletions playwright/_impl/_browser.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -168,7 +168,7 @@ async def new_context(
assert self._browser_type is not None
await self._browser_type._prepare_browser_context_params(params)

channel = await self._channel.send("newContext", params)
channel = await self._channel.send("newContext", None, params)
context = cast(BrowserContext, from_channel(channel))
await context._initialize_har_from_options(
record_har_content=recordHarContent,
Expand DownExpand Up@@ -235,7 +235,7 @@ async def close(self, reason: str = None) -> None:
if self._should_close_connection_on_close:
await self._connection.stop_async()
else:
await self._channel.send("close", {"reason": reason})
await self._channel.send("close", None, {"reason": reason})
except Exception as e:
if not is_target_closed_error(e):
raise e
Expand All@@ -245,7 +245,7 @@ def version(self) -> str:
return self._initializer["version"]

async def new_browser_cdp_session(self) -> CDPSession:
return from_channel(await self._channel.send("newBrowserCDPSession"))
return from_channel(await self._channel.send("newBrowserCDPSession", None))

async def start_tracing(
self,
Expand All@@ -260,10 +260,12 @@ async def start_tracing(
if path:
self._cr_tracing_path = str(path)
params["path"] = str(path)
await self._channel.send("startTracing", params)
await self._channel.send("startTracing", None, params)

async def stop_tracing(self) -> bytes:
artifact = cast(Artifact, from_channel(await self._channel.send("stopTracing")))
artifact = cast(
Artifact, from_channel(await self._channel.send("stopTracing", None))
)
buffer = await artifact.read_info_buffer()
await artifact.delete()
if self._cr_tracing_path:
Expand Down
35 changes: 18 additions & 17 deletions playwright/_impl/_browser_context.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -330,17 +330,17 @@ async def _initialize_har_from_options(
async def new_page(self) -> Page:
if self._owner_page:
raise Error("Please use browser.new_context()")
return from_channel(await self._channel.send("newPage"))
return from_channel(await self._channel.send("newPage", None))

async def cookies(self, urls: Union[str, Sequence[str]] = None) -> List[Cookie]:
if urls is None:
urls = []
if isinstance(urls, str):
urls = [urls]
return await self._channel.send("cookies", dict(urls=urls))
return await self._channel.send("cookies", None, dict(urls=urls))

async def add_cookies(self, cookies: Sequence[SetCookieParam]) -> None:
await self._channel.send("addCookies", dict(cookies=cookies))
await self._channel.send("addCookies", None, dict(cookies=cookies))

async def clear_cookies(
self,
Expand All@@ -350,6 +350,7 @@ async def clear_cookies(
) -> None:
await self._channel.send(
"clearCookies",
None,
{
"name": name if isinstance(name, str) else None,
"nameRegexSource": name.pattern if isinstance(name, Pattern) else None,
Expand All@@ -374,21 +375,21 @@ async def clear_cookies(
async def grant_permissions(
self, permissions: Sequence[str], origin: str = None
) -> None:
await self._channel.send("grantPermissions", locals_to_params(locals()))
await self._channel.send("grantPermissions", None, locals_to_params(locals()))

async def clear_permissions(self) -> None:
await self._channel.send("clearPermissions")
await self._channel.send("clearPermissions", None)

async def set_geolocation(self, geolocation: Geolocation = None) -> None:
await self._channel.send("setGeolocation", locals_to_params(locals()))
await self._channel.send("setGeolocation", None, locals_to_params(locals()))

async def set_extra_http_headers(self, headers: Dict[str, str]) -> None:
await self._channel.send(
"setExtraHTTPHeaders", dict(headers=serialize_headers(headers))
"setExtraHTTPHeaders", None, dict(headers=serialize_headers(headers))
)

async def set_offline(self, offline: bool) -> None:
await self._channel.send("setOffline", dict(offline=offline))
await self._channel.send("setOffline", None, dict(offline=offline))

async def add_init_script(
self, script: str = None, path: Union[str, Path] = None
Expand All@@ -397,7 +398,7 @@ async def add_init_script(
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))
await self._channel.send("addInitScript", None, dict(source=script))

async def expose_binding(
self, name: str, callback: Callable, handle: bool = None
Expand All@@ -411,7 +412,7 @@ async def expose_binding(
raise Error(f'Function "{name}" has been already registered')
self._bindings[name] = callback
await self._channel.send(
"exposeBinding", dict(name=name, needsHandle=handle or False)
"exposeBinding", None, dict(name=name, needsHandle=handle or False)
)

async def expose_function(self, name: str, callback: Callable) -> None:
Expand DownExpand Up@@ -499,7 +500,7 @@ async def _record_into_har(
}
if page:
params["page"] = page._channel
har_id = await self._channel.send("harStart", params)
har_id = await self._channel.send("harStart", None, params)
self._har_recorders[har_id] = {
"path": str(har),
"content": update_content,
Expand DownExpand Up@@ -535,15 +536,15 @@ async def route_from_har(
async def _update_interception_patterns(self) -> None:
patterns = RouteHandler.prepare_interception_patterns(self._routes)
await self._channel.send(
"setNetworkInterceptionPatterns", {"patterns": patterns}
"setNetworkInterceptionPatterns", None, {"patterns": patterns}
)

async def _update_web_socket_interception_patterns(self) -> None:
patterns = WebSocketRouteHandler.prepare_interception_patterns(
self._web_socket_routes
)
await self._channel.send(
"setWebSocketInterceptionPatterns", {"patterns": patterns}
"setWebSocketInterceptionPatterns", None, {"patterns": patterns}
)

def expect_event(
Expand DownExpand Up@@ -596,7 +597,7 @@ async def _inner_close() -> None:
har = cast(
Artifact,
from_channel(
await self._channel.send("harExport", {"harId": har_id})
await self._channel.send("harExport", None, {"harId": har_id})
),
)
# Server side will compress artifact if content is attach or if file is .zip.
Expand All@@ -615,14 +616,14 @@ async def _inner_close() -> None:
await har.delete()

await self._channel._connection.wrap_api_call(_inner_close, True)
await self._channel.send("close", {"reason": reason})
await self._channel.send("close", None, {"reason": reason})
await self._closed_future

async def storage_state(
self, path: Union[str, Path] = None, indexedDB: bool = None
) -> StorageState:
result = await self._channel.send_return_as_dict(
"storageState", {"indexedDB": indexedDB}
"storageState", None, {"indexedDB": indexedDB}
)
if path:
await async_writefile(path, json.dumps(result))
Expand DownExpand Up@@ -749,7 +750,7 @@ async def new_cdp_session(self, page: Union[Page, Frame]) -> CDPSession:
params["frame"] = page._channel
else:
raise Error("page: expected Page or Frame")
return from_channel(await self._channel.send("newCDPSession", params))
return from_channel(await self._channel.send("newCDPSession", None, params))

@property
def tracing(self) -> Tracing:
Expand Down
16 changes: 11 additions & 5 deletions playwright/_impl/_browser_type.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,12 @@ async def launch(
params = locals_to_params(locals())
normalize_launch_params(params)
browser = cast(
Browser, from_channel(await self._channel.send("launch", params))
Browser,
from_channel(
await self._channel.send(
"launch", TimeoutSettings.launch_timeout, params
)
),
)
browser._connect_to_browser_type(
self, str(tracesDir) if tracesDir is not None else None
Expand DownExpand Up@@ -159,7 +164,7 @@ async def launch_persistent_context(
await self._prepare_browser_context_params(params)
normalize_launch_params(params)
result = await self._channel.send_return_as_dict(
"launchPersistentContext", params
"launchPersistentContext", TimeoutSettings.launch_timeout, params
)
browser = cast(
Browser,
Expand DownExpand Up@@ -197,10 +202,11 @@ async def connect_over_cdp(
headers: Dict[str, str] = None,
) -> Browser:
params = locals_to_params(locals())
params["timeout"] = TimeoutSettings.launch_timeout(timeout)
if params.get("headers"):
params["headers"] = serialize_headers(params["headers"])
response = await self._channel.send_return_as_dict("connectOverCDP", params)
response = await self._channel.send_return_as_dict(
"connectOverCDP", TimeoutSettings.launch_timeout, params
)
browser = cast(Browser, from_channel(response["browser"]))
browser._connect_to_browser_type(self, None)

Expand All@@ -222,6 +228,7 @@ async def connect(
pipe_channel = (
await local_utils._channel.send_return_as_dict(
"connect",
None,
{
"wsEndpoint": wsEndpoint,
"headers": headers,
Expand DownExpand Up@@ -355,4 +362,3 @@ def normalize_launch_params(params: Dict) -> None:
params["downloadsPath"] = str(Path(params["downloadsPath"]))
if "tracesDir" in params:
params["tracesDir"] = str(Path(params["tracesDir"]))
params["timeout"] = TimeoutSettings.launch_timeout(params.get("timeout"))
7 changes: 5 additions & 2 deletions playwright/_impl/_cdp_session.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,7 +29,10 @@ def _on_event(self, params: Any) -> None:
self.emit(params["method"], params.get("params"))

async def send(self, method: str, params: Dict = None) -> Dict:
return await self._channel.send("send", locals_to_params(locals()))
return await self._channel.send("send", None, locals_to_params(locals()))

async def detach(self) -> None:
await self._channel.send("detach")
await self._channel.send(
"detach",
None,
)
32 changes: 25 additions & 7 deletions playwright/_impl/_clock.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,46 +27,64 @@ def __init__(self, browser_context: "BrowserContext") -> None:

async def install(self, time: Union[float, str, datetime.datetime] = None) -> None:
await self._browser_context._channel.send(
"clockInstall", parse_time(time) if time is not None else {}
"clockInstall",
None,
parse_time(time) if time is not None else {},
)

async def fast_forward(
self,
ticks: Union[int, str],
) -> None:
await self._browser_context._channel.send(
"clockFastForward", parse_ticks(ticks)
"clockFastForward",
None,
parse_ticks(ticks),
)

async def pause_at(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send("clockPauseAt", parse_time(time))
await self._browser_context._channel.send(
"clockPauseAt",
None,
parse_time(time),
)

async def resume(
self,
) -> None:
await self._browser_context._channel.send("clockResume")
await self._browser_context._channel.send("clockResume", None)

async def run_for(
self,
ticks: Union[int, str],
) -> None:
await self._browser_context._channel.send("clockRunFor", parse_ticks(ticks))
await self._browser_context._channel.send(
"clockRunFor",
None,
parse_ticks(ticks),
)

async def set_fixed_time(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send("clockSetFixedTime", parse_time(time))
await self._browser_context._channel.send(
"clockSetFixedTime",
None,
parse_time(time),
)

async def set_system_time(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send(
"clockSetSystemTime", parse_time(time)
"clockSetSystemTime",
None,
parse_time(time),
)


Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
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 playwright/_impl/_accessibility.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,5 +65,5 @@ async def snapshot(
params = locals_to_params(locals())
if root:
params["root"] = root._channel
result = await self._channel.send("accessibilitySnapshot", params)
result = await self._channel.send("accessibilitySnapshot", None, params)
return _ax_node_from_protocol(result) if result else None
40 changes: 34 additions & 6 deletions playwright/_impl/_artifact.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -33,27 +33,55 @@ async def path_after_finished(self) -> pathlib.Path:
raise Error(
"Path is not available when using browser_type.connect(). Use save_as() to save a local copy."
)
path = await self._channel.send("pathAfterFinished")
path = await self._channel.send(
"pathAfterFinished",
None,
)
return pathlib.Path(path)

async def save_as(self, path: Union[str, Path]) -> None:
stream = cast(Stream, from_channel(await self._channel.send("saveAsStream")))
stream = cast(
Stream,
from_channel(
await self._channel.send(
"saveAsStream",
None,
)
),
)
make_dirs_for_file(path)
await stream.save_as(path)

async def failure(self) -> Optional[str]:
reason = await self._channel.send("failure")
reason = await self._channel.send(
"failure",
None,
)
if reason is None:
return None
return patch_error_message(reason)

async def delete(self) -> None:
await self._channel.send("delete")
await self._channel.send(
"delete",
None,
)

async def read_info_buffer(self) -> bytes:
stream = cast(Stream, from_channel(await self._channel.send("stream")))
stream = cast(
Stream,
from_channel(
await self._channel.send(
"stream",
None,
)
),
)
buffer = await stream.read_all()
return buffer

async def cancel(self) -> None: # pyright: ignore[reportIncompatibleMethodOverride]
await self._channel.send("cancel")
await self._channel.send(
"cancel",
None,
)
12 changes: 7 additions & 5 deletions playwright/_impl/_browser.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -168,7 +168,7 @@ async def new_context(
assert self._browser_type is not None
await self._browser_type._prepare_browser_context_params(params)

channel = await self._channel.send("newContext", params)
channel = await self._channel.send("newContext", None, params)
context = cast(BrowserContext, from_channel(channel))
await context._initialize_har_from_options(
record_har_content=recordHarContent,
Expand DownExpand Up@@ -235,7 +235,7 @@ async def close(self, reason: str = None) -> None:
if self._should_close_connection_on_close:
await self._connection.stop_async()
else:
await self._channel.send("close", {"reason": reason})
await self._channel.send("close", None, {"reason": reason})
except Exception as e:
if not is_target_closed_error(e):
raise e
Expand All@@ -245,7 +245,7 @@ def version(self) -> str:
return self._initializer["version"]

async def new_browser_cdp_session(self) -> CDPSession:
return from_channel(await self._channel.send("newBrowserCDPSession"))
return from_channel(await self._channel.send("newBrowserCDPSession", None))

async def start_tracing(
self,
Expand All@@ -260,10 +260,12 @@ async def start_tracing(
if path:
self._cr_tracing_path = str(path)
params["path"] = str(path)
await self._channel.send("startTracing", params)
await self._channel.send("startTracing", None, params)

async def stop_tracing(self) -> bytes:
artifact = cast(Artifact, from_channel(await self._channel.send("stopTracing")))
artifact = cast(
Artifact, from_channel(await self._channel.send("stopTracing", None))
)
buffer = await artifact.read_info_buffer()
await artifact.delete()
if self._cr_tracing_path:
Expand Down
35 changes: 18 additions & 17 deletions playwright/_impl/_browser_context.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -330,17 +330,17 @@ async def _initialize_har_from_options(
async def new_page(self) -> Page:
if self._owner_page:
raise Error("Please use browser.new_context()")
return from_channel(await self._channel.send("newPage"))
return from_channel(await self._channel.send("newPage", None))

async def cookies(self, urls: Union[str, Sequence[str]] = None) -> List[Cookie]:
if urls is None:
urls = []
if isinstance(urls, str):
urls = [urls]
return await self._channel.send("cookies", dict(urls=urls))
return await self._channel.send("cookies", None, dict(urls=urls))

async def add_cookies(self, cookies: Sequence[SetCookieParam]) -> None:
await self._channel.send("addCookies", dict(cookies=cookies))
await self._channel.send("addCookies", None, dict(cookies=cookies))

async def clear_cookies(
self,
Expand All@@ -350,6 +350,7 @@ async def clear_cookies(
) -> None:
await self._channel.send(
"clearCookies",
None,
{
"name": name if isinstance(name, str) else None,
"nameRegexSource": name.pattern if isinstance(name, Pattern) else None,
Expand All@@ -374,21 +375,21 @@ async def clear_cookies(
async def grant_permissions(
self, permissions: Sequence[str], origin: str = None
) -> None:
await self._channel.send("grantPermissions", locals_to_params(locals()))
await self._channel.send("grantPermissions", None, locals_to_params(locals()))

async def clear_permissions(self) -> None:
await self._channel.send("clearPermissions")
await self._channel.send("clearPermissions", None)

async def set_geolocation(self, geolocation: Geolocation = None) -> None:
await self._channel.send("setGeolocation", locals_to_params(locals()))
await self._channel.send("setGeolocation", None, locals_to_params(locals()))

async def set_extra_http_headers(self, headers: Dict[str, str]) -> None:
await self._channel.send(
"setExtraHTTPHeaders", dict(headers=serialize_headers(headers))
"setExtraHTTPHeaders", None, dict(headers=serialize_headers(headers))
)

async def set_offline(self, offline: bool) -> None:
await self._channel.send("setOffline", dict(offline=offline))
await self._channel.send("setOffline", None, dict(offline=offline))

async def add_init_script(
self, script: str = None, path: Union[str, Path] = None
Expand All@@ -397,7 +398,7 @@ async def add_init_script(
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))
await self._channel.send("addInitScript", None, dict(source=script))

async def expose_binding(
self, name: str, callback: Callable, handle: bool = None
Expand All@@ -411,7 +412,7 @@ async def expose_binding(
raise Error(f'Function "{name}" has been already registered')
self._bindings[name] = callback
await self._channel.send(
"exposeBinding", dict(name=name, needsHandle=handle or False)
"exposeBinding", None, dict(name=name, needsHandle=handle or False)
)

async def expose_function(self, name: str, callback: Callable) -> None:
Expand DownExpand Up@@ -499,7 +500,7 @@ async def _record_into_har(
}
if page:
params["page"] = page._channel
har_id = await self._channel.send("harStart", params)
har_id = await self._channel.send("harStart", None, params)
self._har_recorders[har_id] = {
"path": str(har),
"content": update_content,
Expand DownExpand Up@@ -535,15 +536,15 @@ async def route_from_har(
async def _update_interception_patterns(self) -> None:
patterns = RouteHandler.prepare_interception_patterns(self._routes)
await self._channel.send(
"setNetworkInterceptionPatterns", {"patterns": patterns}
"setNetworkInterceptionPatterns", None, {"patterns": patterns}
)

async def _update_web_socket_interception_patterns(self) -> None:
patterns = WebSocketRouteHandler.prepare_interception_patterns(
self._web_socket_routes
)
await self._channel.send(
"setWebSocketInterceptionPatterns", {"patterns": patterns}
"setWebSocketInterceptionPatterns", None, {"patterns": patterns}
)

def expect_event(
Expand DownExpand Up@@ -596,7 +597,7 @@ async def _inner_close() -> None:
har = cast(
Artifact,
from_channel(
await self._channel.send("harExport", {"harId": har_id})
await self._channel.send("harExport", None, {"harId": har_id})
),
)
# Server side will compress artifact if content is attach or if file is .zip.
Expand All@@ -615,14 +616,14 @@ async def _inner_close() -> None:
await har.delete()

await self._channel._connection.wrap_api_call(_inner_close, True)
await self._channel.send("close", {"reason": reason})
await self._channel.send("close", None, {"reason": reason})
await self._closed_future

async def storage_state(
self, path: Union[str, Path] = None, indexedDB: bool = None
) -> StorageState:
result = await self._channel.send_return_as_dict(
"storageState", {"indexedDB": indexedDB}
"storageState", None, {"indexedDB": indexedDB}
)
if path:
await async_writefile(path, json.dumps(result))
Expand DownExpand Up@@ -749,7 +750,7 @@ async def new_cdp_session(self, page: Union[Page, Frame]) -> CDPSession:
params["frame"] = page._channel
else:
raise Error("page: expected Page or Frame")
return from_channel(await self._channel.send("newCDPSession", params))
return from_channel(await self._channel.send("newCDPSession", None, params))

@property
def tracing(self) -> Tracing:
Expand Down
16 changes: 11 additions & 5 deletions playwright/_impl/_browser_type.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,12 @@ async def launch(
params = locals_to_params(locals())
normalize_launch_params(params)
browser = cast(
Browser, from_channel(await self._channel.send("launch", params))
Browser,
from_channel(
await self._channel.send(
"launch", TimeoutSettings.launch_timeout, params
)
),
)
browser._connect_to_browser_type(
self, str(tracesDir) if tracesDir is not None else None
Expand DownExpand Up@@ -159,7 +164,7 @@ async def launch_persistent_context(
await self._prepare_browser_context_params(params)
normalize_launch_params(params)
result = await self._channel.send_return_as_dict(
"launchPersistentContext", params
"launchPersistentContext", TimeoutSettings.launch_timeout, params
)
browser = cast(
Browser,
Expand DownExpand Up@@ -197,10 +202,11 @@ async def connect_over_cdp(
headers: Dict[str, str] = None,
) -> Browser:
params = locals_to_params(locals())
params["timeout"] = TimeoutSettings.launch_timeout(timeout)
if params.get("headers"):
params["headers"] = serialize_headers(params["headers"])
response = await self._channel.send_return_as_dict("connectOverCDP", params)
response = await self._channel.send_return_as_dict(
"connectOverCDP", TimeoutSettings.launch_timeout, params
)
browser = cast(Browser, from_channel(response["browser"]))
browser._connect_to_browser_type(self, None)

Expand All@@ -222,6 +228,7 @@ async def connect(
pipe_channel = (
await local_utils._channel.send_return_as_dict(
"connect",
None,
{
"wsEndpoint": wsEndpoint,
"headers": headers,
Expand DownExpand Up@@ -355,4 +362,3 @@ def normalize_launch_params(params: Dict) -> None:
params["downloadsPath"] = str(Path(params["downloadsPath"]))
if "tracesDir" in params:
params["tracesDir"] = str(Path(params["tracesDir"]))
params["timeout"] = TimeoutSettings.launch_timeout(params.get("timeout"))
7 changes: 5 additions & 2 deletions playwright/_impl/_cdp_session.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,7 +29,10 @@ def _on_event(self, params: Any) -> None:
self.emit(params["method"], params.get("params"))

async def send(self, method: str, params: Dict = None) -> Dict:
return await self._channel.send("send", locals_to_params(locals()))
return await self._channel.send("send", None, locals_to_params(locals()))

async def detach(self) -> None:
await self._channel.send("detach")
await self._channel.send(
"detach",
None,
)
32 changes: 25 additions & 7 deletions playwright/_impl/_clock.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,46 +27,64 @@ def __init__(self, browser_context: "BrowserContext") -> None:

async def install(self, time: Union[float, str, datetime.datetime] = None) -> None:
await self._browser_context._channel.send(
"clockInstall", parse_time(time) if time is not None else {}
"clockInstall",
None,
parse_time(time) if time is not None else {},
)

async def fast_forward(
self,
ticks: Union[int, str],
) -> None:
await self._browser_context._channel.send(
"clockFastForward", parse_ticks(ticks)
"clockFastForward",
None,
parse_ticks(ticks),
)

async def pause_at(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send("clockPauseAt", parse_time(time))
await self._browser_context._channel.send(
"clockPauseAt",
None,
parse_time(time),
)

async def resume(
self,
) -> None:
await self._browser_context._channel.send("clockResume")
await self._browser_context._channel.send("clockResume", None)

async def run_for(
self,
ticks: Union[int, str],
) -> None:
await self._browser_context._channel.send("clockRunFor", parse_ticks(ticks))
await self._browser_context._channel.send(
"clockRunFor",
None,
parse_ticks(ticks),
)

async def set_fixed_time(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send("clockSetFixedTime", parse_time(time))
await self._browser_context._channel.send(
"clockSetFixedTime",
None,
parse_time(time),
)

async def set_system_time(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send(
"clockSetSystemTime", parse_time(time)
"clockSetSystemTime",
None,
parse_time(time),
)


Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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 playwright/_impl/_accessibility.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,5 +65,5 @@ async def snapshot(
params = locals_to_params(locals())
if root:
params["root"] = root._channel
result = await self._channel.send("accessibilitySnapshot", params)
result = await self._channel.send("accessibilitySnapshot", None, params)
return _ax_node_from_protocol(result) if result else None
40 changes: 34 additions & 6 deletions playwright/_impl/_artifact.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -33,27 +33,55 @@ async def path_after_finished(self) -> pathlib.Path:
raise Error(
"Path is not available when using browser_type.connect(). Use save_as() to save a local copy."
)
path = await self._channel.send("pathAfterFinished")
path = await self._channel.send(
"pathAfterFinished",
None,
)
return pathlib.Path(path)

async def save_as(self, path: Union[str, Path]) -> None:
stream = cast(Stream, from_channel(await self._channel.send("saveAsStream")))
stream = cast(
Stream,
from_channel(
await self._channel.send(
"saveAsStream",
None,
)
),
)
make_dirs_for_file(path)
await stream.save_as(path)

async def failure(self) -> Optional[str]:
reason = await self._channel.send("failure")
reason = await self._channel.send(
"failure",
None,
)
if reason is None:
return None
return patch_error_message(reason)

async def delete(self) -> None:
await self._channel.send("delete")
await self._channel.send(
"delete",
None,
)

async def read_info_buffer(self) -> bytes:
stream = cast(Stream, from_channel(await self._channel.send("stream")))
stream = cast(
Stream,
from_channel(
await self._channel.send(
"stream",
None,
)
),
)
buffer = await stream.read_all()
return buffer

async def cancel(self) -> None: # pyright: ignore[reportIncompatibleMethodOverride]
await self._channel.send("cancel")
await self._channel.send(
"cancel",
None,
)
12 changes: 7 additions & 5 deletions playwright/_impl/_browser.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -168,7 +168,7 @@ async def new_context(
assert self._browser_type is not None
await self._browser_type._prepare_browser_context_params(params)

channel = await self._channel.send("newContext", params)
channel = await self._channel.send("newContext", None, params)
context = cast(BrowserContext, from_channel(channel))
await context._initialize_har_from_options(
record_har_content=recordHarContent,
Expand DownExpand Up@@ -235,7 +235,7 @@ async def close(self, reason: str = None) -> None:
if self._should_close_connection_on_close:
await self._connection.stop_async()
else:
await self._channel.send("close", {"reason": reason})
await self._channel.send("close", None, {"reason": reason})
except Exception as e:
if not is_target_closed_error(e):
raise e
Expand All@@ -245,7 +245,7 @@ def version(self) -> str:
return self._initializer["version"]

async def new_browser_cdp_session(self) -> CDPSession:
return from_channel(await self._channel.send("newBrowserCDPSession"))
return from_channel(await self._channel.send("newBrowserCDPSession", None))

async def start_tracing(
self,
Expand All@@ -260,10 +260,12 @@ async def start_tracing(
if path:
self._cr_tracing_path = str(path)
params["path"] = str(path)
await self._channel.send("startTracing", params)
await self._channel.send("startTracing", None, params)

async def stop_tracing(self) -> bytes:
artifact = cast(Artifact, from_channel(await self._channel.send("stopTracing")))
artifact = cast(
Artifact, from_channel(await self._channel.send("stopTracing", None))
)
buffer = await artifact.read_info_buffer()
await artifact.delete()
if self._cr_tracing_path:
Expand Down
35 changes: 18 additions & 17 deletions playwright/_impl/_browser_context.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -330,17 +330,17 @@ async def _initialize_har_from_options(
async def new_page(self) -> Page:
if self._owner_page:
raise Error("Please use browser.new_context()")
return from_channel(await self._channel.send("newPage"))
return from_channel(await self._channel.send("newPage", None))

async def cookies(self, urls: Union[str, Sequence[str]] = None) -> List[Cookie]:
if urls is None:
urls = []
if isinstance(urls, str):
urls = [urls]
return await self._channel.send("cookies", dict(urls=urls))
return await self._channel.send("cookies", None, dict(urls=urls))

async def add_cookies(self, cookies: Sequence[SetCookieParam]) -> None:
await self._channel.send("addCookies", dict(cookies=cookies))
await self._channel.send("addCookies", None, dict(cookies=cookies))

async def clear_cookies(
self,
Expand All@@ -350,6 +350,7 @@ async def clear_cookies(
) -> None:
await self._channel.send(
"clearCookies",
None,
{
"name": name if isinstance(name, str) else None,
"nameRegexSource": name.pattern if isinstance(name, Pattern) else None,
Expand All@@ -374,21 +375,21 @@ async def clear_cookies(
async def grant_permissions(
self, permissions: Sequence[str], origin: str = None
) -> None:
await self._channel.send("grantPermissions", locals_to_params(locals()))
await self._channel.send("grantPermissions", None, locals_to_params(locals()))

async def clear_permissions(self) -> None:
await self._channel.send("clearPermissions")
await self._channel.send("clearPermissions", None)

async def set_geolocation(self, geolocation: Geolocation = None) -> None:
await self._channel.send("setGeolocation", locals_to_params(locals()))
await self._channel.send("setGeolocation", None, locals_to_params(locals()))

async def set_extra_http_headers(self, headers: Dict[str, str]) -> None:
await self._channel.send(
"setExtraHTTPHeaders", dict(headers=serialize_headers(headers))
"setExtraHTTPHeaders", None, dict(headers=serialize_headers(headers))
)

async def set_offline(self, offline: bool) -> None:
await self._channel.send("setOffline", dict(offline=offline))
await self._channel.send("setOffline", None, dict(offline=offline))

async def add_init_script(
self, script: str = None, path: Union[str, Path] = None
Expand All@@ -397,7 +398,7 @@ async def add_init_script(
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))
await self._channel.send("addInitScript", None, dict(source=script))

async def expose_binding(
self, name: str, callback: Callable, handle: bool = None
Expand All@@ -411,7 +412,7 @@ async def expose_binding(
raise Error(f'Function "{name}" has been already registered')
self._bindings[name] = callback
await self._channel.send(
"exposeBinding", dict(name=name, needsHandle=handle or False)
"exposeBinding", None, dict(name=name, needsHandle=handle or False)
)

async def expose_function(self, name: str, callback: Callable) -> None:
Expand DownExpand Up@@ -499,7 +500,7 @@ async def _record_into_har(
}
if page:
params["page"] = page._channel
har_id = await self._channel.send("harStart", params)
har_id = await self._channel.send("harStart", None, params)
self._har_recorders[har_id] = {
"path": str(har),
"content": update_content,
Expand DownExpand Up@@ -535,15 +536,15 @@ async def route_from_har(
async def _update_interception_patterns(self) -> None:
patterns = RouteHandler.prepare_interception_patterns(self._routes)
await self._channel.send(
"setNetworkInterceptionPatterns", {"patterns": patterns}
"setNetworkInterceptionPatterns", None, {"patterns": patterns}
)

async def _update_web_socket_interception_patterns(self) -> None:
patterns = WebSocketRouteHandler.prepare_interception_patterns(
self._web_socket_routes
)
await self._channel.send(
"setWebSocketInterceptionPatterns", {"patterns": patterns}
"setWebSocketInterceptionPatterns", None, {"patterns": patterns}
)

def expect_event(
Expand DownExpand Up@@ -596,7 +597,7 @@ async def _inner_close() -> None:
har = cast(
Artifact,
from_channel(
await self._channel.send("harExport", {"harId": har_id})
await self._channel.send("harExport", None, {"harId": har_id})
),
)
# Server side will compress artifact if content is attach or if file is .zip.
Expand All@@ -615,14 +616,14 @@ async def _inner_close() -> None:
await har.delete()

await self._channel._connection.wrap_api_call(_inner_close, True)
await self._channel.send("close", {"reason": reason})
await self._channel.send("close", None, {"reason": reason})
await self._closed_future

async def storage_state(
self, path: Union[str, Path] = None, indexedDB: bool = None
) -> StorageState:
result = await self._channel.send_return_as_dict(
"storageState", {"indexedDB": indexedDB}
"storageState", None, {"indexedDB": indexedDB}
)
if path:
await async_writefile(path, json.dumps(result))
Expand DownExpand Up@@ -749,7 +750,7 @@ async def new_cdp_session(self, page: Union[Page, Frame]) -> CDPSession:
params["frame"] = page._channel
else:
raise Error("page: expected Page or Frame")
return from_channel(await self._channel.send("newCDPSession", params))
return from_channel(await self._channel.send("newCDPSession", None, params))

@property
def tracing(self) -> Tracing:
Expand Down
16 changes: 11 additions & 5 deletions playwright/_impl/_browser_type.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,12 @@ async def launch(
params = locals_to_params(locals())
normalize_launch_params(params)
browser = cast(
Browser, from_channel(await self._channel.send("launch", params))
Browser,
from_channel(
await self._channel.send(
"launch", TimeoutSettings.launch_timeout, params
)
),
)
browser._connect_to_browser_type(
self, str(tracesDir) if tracesDir is not None else None
Expand DownExpand Up@@ -159,7 +164,7 @@ async def launch_persistent_context(
await self._prepare_browser_context_params(params)
normalize_launch_params(params)
result = await self._channel.send_return_as_dict(
"launchPersistentContext", params
"launchPersistentContext", TimeoutSettings.launch_timeout, params
)
browser = cast(
Browser,
Expand DownExpand Up@@ -197,10 +202,11 @@ async def connect_over_cdp(
headers: Dict[str, str] = None,
) -> Browser:
params = locals_to_params(locals())
params["timeout"] = TimeoutSettings.launch_timeout(timeout)
if params.get("headers"):
params["headers"] = serialize_headers(params["headers"])
response = await self._channel.send_return_as_dict("connectOverCDP", params)
response = await self._channel.send_return_as_dict(
"connectOverCDP", TimeoutSettings.launch_timeout, params
)
browser = cast(Browser, from_channel(response["browser"]))
browser._connect_to_browser_type(self, None)

Expand All@@ -222,6 +228,7 @@ async def connect(
pipe_channel = (
await local_utils._channel.send_return_as_dict(
"connect",
None,
{
"wsEndpoint": wsEndpoint,
"headers": headers,
Expand DownExpand Up@@ -355,4 +362,3 @@ def normalize_launch_params(params: Dict) -> None:
params["downloadsPath"] = str(Path(params["downloadsPath"]))
if "tracesDir" in params:
params["tracesDir"] = str(Path(params["tracesDir"]))
params["timeout"] = TimeoutSettings.launch_timeout(params.get("timeout"))
7 changes: 5 additions & 2 deletions playwright/_impl/_cdp_session.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,7 +29,10 @@ def _on_event(self, params: Any) -> None:
self.emit(params["method"], params.get("params"))

async def send(self, method: str, params: Dict = None) -> Dict:
return await self._channel.send("send", locals_to_params(locals()))
return await self._channel.send("send", None, locals_to_params(locals()))

async def detach(self) -> None:
await self._channel.send("detach")
await self._channel.send(
"detach",
None,
)
32 changes: 25 additions & 7 deletions playwright/_impl/_clock.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,46 +27,64 @@ def __init__(self, browser_context: "BrowserContext") -> None:

async def install(self, time: Union[float, str, datetime.datetime] = None) -> None:
await self._browser_context._channel.send(
"clockInstall", parse_time(time) if time is not None else {}
"clockInstall",
None,
parse_time(time) if time is not None else {},
)

async def fast_forward(
self,
ticks: Union[int, str],
) -> None:
await self._browser_context._channel.send(
"clockFastForward", parse_ticks(ticks)
"clockFastForward",
None,
parse_ticks(ticks),
)

async def pause_at(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send("clockPauseAt", parse_time(time))
await self._browser_context._channel.send(
"clockPauseAt",
None,
parse_time(time),
)

async def resume(
self,
) -> None:
await self._browser_context._channel.send("clockResume")
await self._browser_context._channel.send("clockResume", None)

async def run_for(
self,
ticks: Union[int, str],
) -> None:
await self._browser_context._channel.send("clockRunFor", parse_ticks(ticks))
await self._browser_context._channel.send(
"clockRunFor",
None,
parse_ticks(ticks),
)

async def set_fixed_time(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send("clockSetFixedTime", parse_time(time))
await self._browser_context._channel.send(
"clockSetFixedTime",
None,
parse_time(time),
)

async def set_system_time(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send(
"clockSetSystemTime", parse_time(time)
"clockSetSystemTime",
None,
parse_time(time),
)


Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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 playwright/_impl/_accessibility.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,5 +65,5 @@ async def snapshot(
params = locals_to_params(locals())
if root:
params["root"] = root._channel
result = await self._channel.send("accessibilitySnapshot", params)
result = await self._channel.send("accessibilitySnapshot", None, params)
return _ax_node_from_protocol(result) if result else None
40 changes: 34 additions & 6 deletions playwright/_impl/_artifact.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -33,27 +33,55 @@ async def path_after_finished(self) -> pathlib.Path:
raise Error(
"Path is not available when using browser_type.connect(). Use save_as() to save a local copy."
)
path = await self._channel.send("pathAfterFinished")
path = await self._channel.send(
"pathAfterFinished",
None,
)
return pathlib.Path(path)

async def save_as(self, path: Union[str, Path]) -> None:
stream = cast(Stream, from_channel(await self._channel.send("saveAsStream")))
stream = cast(
Stream,
from_channel(
await self._channel.send(
"saveAsStream",
None,
)
),
)
make_dirs_for_file(path)
await stream.save_as(path)

async def failure(self) -> Optional[str]:
reason = await self._channel.send("failure")
reason = await self._channel.send(
"failure",
None,
)
if reason is None:
return None
return patch_error_message(reason)

async def delete(self) -> None:
await self._channel.send("delete")
await self._channel.send(
"delete",
None,
)

async def read_info_buffer(self) -> bytes:
stream = cast(Stream, from_channel(await self._channel.send("stream")))
stream = cast(
Stream,
from_channel(
await self._channel.send(
"stream",
None,
)
),
)
buffer = await stream.read_all()
return buffer

async def cancel(self) -> None: # pyright: ignore[reportIncompatibleMethodOverride]
await self._channel.send("cancel")
await self._channel.send(
"cancel",
None,
)
12 changes: 7 additions & 5 deletions playwright/_impl/_browser.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -168,7 +168,7 @@ async def new_context(
assert self._browser_type is not None
await self._browser_type._prepare_browser_context_params(params)

channel = await self._channel.send("newContext", params)
channel = await self._channel.send("newContext", None, params)
context = cast(BrowserContext, from_channel(channel))
await context._initialize_har_from_options(
record_har_content=recordHarContent,
Expand DownExpand Up@@ -235,7 +235,7 @@ async def close(self, reason: str = None) -> None:
if self._should_close_connection_on_close:
await self._connection.stop_async()
else:
await self._channel.send("close", {"reason": reason})
await self._channel.send("close", None, {"reason": reason})
except Exception as e:
if not is_target_closed_error(e):
raise e
Expand All@@ -245,7 +245,7 @@ def version(self) -> str:
return self._initializer["version"]

async def new_browser_cdp_session(self) -> CDPSession:
return from_channel(await self._channel.send("newBrowserCDPSession"))
return from_channel(await self._channel.send("newBrowserCDPSession", None))

async def start_tracing(
self,
Expand All@@ -260,10 +260,12 @@ async def start_tracing(
if path:
self._cr_tracing_path = str(path)
params["path"] = str(path)
await self._channel.send("startTracing", params)
await self._channel.send("startTracing", None, params)

async def stop_tracing(self) -> bytes:
artifact = cast(Artifact, from_channel(await self._channel.send("stopTracing")))
artifact = cast(
Artifact, from_channel(await self._channel.send("stopTracing", None))
)
buffer = await artifact.read_info_buffer()
await artifact.delete()
if self._cr_tracing_path:
Expand Down
35 changes: 18 additions & 17 deletions playwright/_impl/_browser_context.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -330,17 +330,17 @@ async def _initialize_har_from_options(
async def new_page(self) -> Page:
if self._owner_page:
raise Error("Please use browser.new_context()")
return from_channel(await self._channel.send("newPage"))
return from_channel(await self._channel.send("newPage", None))

async def cookies(self, urls: Union[str, Sequence[str]] = None) -> List[Cookie]:
if urls is None:
urls = []
if isinstance(urls, str):
urls = [urls]
return await self._channel.send("cookies", dict(urls=urls))
return await self._channel.send("cookies", None, dict(urls=urls))

async def add_cookies(self, cookies: Sequence[SetCookieParam]) -> None:
await self._channel.send("addCookies", dict(cookies=cookies))
await self._channel.send("addCookies", None, dict(cookies=cookies))

async def clear_cookies(
self,
Expand All@@ -350,6 +350,7 @@ async def clear_cookies(
) -> None:
await self._channel.send(
"clearCookies",
None,
{
"name": name if isinstance(name, str) else None,
"nameRegexSource": name.pattern if isinstance(name, Pattern) else None,
Expand All@@ -374,21 +375,21 @@ async def clear_cookies(
async def grant_permissions(
self, permissions: Sequence[str], origin: str = None
) -> None:
await self._channel.send("grantPermissions", locals_to_params(locals()))
await self._channel.send("grantPermissions", None, locals_to_params(locals()))

async def clear_permissions(self) -> None:
await self._channel.send("clearPermissions")
await self._channel.send("clearPermissions", None)

async def set_geolocation(self, geolocation: Geolocation = None) -> None:
await self._channel.send("setGeolocation", locals_to_params(locals()))
await self._channel.send("setGeolocation", None, locals_to_params(locals()))

async def set_extra_http_headers(self, headers: Dict[str, str]) -> None:
await self._channel.send(
"setExtraHTTPHeaders", dict(headers=serialize_headers(headers))
"setExtraHTTPHeaders", None, dict(headers=serialize_headers(headers))
)

async def set_offline(self, offline: bool) -> None:
await self._channel.send("setOffline", dict(offline=offline))
await self._channel.send("setOffline", None, dict(offline=offline))

async def add_init_script(
self, script: str = None, path: Union[str, Path] = None
Expand All@@ -397,7 +398,7 @@ async def add_init_script(
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))
await self._channel.send("addInitScript", None, dict(source=script))

async def expose_binding(
self, name: str, callback: Callable, handle: bool = None
Expand All@@ -411,7 +412,7 @@ async def expose_binding(
raise Error(f'Function "{name}" has been already registered')
self._bindings[name] = callback
await self._channel.send(
"exposeBinding", dict(name=name, needsHandle=handle or False)
"exposeBinding", None, dict(name=name, needsHandle=handle or False)
)

async def expose_function(self, name: str, callback: Callable) -> None:
Expand DownExpand Up@@ -499,7 +500,7 @@ async def _record_into_har(
}
if page:
params["page"] = page._channel
har_id = await self._channel.send("harStart", params)
har_id = await self._channel.send("harStart", None, params)
self._har_recorders[har_id] = {
"path": str(har),
"content": update_content,
Expand DownExpand Up@@ -535,15 +536,15 @@ async def route_from_har(
async def _update_interception_patterns(self) -> None:
patterns = RouteHandler.prepare_interception_patterns(self._routes)
await self._channel.send(
"setNetworkInterceptionPatterns", {"patterns": patterns}
"setNetworkInterceptionPatterns", None, {"patterns": patterns}
)

async def _update_web_socket_interception_patterns(self) -> None:
patterns = WebSocketRouteHandler.prepare_interception_patterns(
self._web_socket_routes
)
await self._channel.send(
"setWebSocketInterceptionPatterns", {"patterns": patterns}
"setWebSocketInterceptionPatterns", None, {"patterns": patterns}
)

def expect_event(
Expand DownExpand Up@@ -596,7 +597,7 @@ async def _inner_close() -> None:
har = cast(
Artifact,
from_channel(
await self._channel.send("harExport", {"harId": har_id})
await self._channel.send("harExport", None, {"harId": har_id})
),
)
# Server side will compress artifact if content is attach or if file is .zip.
Expand All@@ -615,14 +616,14 @@ async def _inner_close() -> None:
await har.delete()

await self._channel._connection.wrap_api_call(_inner_close, True)
await self._channel.send("close", {"reason": reason})
await self._channel.send("close", None, {"reason": reason})
await self._closed_future

async def storage_state(
self, path: Union[str, Path] = None, indexedDB: bool = None
) -> StorageState:
result = await self._channel.send_return_as_dict(
"storageState", {"indexedDB": indexedDB}
"storageState", None, {"indexedDB": indexedDB}
)
if path:
await async_writefile(path, json.dumps(result))
Expand DownExpand Up@@ -749,7 +750,7 @@ async def new_cdp_session(self, page: Union[Page, Frame]) -> CDPSession:
params["frame"] = page._channel
else:
raise Error("page: expected Page or Frame")
return from_channel(await self._channel.send("newCDPSession", params))
return from_channel(await self._channel.send("newCDPSession", None, params))

@property
def tracing(self) -> Tracing:
Expand Down
16 changes: 11 additions & 5 deletions playwright/_impl/_browser_type.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,12 @@ async def launch(
params = locals_to_params(locals())
normalize_launch_params(params)
browser = cast(
Browser, from_channel(await self._channel.send("launch", params))
Browser,
from_channel(
await self._channel.send(
"launch", TimeoutSettings.launch_timeout, params
)
),
)
browser._connect_to_browser_type(
self, str(tracesDir) if tracesDir is not None else None
Expand DownExpand Up@@ -159,7 +164,7 @@ async def launch_persistent_context(
await self._prepare_browser_context_params(params)
normalize_launch_params(params)
result = await self._channel.send_return_as_dict(
"launchPersistentContext", params
"launchPersistentContext", TimeoutSettings.launch_timeout, params
)
browser = cast(
Browser,
Expand DownExpand Up@@ -197,10 +202,11 @@ async def connect_over_cdp(
headers: Dict[str, str] = None,
) -> Browser:
params = locals_to_params(locals())
params["timeout"] = TimeoutSettings.launch_timeout(timeout)
if params.get("headers"):
params["headers"] = serialize_headers(params["headers"])
response = await self._channel.send_return_as_dict("connectOverCDP", params)
response = await self._channel.send_return_as_dict(
"connectOverCDP", TimeoutSettings.launch_timeout, params
)
browser = cast(Browser, from_channel(response["browser"]))
browser._connect_to_browser_type(self, None)

Expand All@@ -222,6 +228,7 @@ async def connect(
pipe_channel = (
await local_utils._channel.send_return_as_dict(
"connect",
None,
{
"wsEndpoint": wsEndpoint,
"headers": headers,
Expand DownExpand Up@@ -355,4 +362,3 @@ def normalize_launch_params(params: Dict) -> None:
params["downloadsPath"] = str(Path(params["downloadsPath"]))
if "tracesDir" in params:
params["tracesDir"] = str(Path(params["tracesDir"]))
params["timeout"] = TimeoutSettings.launch_timeout(params.get("timeout"))
7 changes: 5 additions & 2 deletions playwright/_impl/_cdp_session.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,7 +29,10 @@ def _on_event(self, params: Any) -> None:
self.emit(params["method"], params.get("params"))

async def send(self, method: str, params: Dict = None) -> Dict:
return await self._channel.send("send", locals_to_params(locals()))
return await self._channel.send("send", None, locals_to_params(locals()))

async def detach(self) -> None:
await self._channel.send("detach")
await self._channel.send(
"detach",
None,
)
32 changes: 25 additions & 7 deletions playwright/_impl/_clock.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,46 +27,64 @@ def __init__(self, browser_context: "BrowserContext") -> None:

async def install(self, time: Union[float, str, datetime.datetime] = None) -> None:
await self._browser_context._channel.send(
"clockInstall", parse_time(time) if time is not None else {}
"clockInstall",
None,
parse_time(time) if time is not None else {},
)

async def fast_forward(
self,
ticks: Union[int, str],
) -> None:
await self._browser_context._channel.send(
"clockFastForward", parse_ticks(ticks)
"clockFastForward",
None,
parse_ticks(ticks),
)

async def pause_at(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send("clockPauseAt", parse_time(time))
await self._browser_context._channel.send(
"clockPauseAt",
None,
parse_time(time),
)

async def resume(
self,
) -> None:
await self._browser_context._channel.send("clockResume")
await self._browser_context._channel.send("clockResume", None)

async def run_for(
self,
ticks: Union[int, str],
) -> None:
await self._browser_context._channel.send("clockRunFor", parse_ticks(ticks))
await self._browser_context._channel.send(
"clockRunFor",
None,
parse_ticks(ticks),
)

async def set_fixed_time(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send("clockSetFixedTime", parse_time(time))
await self._browser_context._channel.send(
"clockSetFixedTime",
None,
parse_time(time),
)

async def set_system_time(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send(
"clockSetSystemTime", parse_time(time)
"clockSetSystemTime",
None,
parse_time(time),
)


Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
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 playwright/_impl/_accessibility.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,5 +65,5 @@ async def snapshot(
params = locals_to_params(locals())
if root:
params["root"] = root._channel
result = await self._channel.send("accessibilitySnapshot", params)
result = await self._channel.send("accessibilitySnapshot", None, params)
return _ax_node_from_protocol(result) if result else None
40 changes: 34 additions & 6 deletions playwright/_impl/_artifact.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -33,27 +33,55 @@ async def path_after_finished(self) -> pathlib.Path:
raise Error(
"Path is not available when using browser_type.connect(). Use save_as() to save a local copy."
)
path = await self._channel.send("pathAfterFinished")
path = await self._channel.send(
"pathAfterFinished",
None,
)
return pathlib.Path(path)

async def save_as(self, path: Union[str, Path]) -> None:
stream = cast(Stream, from_channel(await self._channel.send("saveAsStream")))
stream = cast(
Stream,
from_channel(
await self._channel.send(
"saveAsStream",
None,
)
),
)
make_dirs_for_file(path)
await stream.save_as(path)

async def failure(self) -> Optional[str]:
reason = await self._channel.send("failure")
reason = await self._channel.send(
"failure",
None,
)
if reason is None:
return None
return patch_error_message(reason)

async def delete(self) -> None:
await self._channel.send("delete")
await self._channel.send(
"delete",
None,
)

async def read_info_buffer(self) -> bytes:
stream = cast(Stream, from_channel(await self._channel.send("stream")))
stream = cast(
Stream,
from_channel(
await self._channel.send(
"stream",
None,
)
),
)
buffer = await stream.read_all()
return buffer

async def cancel(self) -> None: # pyright: ignore[reportIncompatibleMethodOverride]
await self._channel.send("cancel")
await self._channel.send(
"cancel",
None,
)
12 changes: 7 additions & 5 deletions playwright/_impl/_browser.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -168,7 +168,7 @@ async def new_context(
assert self._browser_type is not None
await self._browser_type._prepare_browser_context_params(params)

channel = await self._channel.send("newContext", params)
channel = await self._channel.send("newContext", None, params)
context = cast(BrowserContext, from_channel(channel))
await context._initialize_har_from_options(
record_har_content=recordHarContent,
Expand DownExpand Up@@ -235,7 +235,7 @@ async def close(self, reason: str = None) -> None:
if self._should_close_connection_on_close:
await self._connection.stop_async()
else:
await self._channel.send("close", {"reason": reason})
await self._channel.send("close", None, {"reason": reason})
except Exception as e:
if not is_target_closed_error(e):
raise e
Expand All@@ -245,7 +245,7 @@ def version(self) -> str:
return self._initializer["version"]

async def new_browser_cdp_session(self) -> CDPSession:
return from_channel(await self._channel.send("newBrowserCDPSession"))
return from_channel(await self._channel.send("newBrowserCDPSession", None))

async def start_tracing(
self,
Expand All@@ -260,10 +260,12 @@ async def start_tracing(
if path:
self._cr_tracing_path = str(path)
params["path"] = str(path)
await self._channel.send("startTracing", params)
await self._channel.send("startTracing", None, params)

async def stop_tracing(self) -> bytes:
artifact = cast(Artifact, from_channel(await self._channel.send("stopTracing")))
artifact = cast(
Artifact, from_channel(await self._channel.send("stopTracing", None))
)
buffer = await artifact.read_info_buffer()
await artifact.delete()
if self._cr_tracing_path:
Expand Down
35 changes: 18 additions & 17 deletions playwright/_impl/_browser_context.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -330,17 +330,17 @@ async def _initialize_har_from_options(
async def new_page(self) -> Page:
if self._owner_page:
raise Error("Please use browser.new_context()")
return from_channel(await self._channel.send("newPage"))
return from_channel(await self._channel.send("newPage", None))

async def cookies(self, urls: Union[str, Sequence[str]] = None) -> List[Cookie]:
if urls is None:
urls = []
if isinstance(urls, str):
urls = [urls]
return await self._channel.send("cookies", dict(urls=urls))
return await self._channel.send("cookies", None, dict(urls=urls))

async def add_cookies(self, cookies: Sequence[SetCookieParam]) -> None:
await self._channel.send("addCookies", dict(cookies=cookies))
await self._channel.send("addCookies", None, dict(cookies=cookies))

async def clear_cookies(
self,
Expand All@@ -350,6 +350,7 @@ async def clear_cookies(
) -> None:
await self._channel.send(
"clearCookies",
None,
{
"name": name if isinstance(name, str) else None,
"nameRegexSource": name.pattern if isinstance(name, Pattern) else None,
Expand All@@ -374,21 +375,21 @@ async def clear_cookies(
async def grant_permissions(
self, permissions: Sequence[str], origin: str = None
) -> None:
await self._channel.send("grantPermissions", locals_to_params(locals()))
await self._channel.send("grantPermissions", None, locals_to_params(locals()))

async def clear_permissions(self) -> None:
await self._channel.send("clearPermissions")
await self._channel.send("clearPermissions", None)

async def set_geolocation(self, geolocation: Geolocation = None) -> None:
await self._channel.send("setGeolocation", locals_to_params(locals()))
await self._channel.send("setGeolocation", None, locals_to_params(locals()))

async def set_extra_http_headers(self, headers: Dict[str, str]) -> None:
await self._channel.send(
"setExtraHTTPHeaders", dict(headers=serialize_headers(headers))
"setExtraHTTPHeaders", None, dict(headers=serialize_headers(headers))
)

async def set_offline(self, offline: bool) -> None:
await self._channel.send("setOffline", dict(offline=offline))
await self._channel.send("setOffline", None, dict(offline=offline))

async def add_init_script(
self, script: str = None, path: Union[str, Path] = None
Expand All@@ -397,7 +398,7 @@ async def add_init_script(
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))
await self._channel.send("addInitScript", None, dict(source=script))

async def expose_binding(
self, name: str, callback: Callable, handle: bool = None
Expand All@@ -411,7 +412,7 @@ async def expose_binding(
raise Error(f'Function "{name}" has been already registered')
self._bindings[name] = callback
await self._channel.send(
"exposeBinding", dict(name=name, needsHandle=handle or False)
"exposeBinding", None, dict(name=name, needsHandle=handle or False)
)

async def expose_function(self, name: str, callback: Callable) -> None:
Expand DownExpand Up@@ -499,7 +500,7 @@ async def _record_into_har(
}
if page:
params["page"] = page._channel
har_id = await self._channel.send("harStart", params)
har_id = await self._channel.send("harStart", None, params)
self._har_recorders[har_id] = {
"path": str(har),
"content": update_content,
Expand DownExpand Up@@ -535,15 +536,15 @@ async def route_from_har(
async def _update_interception_patterns(self) -> None:
patterns = RouteHandler.prepare_interception_patterns(self._routes)
await self._channel.send(
"setNetworkInterceptionPatterns", {"patterns": patterns}
"setNetworkInterceptionPatterns", None, {"patterns": patterns}
)

async def _update_web_socket_interception_patterns(self) -> None:
patterns = WebSocketRouteHandler.prepare_interception_patterns(
self._web_socket_routes
)
await self._channel.send(
"setWebSocketInterceptionPatterns", {"patterns": patterns}
"setWebSocketInterceptionPatterns", None, {"patterns": patterns}
)

def expect_event(
Expand DownExpand Up@@ -596,7 +597,7 @@ async def _inner_close() -> None:
har = cast(
Artifact,
from_channel(
await self._channel.send("harExport", {"harId": har_id})
await self._channel.send("harExport", None, {"harId": har_id})
),
)
# Server side will compress artifact if content is attach or if file is .zip.
Expand All@@ -615,14 +616,14 @@ async def _inner_close() -> None:
await har.delete()

await self._channel._connection.wrap_api_call(_inner_close, True)
await self._channel.send("close", {"reason": reason})
await self._channel.send("close", None, {"reason": reason})
await self._closed_future

async def storage_state(
self, path: Union[str, Path] = None, indexedDB: bool = None
) -> StorageState:
result = await self._channel.send_return_as_dict(
"storageState", {"indexedDB": indexedDB}
"storageState", None, {"indexedDB": indexedDB}
)
if path:
await async_writefile(path, json.dumps(result))
Expand DownExpand Up@@ -749,7 +750,7 @@ async def new_cdp_session(self, page: Union[Page, Frame]) -> CDPSession:
params["frame"] = page._channel
else:
raise Error("page: expected Page or Frame")
return from_channel(await self._channel.send("newCDPSession", params))
return from_channel(await self._channel.send("newCDPSession", None, params))

@property
def tracing(self) -> Tracing:
Expand Down
16 changes: 11 additions & 5 deletions playwright/_impl/_browser_type.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,12 @@ async def launch(
params = locals_to_params(locals())
normalize_launch_params(params)
browser = cast(
Browser, from_channel(await self._channel.send("launch", params))
Browser,
from_channel(
await self._channel.send(
"launch", TimeoutSettings.launch_timeout, params
)
),
)
browser._connect_to_browser_type(
self, str(tracesDir) if tracesDir is not None else None
Expand DownExpand Up@@ -159,7 +164,7 @@ async def launch_persistent_context(
await self._prepare_browser_context_params(params)
normalize_launch_params(params)
result = await self._channel.send_return_as_dict(
"launchPersistentContext", params
"launchPersistentContext", TimeoutSettings.launch_timeout, params
)
browser = cast(
Browser,
Expand DownExpand Up@@ -197,10 +202,11 @@ async def connect_over_cdp(
headers: Dict[str, str] = None,
) -> Browser:
params = locals_to_params(locals())
params["timeout"] = TimeoutSettings.launch_timeout(timeout)
if params.get("headers"):
params["headers"] = serialize_headers(params["headers"])
response = await self._channel.send_return_as_dict("connectOverCDP", params)
response = await self._channel.send_return_as_dict(
"connectOverCDP", TimeoutSettings.launch_timeout, params
)
browser = cast(Browser, from_channel(response["browser"]))
browser._connect_to_browser_type(self, None)

Expand All@@ -222,6 +228,7 @@ async def connect(
pipe_channel = (
await local_utils._channel.send_return_as_dict(
"connect",
None,
{
"wsEndpoint": wsEndpoint,
"headers": headers,
Expand DownExpand Up@@ -355,4 +362,3 @@ def normalize_launch_params(params: Dict) -> None:
params["downloadsPath"] = str(Path(params["downloadsPath"]))
if "tracesDir" in params:
params["tracesDir"] = str(Path(params["tracesDir"]))
params["timeout"] = TimeoutSettings.launch_timeout(params.get("timeout"))
7 changes: 5 additions & 2 deletions playwright/_impl/_cdp_session.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,7 +29,10 @@ def _on_event(self, params: Any) -> None:
self.emit(params["method"], params.get("params"))

async def send(self, method: str, params: Dict = None) -> Dict:
return await self._channel.send("send", locals_to_params(locals()))
return await self._channel.send("send", None, locals_to_params(locals()))

async def detach(self) -> None:
await self._channel.send("detach")
await self._channel.send(
"detach",
None,
)
32 changes: 25 additions & 7 deletions playwright/_impl/_clock.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,46 +27,64 @@ def __init__(self, browser_context: "BrowserContext") -> None:

async def install(self, time: Union[float, str, datetime.datetime] = None) -> None:
await self._browser_context._channel.send(
"clockInstall", parse_time(time) if time is not None else {}
"clockInstall",
None,
parse_time(time) if time is not None else {},
)

async def fast_forward(
self,
ticks: Union[int, str],
) -> None:
await self._browser_context._channel.send(
"clockFastForward", parse_ticks(ticks)
"clockFastForward",
None,
parse_ticks(ticks),
)

async def pause_at(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send("clockPauseAt", parse_time(time))
await self._browser_context._channel.send(
"clockPauseAt",
None,
parse_time(time),
)

async def resume(
self,
) -> None:
await self._browser_context._channel.send("clockResume")
await self._browser_context._channel.send("clockResume", None)

async def run_for(
self,
ticks: Union[int, str],
) -> None:
await self._browser_context._channel.send("clockRunFor", parse_ticks(ticks))
await self._browser_context._channel.send(
"clockRunFor",
None,
parse_ticks(ticks),
)

async def set_fixed_time(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send("clockSetFixedTime", parse_time(time))
await self._browser_context._channel.send(
"clockSetFixedTime",
None,
parse_time(time),
)

async def set_system_time(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send(
"clockSetSystemTime", parse_time(time)
"clockSetSystemTime",
None,
parse_time(time),
)


Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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 playwright/_impl/_accessibility.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,5 +65,5 @@ async def snapshot(
params = locals_to_params(locals())
if root:
params["root"] = root._channel
result = await self._channel.send("accessibilitySnapshot", params)
result = await self._channel.send("accessibilitySnapshot", None, params)
return _ax_node_from_protocol(result) if result else None
40 changes: 34 additions & 6 deletions playwright/_impl/_artifact.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -33,27 +33,55 @@ async def path_after_finished(self) -> pathlib.Path:
raise Error(
"Path is not available when using browser_type.connect(). Use save_as() to save a local copy."
)
path = await self._channel.send("pathAfterFinished")
path = await self._channel.send(
"pathAfterFinished",
None,
)
return pathlib.Path(path)

async def save_as(self, path: Union[str, Path]) -> None:
stream = cast(Stream, from_channel(await self._channel.send("saveAsStream")))
stream = cast(
Stream,
from_channel(
await self._channel.send(
"saveAsStream",
None,
)
),
)
make_dirs_for_file(path)
await stream.save_as(path)

async def failure(self) -> Optional[str]:
reason = await self._channel.send("failure")
reason = await self._channel.send(
"failure",
None,
)
if reason is None:
return None
return patch_error_message(reason)

async def delete(self) -> None:
await self._channel.send("delete")
await self._channel.send(
"delete",
None,
)

async def read_info_buffer(self) -> bytes:
stream = cast(Stream, from_channel(await self._channel.send("stream")))
stream = cast(
Stream,
from_channel(
await self._channel.send(
"stream",
None,
)
),
)
buffer = await stream.read_all()
return buffer

async def cancel(self) -> None: # pyright: ignore[reportIncompatibleMethodOverride]
await self._channel.send("cancel")
await self._channel.send(
"cancel",
None,
)
12 changes: 7 additions & 5 deletions playwright/_impl/_browser.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -168,7 +168,7 @@ async def new_context(
assert self._browser_type is not None
await self._browser_type._prepare_browser_context_params(params)

channel = await self._channel.send("newContext", params)
channel = await self._channel.send("newContext", None, params)
context = cast(BrowserContext, from_channel(channel))
await context._initialize_har_from_options(
record_har_content=recordHarContent,
Expand DownExpand Up@@ -235,7 +235,7 @@ async def close(self, reason: str = None) -> None:
if self._should_close_connection_on_close:
await self._connection.stop_async()
else:
await self._channel.send("close", {"reason": reason})
await self._channel.send("close", None, {"reason": reason})
except Exception as e:
if not is_target_closed_error(e):
raise e
Expand All@@ -245,7 +245,7 @@ def version(self) -> str:
return self._initializer["version"]

async def new_browser_cdp_session(self) -> CDPSession:
return from_channel(await self._channel.send("newBrowserCDPSession"))
return from_channel(await self._channel.send("newBrowserCDPSession", None))

async def start_tracing(
self,
Expand All@@ -260,10 +260,12 @@ async def start_tracing(
if path:
self._cr_tracing_path = str(path)
params["path"] = str(path)
await self._channel.send("startTracing", params)
await self._channel.send("startTracing", None, params)

async def stop_tracing(self) -> bytes:
artifact = cast(Artifact, from_channel(await self._channel.send("stopTracing")))
artifact = cast(
Artifact, from_channel(await self._channel.send("stopTracing", None))
)
buffer = await artifact.read_info_buffer()
await artifact.delete()
if self._cr_tracing_path:
Expand Down
35 changes: 18 additions & 17 deletions playwright/_impl/_browser_context.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -330,17 +330,17 @@ async def _initialize_har_from_options(
async def new_page(self) -> Page:
if self._owner_page:
raise Error("Please use browser.new_context()")
return from_channel(await self._channel.send("newPage"))
return from_channel(await self._channel.send("newPage", None))

async def cookies(self, urls: Union[str, Sequence[str]] = None) -> List[Cookie]:
if urls is None:
urls = []
if isinstance(urls, str):
urls = [urls]
return await self._channel.send("cookies", dict(urls=urls))
return await self._channel.send("cookies", None, dict(urls=urls))

async def add_cookies(self, cookies: Sequence[SetCookieParam]) -> None:
await self._channel.send("addCookies", dict(cookies=cookies))
await self._channel.send("addCookies", None, dict(cookies=cookies))

async def clear_cookies(
self,
Expand All@@ -350,6 +350,7 @@ async def clear_cookies(
) -> None:
await self._channel.send(
"clearCookies",
None,
{
"name": name if isinstance(name, str) else None,
"nameRegexSource": name.pattern if isinstance(name, Pattern) else None,
Expand All@@ -374,21 +375,21 @@ async def clear_cookies(
async def grant_permissions(
self, permissions: Sequence[str], origin: str = None
) -> None:
await self._channel.send("grantPermissions", locals_to_params(locals()))
await self._channel.send("grantPermissions", None, locals_to_params(locals()))

async def clear_permissions(self) -> None:
await self._channel.send("clearPermissions")
await self._channel.send("clearPermissions", None)

async def set_geolocation(self, geolocation: Geolocation = None) -> None:
await self._channel.send("setGeolocation", locals_to_params(locals()))
await self._channel.send("setGeolocation", None, locals_to_params(locals()))

async def set_extra_http_headers(self, headers: Dict[str, str]) -> None:
await self._channel.send(
"setExtraHTTPHeaders", dict(headers=serialize_headers(headers))
"setExtraHTTPHeaders", None, dict(headers=serialize_headers(headers))
)

async def set_offline(self, offline: bool) -> None:
await self._channel.send("setOffline", dict(offline=offline))
await self._channel.send("setOffline", None, dict(offline=offline))

async def add_init_script(
self, script: str = None, path: Union[str, Path] = None
Expand All@@ -397,7 +398,7 @@ async def add_init_script(
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))
await self._channel.send("addInitScript", None, dict(source=script))

async def expose_binding(
self, name: str, callback: Callable, handle: bool = None
Expand All@@ -411,7 +412,7 @@ async def expose_binding(
raise Error(f'Function "{name}" has been already registered')
self._bindings[name] = callback
await self._channel.send(
"exposeBinding", dict(name=name, needsHandle=handle or False)
"exposeBinding", None, dict(name=name, needsHandle=handle or False)
)

async def expose_function(self, name: str, callback: Callable) -> None:
Expand DownExpand Up@@ -499,7 +500,7 @@ async def _record_into_har(
}
if page:
params["page"] = page._channel
har_id = await self._channel.send("harStart", params)
har_id = await self._channel.send("harStart", None, params)
self._har_recorders[har_id] = {
"path": str(har),
"content": update_content,
Expand DownExpand Up@@ -535,15 +536,15 @@ async def route_from_har(
async def _update_interception_patterns(self) -> None:
patterns = RouteHandler.prepare_interception_patterns(self._routes)
await self._channel.send(
"setNetworkInterceptionPatterns", {"patterns": patterns}
"setNetworkInterceptionPatterns", None, {"patterns": patterns}
)

async def _update_web_socket_interception_patterns(self) -> None:
patterns = WebSocketRouteHandler.prepare_interception_patterns(
self._web_socket_routes
)
await self._channel.send(
"setWebSocketInterceptionPatterns", {"patterns": patterns}
"setWebSocketInterceptionPatterns", None, {"patterns": patterns}
)

def expect_event(
Expand DownExpand Up@@ -596,7 +597,7 @@ async def _inner_close() -> None:
har = cast(
Artifact,
from_channel(
await self._channel.send("harExport", {"harId": har_id})
await self._channel.send("harExport", None, {"harId": har_id})
),
)
# Server side will compress artifact if content is attach or if file is .zip.
Expand All@@ -615,14 +616,14 @@ async def _inner_close() -> None:
await har.delete()

await self._channel._connection.wrap_api_call(_inner_close, True)
await self._channel.send("close", {"reason": reason})
await self._channel.send("close", None, {"reason": reason})
await self._closed_future

async def storage_state(
self, path: Union[str, Path] = None, indexedDB: bool = None
) -> StorageState:
result = await self._channel.send_return_as_dict(
"storageState", {"indexedDB": indexedDB}
"storageState", None, {"indexedDB": indexedDB}
)
if path:
await async_writefile(path, json.dumps(result))
Expand DownExpand Up@@ -749,7 +750,7 @@ async def new_cdp_session(self, page: Union[Page, Frame]) -> CDPSession:
params["frame"] = page._channel
else:
raise Error("page: expected Page or Frame")
return from_channel(await self._channel.send("newCDPSession", params))
return from_channel(await self._channel.send("newCDPSession", None, params))

@property
def tracing(self) -> Tracing:
Expand Down
16 changes: 11 additions & 5 deletions playwright/_impl/_browser_type.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,12 @@ async def launch(
params = locals_to_params(locals())
normalize_launch_params(params)
browser = cast(
Browser, from_channel(await self._channel.send("launch", params))
Browser,
from_channel(
await self._channel.send(
"launch", TimeoutSettings.launch_timeout, params
)
),
)
browser._connect_to_browser_type(
self, str(tracesDir) if tracesDir is not None else None
Expand DownExpand Up@@ -159,7 +164,7 @@ async def launch_persistent_context(
await self._prepare_browser_context_params(params)
normalize_launch_params(params)
result = await self._channel.send_return_as_dict(
"launchPersistentContext", params
"launchPersistentContext", TimeoutSettings.launch_timeout, params
)
browser = cast(
Browser,
Expand DownExpand Up@@ -197,10 +202,11 @@ async def connect_over_cdp(
headers: Dict[str, str] = None,
) -> Browser:
params = locals_to_params(locals())
params["timeout"] = TimeoutSettings.launch_timeout(timeout)
if params.get("headers"):
params["headers"] = serialize_headers(params["headers"])
response = await self._channel.send_return_as_dict("connectOverCDP", params)
response = await self._channel.send_return_as_dict(
"connectOverCDP", TimeoutSettings.launch_timeout, params
)
browser = cast(Browser, from_channel(response["browser"]))
browser._connect_to_browser_type(self, None)

Expand All@@ -222,6 +228,7 @@ async def connect(
pipe_channel = (
await local_utils._channel.send_return_as_dict(
"connect",
None,
{
"wsEndpoint": wsEndpoint,
"headers": headers,
Expand DownExpand Up@@ -355,4 +362,3 @@ def normalize_launch_params(params: Dict) -> None:
params["downloadsPath"] = str(Path(params["downloadsPath"]))
if "tracesDir" in params:
params["tracesDir"] = str(Path(params["tracesDir"]))
params["timeout"] = TimeoutSettings.launch_timeout(params.get("timeout"))
7 changes: 5 additions & 2 deletions playwright/_impl/_cdp_session.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,7 +29,10 @@ def _on_event(self, params: Any) -> None:
self.emit(params["method"], params.get("params"))

async def send(self, method: str, params: Dict = None) -> Dict:
return await self._channel.send("send", locals_to_params(locals()))
return await self._channel.send("send", None, locals_to_params(locals()))

async def detach(self) -> None:
await self._channel.send("detach")
await self._channel.send(
"detach",
None,
)
32 changes: 25 additions & 7 deletions playwright/_impl/_clock.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,46 +27,64 @@ def __init__(self, browser_context: "BrowserContext") -> None:

async def install(self, time: Union[float, str, datetime.datetime] = None) -> None:
await self._browser_context._channel.send(
"clockInstall", parse_time(time) if time is not None else {}
"clockInstall",
None,
parse_time(time) if time is not None else {},
)

async def fast_forward(
self,
ticks: Union[int, str],
) -> None:
await self._browser_context._channel.send(
"clockFastForward", parse_ticks(ticks)
"clockFastForward",
None,
parse_ticks(ticks),
)

async def pause_at(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send("clockPauseAt", parse_time(time))
await self._browser_context._channel.send(
"clockPauseAt",
None,
parse_time(time),
)

async def resume(
self,
) -> None:
await self._browser_context._channel.send("clockResume")
await self._browser_context._channel.send("clockResume", None)

async def run_for(
self,
ticks: Union[int, str],
) -> None:
await self._browser_context._channel.send("clockRunFor", parse_ticks(ticks))
await self._browser_context._channel.send(
"clockRunFor",
None,
parse_ticks(ticks),
)

async def set_fixed_time(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send("clockSetFixedTime", parse_time(time))
await self._browser_context._channel.send(
"clockSetFixedTime",
None,
parse_time(time),
)

async def set_system_time(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send(
"clockSetSystemTime", parse_time(time)
"clockSetSystemTime",
None,
parse_time(time),
)


Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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 playwright/_impl/_accessibility.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,5 +65,5 @@ async def snapshot(
params = locals_to_params(locals())
if root:
params["root"] = root._channel
result = await self._channel.send("accessibilitySnapshot", params)
result = await self._channel.send("accessibilitySnapshot", None, params)
return _ax_node_from_protocol(result) if result else None
40 changes: 34 additions & 6 deletions playwright/_impl/_artifact.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -33,27 +33,55 @@ async def path_after_finished(self) -> pathlib.Path:
raise Error(
"Path is not available when using browser_type.connect(). Use save_as() to save a local copy."
)
path = await self._channel.send("pathAfterFinished")
path = await self._channel.send(
"pathAfterFinished",
None,
)
return pathlib.Path(path)

async def save_as(self, path: Union[str, Path]) -> None:
stream = cast(Stream, from_channel(await self._channel.send("saveAsStream")))
stream = cast(
Stream,
from_channel(
await self._channel.send(
"saveAsStream",
None,
)
),
)
make_dirs_for_file(path)
await stream.save_as(path)

async def failure(self) -> Optional[str]:
reason = await self._channel.send("failure")
reason = await self._channel.send(
"failure",
None,
)
if reason is None:
return None
return patch_error_message(reason)

async def delete(self) -> None:
await self._channel.send("delete")
await self._channel.send(
"delete",
None,
)

async def read_info_buffer(self) -> bytes:
stream = cast(Stream, from_channel(await self._channel.send("stream")))
stream = cast(
Stream,
from_channel(
await self._channel.send(
"stream",
None,
)
),
)
buffer = await stream.read_all()
return buffer

async def cancel(self) -> None: # pyright: ignore[reportIncompatibleMethodOverride]
await self._channel.send("cancel")
await self._channel.send(
"cancel",
None,
)
12 changes: 7 additions & 5 deletions playwright/_impl/_browser.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -168,7 +168,7 @@ async def new_context(
assert self._browser_type is not None
await self._browser_type._prepare_browser_context_params(params)

channel = await self._channel.send("newContext", params)
channel = await self._channel.send("newContext", None, params)
context = cast(BrowserContext, from_channel(channel))
await context._initialize_har_from_options(
record_har_content=recordHarContent,
Expand DownExpand Up@@ -235,7 +235,7 @@ async def close(self, reason: str = None) -> None:
if self._should_close_connection_on_close:
await self._connection.stop_async()
else:
await self._channel.send("close", {"reason": reason})
await self._channel.send("close", None, {"reason": reason})
except Exception as e:
if not is_target_closed_error(e):
raise e
Expand All@@ -245,7 +245,7 @@ def version(self) -> str:
return self._initializer["version"]

async def new_browser_cdp_session(self) -> CDPSession:
return from_channel(await self._channel.send("newBrowserCDPSession"))
return from_channel(await self._channel.send("newBrowserCDPSession", None))

async def start_tracing(
self,
Expand All@@ -260,10 +260,12 @@ async def start_tracing(
if path:
self._cr_tracing_path = str(path)
params["path"] = str(path)
await self._channel.send("startTracing", params)
await self._channel.send("startTracing", None, params)

async def stop_tracing(self) -> bytes:
artifact = cast(Artifact, from_channel(await self._channel.send("stopTracing")))
artifact = cast(
Artifact, from_channel(await self._channel.send("stopTracing", None))
)
buffer = await artifact.read_info_buffer()
await artifact.delete()
if self._cr_tracing_path:
Expand Down
35 changes: 18 additions & 17 deletions playwright/_impl/_browser_context.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -330,17 +330,17 @@ async def _initialize_har_from_options(
async def new_page(self) -> Page:
if self._owner_page:
raise Error("Please use browser.new_context()")
return from_channel(await self._channel.send("newPage"))
return from_channel(await self._channel.send("newPage", None))

async def cookies(self, urls: Union[str, Sequence[str]] = None) -> List[Cookie]:
if urls is None:
urls = []
if isinstance(urls, str):
urls = [urls]
return await self._channel.send("cookies", dict(urls=urls))
return await self._channel.send("cookies", None, dict(urls=urls))

async def add_cookies(self, cookies: Sequence[SetCookieParam]) -> None:
await self._channel.send("addCookies", dict(cookies=cookies))
await self._channel.send("addCookies", None, dict(cookies=cookies))

async def clear_cookies(
self,
Expand All@@ -350,6 +350,7 @@ async def clear_cookies(
) -> None:
await self._channel.send(
"clearCookies",
None,
{
"name": name if isinstance(name, str) else None,
"nameRegexSource": name.pattern if isinstance(name, Pattern) else None,
Expand All@@ -374,21 +375,21 @@ async def clear_cookies(
async def grant_permissions(
self, permissions: Sequence[str], origin: str = None
) -> None:
await self._channel.send("grantPermissions", locals_to_params(locals()))
await self._channel.send("grantPermissions", None, locals_to_params(locals()))

async def clear_permissions(self) -> None:
await self._channel.send("clearPermissions")
await self._channel.send("clearPermissions", None)

async def set_geolocation(self, geolocation: Geolocation = None) -> None:
await self._channel.send("setGeolocation", locals_to_params(locals()))
await self._channel.send("setGeolocation", None, locals_to_params(locals()))

async def set_extra_http_headers(self, headers: Dict[str, str]) -> None:
await self._channel.send(
"setExtraHTTPHeaders", dict(headers=serialize_headers(headers))
"setExtraHTTPHeaders", None, dict(headers=serialize_headers(headers))
)

async def set_offline(self, offline: bool) -> None:
await self._channel.send("setOffline", dict(offline=offline))
await self._channel.send("setOffline", None, dict(offline=offline))

async def add_init_script(
self, script: str = None, path: Union[str, Path] = None
Expand All@@ -397,7 +398,7 @@ async def add_init_script(
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))
await self._channel.send("addInitScript", None, dict(source=script))

async def expose_binding(
self, name: str, callback: Callable, handle: bool = None
Expand All@@ -411,7 +412,7 @@ async def expose_binding(
raise Error(f'Function "{name}" has been already registered')
self._bindings[name] = callback
await self._channel.send(
"exposeBinding", dict(name=name, needsHandle=handle or False)
"exposeBinding", None, dict(name=name, needsHandle=handle or False)
)

async def expose_function(self, name: str, callback: Callable) -> None:
Expand DownExpand Up@@ -499,7 +500,7 @@ async def _record_into_har(
}
if page:
params["page"] = page._channel
har_id = await self._channel.send("harStart", params)
har_id = await self._channel.send("harStart", None, params)
self._har_recorders[har_id] = {
"path": str(har),
"content": update_content,
Expand DownExpand Up@@ -535,15 +536,15 @@ async def route_from_har(
async def _update_interception_patterns(self) -> None:
patterns = RouteHandler.prepare_interception_patterns(self._routes)
await self._channel.send(
"setNetworkInterceptionPatterns", {"patterns": patterns}
"setNetworkInterceptionPatterns", None, {"patterns": patterns}
)

async def _update_web_socket_interception_patterns(self) -> None:
patterns = WebSocketRouteHandler.prepare_interception_patterns(
self._web_socket_routes
)
await self._channel.send(
"setWebSocketInterceptionPatterns", {"patterns": patterns}
"setWebSocketInterceptionPatterns", None, {"patterns": patterns}
)

def expect_event(
Expand DownExpand Up@@ -596,7 +597,7 @@ async def _inner_close() -> None:
har = cast(
Artifact,
from_channel(
await self._channel.send("harExport", {"harId": har_id})
await self._channel.send("harExport", None, {"harId": har_id})
),
)
# Server side will compress artifact if content is attach or if file is .zip.
Expand All@@ -615,14 +616,14 @@ async def _inner_close() -> None:
await har.delete()

await self._channel._connection.wrap_api_call(_inner_close, True)
await self._channel.send("close", {"reason": reason})
await self._channel.send("close", None, {"reason": reason})
await self._closed_future

async def storage_state(
self, path: Union[str, Path] = None, indexedDB: bool = None
) -> StorageState:
result = await self._channel.send_return_as_dict(
"storageState", {"indexedDB": indexedDB}
"storageState", None, {"indexedDB": indexedDB}
)
if path:
await async_writefile(path, json.dumps(result))
Expand DownExpand Up@@ -749,7 +750,7 @@ async def new_cdp_session(self, page: Union[Page, Frame]) -> CDPSession:
params["frame"] = page._channel
else:
raise Error("page: expected Page or Frame")
return from_channel(await self._channel.send("newCDPSession", params))
return from_channel(await self._channel.send("newCDPSession", None, params))

@property
def tracing(self) -> Tracing:
Expand Down
16 changes: 11 additions & 5 deletions playwright/_impl/_browser_type.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,12 @@ async def launch(
params = locals_to_params(locals())
normalize_launch_params(params)
browser = cast(
Browser, from_channel(await self._channel.send("launch", params))
Browser,
from_channel(
await self._channel.send(
"launch", TimeoutSettings.launch_timeout, params
)
),
)
browser._connect_to_browser_type(
self, str(tracesDir) if tracesDir is not None else None
Expand DownExpand Up@@ -159,7 +164,7 @@ async def launch_persistent_context(
await self._prepare_browser_context_params(params)
normalize_launch_params(params)
result = await self._channel.send_return_as_dict(
"launchPersistentContext", params
"launchPersistentContext", TimeoutSettings.launch_timeout, params
)
browser = cast(
Browser,
Expand DownExpand Up@@ -197,10 +202,11 @@ async def connect_over_cdp(
headers: Dict[str, str] = None,
) -> Browser:
params = locals_to_params(locals())
params["timeout"] = TimeoutSettings.launch_timeout(timeout)
if params.get("headers"):
params["headers"] = serialize_headers(params["headers"])
response = await self._channel.send_return_as_dict("connectOverCDP", params)
response = await self._channel.send_return_as_dict(
"connectOverCDP", TimeoutSettings.launch_timeout, params
)
browser = cast(Browser, from_channel(response["browser"]))
browser._connect_to_browser_type(self, None)

Expand All@@ -222,6 +228,7 @@ async def connect(
pipe_channel = (
await local_utils._channel.send_return_as_dict(
"connect",
None,
{
"wsEndpoint": wsEndpoint,
"headers": headers,
Expand DownExpand Up@@ -355,4 +362,3 @@ def normalize_launch_params(params: Dict) -> None:
params["downloadsPath"] = str(Path(params["downloadsPath"]))
if "tracesDir" in params:
params["tracesDir"] = str(Path(params["tracesDir"]))
params["timeout"] = TimeoutSettings.launch_timeout(params.get("timeout"))
7 changes: 5 additions & 2 deletions playwright/_impl/_cdp_session.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,7 +29,10 @@ def _on_event(self, params: Any) -> None:
self.emit(params["method"], params.get("params"))

async def send(self, method: str, params: Dict = None) -> Dict:
return await self._channel.send("send", locals_to_params(locals()))
return await self._channel.send("send", None, locals_to_params(locals()))

async def detach(self) -> None:
await self._channel.send("detach")
await self._channel.send(
"detach",
None,
)
32 changes: 25 additions & 7 deletions playwright/_impl/_clock.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,46 +27,64 @@ def __init__(self, browser_context: "BrowserContext") -> None:

async def install(self, time: Union[float, str, datetime.datetime] = None) -> None:
await self._browser_context._channel.send(
"clockInstall", parse_time(time) if time is not None else {}
"clockInstall",
None,
parse_time(time) if time is not None else {},
)

async def fast_forward(
self,
ticks: Union[int, str],
) -> None:
await self._browser_context._channel.send(
"clockFastForward", parse_ticks(ticks)
"clockFastForward",
None,
parse_ticks(ticks),
)

async def pause_at(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send("clockPauseAt", parse_time(time))
await self._browser_context._channel.send(
"clockPauseAt",
None,
parse_time(time),
)

async def resume(
self,
) -> None:
await self._browser_context._channel.send("clockResume")
await self._browser_context._channel.send("clockResume", None)

async def run_for(
self,
ticks: Union[int, str],
) -> None:
await self._browser_context._channel.send("clockRunFor", parse_ticks(ticks))
await self._browser_context._channel.send(
"clockRunFor",
None,
parse_ticks(ticks),
)

async def set_fixed_time(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send("clockSetFixedTime", parse_time(time))
await self._browser_context._channel.send(
"clockSetFixedTime",
None,
parse_time(time),
)

async def set_system_time(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send(
"clockSetSystemTime", parse_time(time)
"clockSetSystemTime",
None,
parse_time(time),
)


Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
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 playwright/_impl/_accessibility.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,5 +65,5 @@ async def snapshot(
params = locals_to_params(locals())
if root:
params["root"] = root._channel
result = await self._channel.send("accessibilitySnapshot", params)
result = await self._channel.send("accessibilitySnapshot", None, params)
return _ax_node_from_protocol(result) if result else None
40 changes: 34 additions & 6 deletions playwright/_impl/_artifact.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -33,27 +33,55 @@ async def path_after_finished(self) -> pathlib.Path:
raise Error(
"Path is not available when using browser_type.connect(). Use save_as() to save a local copy."
)
path = await self._channel.send("pathAfterFinished")
path = await self._channel.send(
"pathAfterFinished",
None,
)
return pathlib.Path(path)

async def save_as(self, path: Union[str, Path]) -> None:
stream = cast(Stream, from_channel(await self._channel.send("saveAsStream")))
stream = cast(
Stream,
from_channel(
await self._channel.send(
"saveAsStream",
None,
)
),
)
make_dirs_for_file(path)
await stream.save_as(path)

async def failure(self) -> Optional[str]:
reason = await self._channel.send("failure")
reason = await self._channel.send(
"failure",
None,
)
if reason is None:
return None
return patch_error_message(reason)

async def delete(self) -> None:
await self._channel.send("delete")
await self._channel.send(
"delete",
None,
)

async def read_info_buffer(self) -> bytes:
stream = cast(Stream, from_channel(await self._channel.send("stream")))
stream = cast(
Stream,
from_channel(
await self._channel.send(
"stream",
None,
)
),
)
buffer = await stream.read_all()
return buffer

async def cancel(self) -> None: # pyright: ignore[reportIncompatibleMethodOverride]
await self._channel.send("cancel")
await self._channel.send(
"cancel",
None,
)
12 changes: 7 additions & 5 deletions playwright/_impl/_browser.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -168,7 +168,7 @@ async def new_context(
assert self._browser_type is not None
await self._browser_type._prepare_browser_context_params(params)

channel = await self._channel.send("newContext", params)
channel = await self._channel.send("newContext", None, params)
context = cast(BrowserContext, from_channel(channel))
await context._initialize_har_from_options(
record_har_content=recordHarContent,
Expand DownExpand Up@@ -235,7 +235,7 @@ async def close(self, reason: str = None) -> None:
if self._should_close_connection_on_close:
await self._connection.stop_async()
else:
await self._channel.send("close", {"reason": reason})
await self._channel.send("close", None, {"reason": reason})
except Exception as e:
if not is_target_closed_error(e):
raise e
Expand All@@ -245,7 +245,7 @@ def version(self) -> str:
return self._initializer["version"]

async def new_browser_cdp_session(self) -> CDPSession:
return from_channel(await self._channel.send("newBrowserCDPSession"))
return from_channel(await self._channel.send("newBrowserCDPSession", None))

async def start_tracing(
self,
Expand All@@ -260,10 +260,12 @@ async def start_tracing(
if path:
self._cr_tracing_path = str(path)
params["path"] = str(path)
await self._channel.send("startTracing", params)
await self._channel.send("startTracing", None, params)

async def stop_tracing(self) -> bytes:
artifact = cast(Artifact, from_channel(await self._channel.send("stopTracing")))
artifact = cast(
Artifact, from_channel(await self._channel.send("stopTracing", None))
)
buffer = await artifact.read_info_buffer()
await artifact.delete()
if self._cr_tracing_path:
Expand Down
35 changes: 18 additions & 17 deletions playwright/_impl/_browser_context.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -330,17 +330,17 @@ async def _initialize_har_from_options(
async def new_page(self) -> Page:
if self._owner_page:
raise Error("Please use browser.new_context()")
return from_channel(await self._channel.send("newPage"))
return from_channel(await self._channel.send("newPage", None))

async def cookies(self, urls: Union[str, Sequence[str]] = None) -> List[Cookie]:
if urls is None:
urls = []
if isinstance(urls, str):
urls = [urls]
return await self._channel.send("cookies", dict(urls=urls))
return await self._channel.send("cookies", None, dict(urls=urls))

async def add_cookies(self, cookies: Sequence[SetCookieParam]) -> None:
await self._channel.send("addCookies", dict(cookies=cookies))
await self._channel.send("addCookies", None, dict(cookies=cookies))

async def clear_cookies(
self,
Expand All@@ -350,6 +350,7 @@ async def clear_cookies(
) -> None:
await self._channel.send(
"clearCookies",
None,
{
"name": name if isinstance(name, str) else None,
"nameRegexSource": name.pattern if isinstance(name, Pattern) else None,
Expand All@@ -374,21 +375,21 @@ async def clear_cookies(
async def grant_permissions(
self, permissions: Sequence[str], origin: str = None
) -> None:
await self._channel.send("grantPermissions", locals_to_params(locals()))
await self._channel.send("grantPermissions", None, locals_to_params(locals()))

async def clear_permissions(self) -> None:
await self._channel.send("clearPermissions")
await self._channel.send("clearPermissions", None)

async def set_geolocation(self, geolocation: Geolocation = None) -> None:
await self._channel.send("setGeolocation", locals_to_params(locals()))
await self._channel.send("setGeolocation", None, locals_to_params(locals()))

async def set_extra_http_headers(self, headers: Dict[str, str]) -> None:
await self._channel.send(
"setExtraHTTPHeaders", dict(headers=serialize_headers(headers))
"setExtraHTTPHeaders", None, dict(headers=serialize_headers(headers))
)

async def set_offline(self, offline: bool) -> None:
await self._channel.send("setOffline", dict(offline=offline))
await self._channel.send("setOffline", None, dict(offline=offline))

async def add_init_script(
self, script: str = None, path: Union[str, Path] = None
Expand All@@ -397,7 +398,7 @@ async def add_init_script(
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))
await self._channel.send("addInitScript", None, dict(source=script))

async def expose_binding(
self, name: str, callback: Callable, handle: bool = None
Expand All@@ -411,7 +412,7 @@ async def expose_binding(
raise Error(f'Function "{name}" has been already registered')
self._bindings[name] = callback
await self._channel.send(
"exposeBinding", dict(name=name, needsHandle=handle or False)
"exposeBinding", None, dict(name=name, needsHandle=handle or False)
)

async def expose_function(self, name: str, callback: Callable) -> None:
Expand DownExpand Up@@ -499,7 +500,7 @@ async def _record_into_har(
}
if page:
params["page"] = page._channel
har_id = await self._channel.send("harStart", params)
har_id = await self._channel.send("harStart", None, params)
self._har_recorders[har_id] = {
"path": str(har),
"content": update_content,
Expand DownExpand Up@@ -535,15 +536,15 @@ async def route_from_har(
async def _update_interception_patterns(self) -> None:
patterns = RouteHandler.prepare_interception_patterns(self._routes)
await self._channel.send(
"setNetworkInterceptionPatterns", {"patterns": patterns}
"setNetworkInterceptionPatterns", None, {"patterns": patterns}
)

async def _update_web_socket_interception_patterns(self) -> None:
patterns = WebSocketRouteHandler.prepare_interception_patterns(
self._web_socket_routes
)
await self._channel.send(
"setWebSocketInterceptionPatterns", {"patterns": patterns}
"setWebSocketInterceptionPatterns", None, {"patterns": patterns}
)

def expect_event(
Expand DownExpand Up@@ -596,7 +597,7 @@ async def _inner_close() -> None:
har = cast(
Artifact,
from_channel(
await self._channel.send("harExport", {"harId": har_id})
await self._channel.send("harExport", None, {"harId": har_id})
),
)
# Server side will compress artifact if content is attach or if file is .zip.
Expand All@@ -615,14 +616,14 @@ async def _inner_close() -> None:
await har.delete()

await self._channel._connection.wrap_api_call(_inner_close, True)
await self._channel.send("close", {"reason": reason})
await self._channel.send("close", None, {"reason": reason})
await self._closed_future

async def storage_state(
self, path: Union[str, Path] = None, indexedDB: bool = None
) -> StorageState:
result = await self._channel.send_return_as_dict(
"storageState", {"indexedDB": indexedDB}
"storageState", None, {"indexedDB": indexedDB}
)
if path:
await async_writefile(path, json.dumps(result))
Expand DownExpand Up@@ -749,7 +750,7 @@ async def new_cdp_session(self, page: Union[Page, Frame]) -> CDPSession:
params["frame"] = page._channel
else:
raise Error("page: expected Page or Frame")
return from_channel(await self._channel.send("newCDPSession", params))
return from_channel(await self._channel.send("newCDPSession", None, params))

@property
def tracing(self) -> Tracing:
Expand Down
16 changes: 11 additions & 5 deletions playwright/_impl/_browser_type.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,12 @@ async def launch(
params = locals_to_params(locals())
normalize_launch_params(params)
browser = cast(
Browser, from_channel(await self._channel.send("launch", params))
Browser,
from_channel(
await self._channel.send(
"launch", TimeoutSettings.launch_timeout, params
)
),
)
browser._connect_to_browser_type(
self, str(tracesDir) if tracesDir is not None else None
Expand DownExpand Up@@ -159,7 +164,7 @@ async def launch_persistent_context(
await self._prepare_browser_context_params(params)
normalize_launch_params(params)
result = await self._channel.send_return_as_dict(
"launchPersistentContext", params
"launchPersistentContext", TimeoutSettings.launch_timeout, params
)
browser = cast(
Browser,
Expand DownExpand Up@@ -197,10 +202,11 @@ async def connect_over_cdp(
headers: Dict[str, str] = None,
) -> Browser:
params = locals_to_params(locals())
params["timeout"] = TimeoutSettings.launch_timeout(timeout)
if params.get("headers"):
params["headers"] = serialize_headers(params["headers"])
response = await self._channel.send_return_as_dict("connectOverCDP", params)
response = await self._channel.send_return_as_dict(
"connectOverCDP", TimeoutSettings.launch_timeout, params
)
browser = cast(Browser, from_channel(response["browser"]))
browser._connect_to_browser_type(self, None)

Expand All@@ -222,6 +228,7 @@ async def connect(
pipe_channel = (
await local_utils._channel.send_return_as_dict(
"connect",
None,
{
"wsEndpoint": wsEndpoint,
"headers": headers,
Expand DownExpand Up@@ -355,4 +362,3 @@ def normalize_launch_params(params: Dict) -> None:
params["downloadsPath"] = str(Path(params["downloadsPath"]))
if "tracesDir" in params:
params["tracesDir"] = str(Path(params["tracesDir"]))
params["timeout"] = TimeoutSettings.launch_timeout(params.get("timeout"))
7 changes: 5 additions & 2 deletions playwright/_impl/_cdp_session.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,7 +29,10 @@ def _on_event(self, params: Any) -> None:
self.emit(params["method"], params.get("params"))

async def send(self, method: str, params: Dict = None) -> Dict:
return await self._channel.send("send", locals_to_params(locals()))
return await self._channel.send("send", None, locals_to_params(locals()))

async def detach(self) -> None:
await self._channel.send("detach")
await self._channel.send(
"detach",
None,
)
32 changes: 25 additions & 7 deletions playwright/_impl/_clock.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,46 +27,64 @@ def __init__(self, browser_context: "BrowserContext") -> None:

async def install(self, time: Union[float, str, datetime.datetime] = None) -> None:
await self._browser_context._channel.send(
"clockInstall", parse_time(time) if time is not None else {}
"clockInstall",
None,
parse_time(time) if time is not None else {},
)

async def fast_forward(
self,
ticks: Union[int, str],
) -> None:
await self._browser_context._channel.send(
"clockFastForward", parse_ticks(ticks)
"clockFastForward",
None,
parse_ticks(ticks),
)

async def pause_at(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send("clockPauseAt", parse_time(time))
await self._browser_context._channel.send(
"clockPauseAt",
None,
parse_time(time),
)

async def resume(
self,
) -> None:
await self._browser_context._channel.send("clockResume")
await self._browser_context._channel.send("clockResume", None)

async def run_for(
self,
ticks: Union[int, str],
) -> None:
await self._browser_context._channel.send("clockRunFor", parse_ticks(ticks))
await self._browser_context._channel.send(
"clockRunFor",
None,
parse_ticks(ticks),
)

async def set_fixed_time(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send("clockSetFixedTime", parse_time(time))
await self._browser_context._channel.send(
"clockSetFixedTime",
None,
parse_time(time),
)

async def set_system_time(
self,
time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send(
"clockSetSystemTime", parse_time(time)
"clockSetSystemTime",
None,
parse_time(time),
)


Expand Down
Loading