async def add_style_tag(self, url: str = None, path: Union[str, Path] = None, content: str = None) -> ElementHandle: params = locals_to_params(locals()) if path: params["content"] = ((await async_readfile(path)).decode() + "\n/*# sourceURL=" + str(Path(path)) + "*/") del params["path"] return from_channel(await self._channel.send("addStyleTag", params))
async def evaluate_handle(self, expression: str, arg: Serializable = None) -> "JSHandle": return from_channel(await self._channel.send( "evaluateExpressionHandle", dict( expression=expression, arg=serialize_argument(arg), ), ))
async def call(self, func: Callable) -> None: try: frame = from_channel(self._initializer["frame"]) source = dict(context=frame._page.context, page=frame._page, frame=frame) if self._initializer.get("handle"): result = func(source, from_channel(self._initializer["handle"])) else: func_args = list(map(parse_result, self._initializer["args"])) result = func(source, *func_args) if inspect.iscoroutine(result): result = await result await self._channel.send("resolve", dict(result=serialize_argument(result))) except Exception as e: tb = sys.exc_info()[2] asyncio.create_task( self._channel.send( "reject", dict(error=dict(error=serialize_error(e, tb))) ) )
async def stop(self, path: Union[pathlib.Path, str] = None) -> None: await self._channel.send("tracingStop") if path: artifact = cast( Artifact, from_channel(await self._channel.send("tracingExport"))) if self._context._browser: artifact._is_remote = self._context._browser._is_remote await artifact.save_as(path) await artifact.delete()
async def wait_for_function( self, expression: str, arg: Serializable = None, timeout: float = None, polling: Union[float, Literal["raf"]] = None, ) -> JSHandle: params = locals_to_params(locals()) params["arg"] = serialize_argument(arg) return from_channel(await self._channel.send("waitForFunction", params))
async def addStyleTag(self, url: str = None, path: Union[str, Path] = None, content: str = None) -> ElementHandle: params = locals_to_params(locals()) if path: with open(path, "r") as file: params["content"] = (file.read() + "\n/*# sourceURL=" + str(Path(path)) + "*/") del params["path"] return from_channel(await self._channel.send("addStyleTag", params))
async def close(self) -> None: try: if self._options.get("recordHar"): har = cast(Artifact, from_channel(await self._channel.send("harExport"))) await har.save_as( cast(Dict[str, str], self._options["recordHar"])["path"]) await har.delete() await self._channel.send("close") await self._closed_future except Exception as e: if not is_safe_close_error(e): raise e
def __init__(self, parent: ChannelOwner, type: str, guid: str, initializer: Dict) -> None: super().__init__(parent, type, guid, initializer) self.request = APIRequest(self) self.chromium = from_channel(initializer["chromium"]) self.chromium._playwright = self self.firefox = from_channel(initializer["firefox"]) self.firefox._playwright = self self.webkit = from_channel(initializer["webkit"]) self.webkit._playwright = self self.selectors = Selectors(self._loop) selectors_owner: SelectorsOwner = from_channel( initializer["selectors"]) self.selectors._add_channel(selectors_owner) self._connection.on( "close", lambda: self.selectors._remove_channel(selectors_owner)) self.devices = {} self.devices = { device["name"]: parse_device_descriptor(device["descriptor"]) for device in initializer["deviceDescriptors"] } self._utils: LocalUtils = from_channel(initializer["utils"])
async def wait_for_function( self, expression: str, arg: Serializable = None, force_expr: bool = None, timeout: float = None, polling: Union[float, Literal["raf"]] = None, ) -> JSHandle: if not is_function_body(expression): force_expr = True params = locals_to_params(locals()) params["isFunction"] = not (force_expr) params["arg"] = serialize_argument(arg) return from_channel(await self._channel.send("waitForFunction", params))
async def new_context( self, viewport: ViewportSize = None, screen: ViewportSize = None, noViewport: bool = None, ignoreHTTPSErrors: bool = None, javaScriptEnabled: bool = None, bypassCSP: bool = None, userAgent: str = None, locale: str = None, timezoneId: str = None, geolocation: Geolocation = None, permissions: List[str] = None, extraHTTPHeaders: Dict[str, str] = None, offline: bool = None, httpCredentials: HttpCredentials = None, deviceScaleFactor: float = None, isMobile: bool = None, hasTouch: bool = None, colorScheme: ColorScheme = None, reducedMotion: ReducedMotion = None, forcedColors: ForcedColors = None, acceptDownloads: bool = None, defaultBrowserType: str = None, proxy: ProxySettings = None, recordHarPath: Union[Path, str] = None, recordHarOmitContent: bool = None, recordVideoDir: Union[Path, str] = None, recordVideoSize: ViewportSize = None, storageState: Union[StorageState, str, Path] = None, baseURL: str = None, strictSelectors: bool = None, serviceWorkers: ServiceWorkersPolicy = None, recordHarUrlFilter: Union[Pattern[str], str] = None, recordHarMode: HarMode = None, recordHarContent: HarContentPolicy = None, ) -> BrowserContext: params = locals_to_params(locals()) await normalize_context_params(self._connection._is_sync, params) channel = await self._channel.send("newContext", params) context = cast(BrowserContext, from_channel(channel)) self._contexts.append(context) context._browser = self context._options = params context._set_browser_type(self._browser_type) return context
async def connect_over_cdp( self, endpointURL: str, timeout: float = None, slow_mo: float = None ) -> Browser: params = locals_to_params(locals()) params["sdkLanguage"] = ( "python" if self._connection._is_sync else "python-async" ) response = await self._channel.send_return_as_dict("connectOverCDP", params) browser = cast(Browser, from_channel(response["browser"])) browser._is_remote = True default_context = cast( Optional[BrowserContext], from_nullable_channel(response.get("defaultContext")), ) if default_context: browser._contexts.append(default_context) default_context._browser = browser return browser
async def convert_input_files( files: Union[str, Path, FilePayload, List[Union[str, Path]], List[FilePayload]], context: "BrowserContext", ) -> InputFilesList: file_list = files if isinstance(files, list) else [files] has_large_buffer = any([ len(f.get("buffer", "")) > SIZE_LIMIT_IN_BYTES for f in file_list if not isinstance(f, (str, Path)) ]) if has_large_buffer: raise Error( "Cannot set buffer larger than 50Mb, please write it to a file and pass its path instead." ) has_large_file = any([ os.stat(f).st_size > SIZE_LIMIT_IN_BYTES for f in file_list if isinstance(f, (str, Path)) ]) if has_large_file: if context._channel._connection.is_remote: streams = [] for file in file_list: assert isinstance(file, (str, Path)) stream: WritableStream = from_channel( await context._channel.send("createTempFile", {"name": os.path.basename(file)})) await stream.copy(file) streams.append(stream._channel) return InputFilesList(streams=streams, localPaths=None, files=None) local_paths = [] for p in file_list: assert isinstance(p, (str, Path)) local_paths.append(str(Path(p).absolute().resolve())) return InputFilesList(streams=None, localPaths=local_paths, files=None) return InputFilesList(streams=None, localPaths=None, files=await _normalize_file_payloads(files))
async def connect( self, ws_endpoint: str, timeout: float = None, slow_mo: float = None, headers: Dict[str, str] = None, ) -> Browser: transport = WebSocketTransport(ws_endpoint, timeout, headers) connection = Connection( self._connection._dispatcher_fiber, self._connection._object_factory, transport, ) await connection._transport.start() connection._is_sync = self._connection._is_sync connection._loop = self._connection._loop connection._loop.create_task(connection.run()) obj = asyncio.create_task( connection.wait_for_object_with_known_name("Playwright")) done, pending = await asyncio.wait( { obj, connection._transport.on_error_future, # type: ignore }, return_when=asyncio.FIRST_COMPLETED, ) if not obj.done(): obj.cancel() playwright = next(iter(done)).result() self._connection._child_ws_connections.append(connection) pre_launched_browser = playwright._initializer.get( "preLaunchedBrowser") assert pre_launched_browser browser = cast(Browser, from_channel(pre_launched_browser)) browser._is_remote = True browser._is_connected_over_websocket = True transport.once("close", browser._on_close) return browser
async def connect_over_cdp( self, endpointURL: str, timeout: float = None, slow_mo: float = None, headers: Dict[str, str] = None, ) -> Browser: params = locals_to_params(locals()) response = await self._channel.send_return_as_dict( "connectOverCDP", params) browser = cast(Browser, from_channel(response["browser"])) browser._local_utils = self._playwright._utils default_context = cast( Optional[BrowserContext], from_nullable_channel(response.get("defaultContext")), ) if default_context: browser._contexts.append(default_context) default_context._browser = browser return browser
async def new_context( self, baseURL: str = None, extraHTTPHeaders: Dict[str, str] = None, httpCredentials: HttpCredentials = None, ignoreHTTPSErrors: bool = None, proxy: ProxySettings = None, userAgent: str = None, timeout: float = None, storageState: Union[StorageState, str, Path] = None, ) -> "APIRequestContext": params = locals_to_params(locals()) if "storageState" in params: storage_state = params["storageState"] if not isinstance(storage_state, dict) and storage_state: params["storageState"] = json.loads( (await async_readfile(storage_state)).decode()) if "extraHTTPHeaders" in params: params["extraHTTPHeaders"] = serialize_headers( params["extraHTTPHeaders"]) return from_channel(await self.playwright._channel.send( "newRequest", params))
async def wait_for_navigation( self, url: URLMatch = None, waitUntil: DocumentLoadState = None, timeout: float = None, ) -> Optional[Response]: if not waitUntil: waitUntil = "load" if timeout is None: timeout = self._page._timeout_settings.navigation_timeout() deadline = monotonic_time() + timeout wait_helper = self._setup_navigation_wait_helper(timeout) matcher = URLMatcher(url) if url else None def predicate(event: Any) -> bool: # Any failed navigation results in a rejection. if event.get("error"): return True return not matcher or matcher.matches(event["url"]) event = await wait_helper.wait_for_event( self._event_emitter, "navigated", predicate=predicate, ) if "error" in event: raise Error(event["error"]) if waitUntil not in self._load_states: t = deadline - monotonic_time() if t > 0: await self.wait_for_load_state(state=waitUntil, timeout=t) if "newDocument" in event and "request" in event["newDocument"]: request = from_channel(event["newDocument"]["request"]) return await request.response() return None
async def launch( self, executablePath: Union[str, Path] = None, channel: str = None, args: List[str] = None, ignoreDefaultArgs: Union[bool, List[str]] = None, handleSIGINT: bool = None, handleSIGTERM: bool = None, handleSIGHUP: bool = None, timeout: float = None, env: Env = None, headless: bool = None, devtools: bool = None, proxy: ProxySettings = None, downloadsPath: Union[str, Path] = None, slowMo: float = None, tracesDir: Union[pathlib.Path, str] = None, chromiumSandbox: bool = None, firefoxUserPrefs: Dict[str, Union[str, float, bool]] = None, ) -> Browser: params = locals_to_params(locals()) normalize_launch_params(params) return from_channel(await self._channel.send("launch", params))
async def new_context( self, viewport: ViewportSize = None, noViewport: bool = None, ignoreHTTPSErrors: bool = None, javaScriptEnabled: bool = None, bypassCSP: bool = None, userAgent: str = None, locale: str = None, timezoneId: str = None, geolocation: Geolocation = None, permissions: List[str] = None, extraHTTPHeaders: Dict[str, str] = None, offline: bool = None, httpCredentials: HttpCredentials = None, deviceScaleFactor: float = None, isMobile: bool = None, hasTouch: bool = None, colorScheme: ColorScheme = None, acceptDownloads: bool = None, defaultBrowserType: str = None, proxy: ProxySettings = None, recordHarPath: Union[Path, str] = None, recordHarOmitContent: bool = None, recordVideoDir: Union[Path, str] = None, recordVideoSize: ViewportSize = None, storageState: Union[StorageState, str, Path] = None, ) -> BrowserContext: params = locals_to_params(locals()) normalize_context_params(self._connection._is_sync, params) channel = await self._channel.send("newContext", params) context = from_channel(channel) self._contexts.append(context) context._browser = self context._options = params return context
async def connect( self, ws_endpoint: str, timeout: float = None, slow_mo: float = None ) -> Browser: transport = WebSocketTransport(ws_endpoint, timeout) connection = Connection( self._connection._dispatcher_fiber, self._connection._object_factory, transport, ) connection._is_sync = self._connection._is_sync connection._loop = self._connection._loop connection._loop.create_task(connection.run()) self._connection._child_ws_connections.append(connection) playwright = await connection.wait_for_object_with_known_name("Playwright") pre_launched_browser = playwright._initializer.get("preLaunchedBrowser") assert pre_launched_browser browser = cast(Browser, from_channel(pre_launched_browser)) browser._is_remote = True browser._is_connected_over_websocket = True transport.once("close", browser._on_close) return browser