Ejemplo n.º 1
0
 async def wait_for_load_state(self,
                               state: DocumentLoadState = None,
                               timeout: float = None) -> None:
     if not state:
         state = "load"
     if state not in ("load", "domcontentloaded", "networkidle"):
         raise Error(
             "state: expected one of (load|domcontentloaded|networkidle)")
     if state in self._load_states:
         return
     wait_helper = self._setup_navigation_wait_helper(timeout)
     wait_helper.wait_for_event(self._event_emitter, "loadstate",
                                lambda s: s == state)
     await wait_helper.result()
Ejemplo n.º 2
0
 def expect_event(
     self,
     event: str,
     predicate: Callable = None,
     timeout: float = None,
 ) -> EventContextManagerImpl:
     if timeout is None:
         timeout = cast(Any, self._parent)._timeout_settings.timeout()
     wait_helper = WaitHelper(self, f"web_socket.expect_event({event})")
     wait_helper.reject_on_timeout(
         cast(float, timeout),
         f'Timeout {timeout}ms exceeded while waiting for event "{event}"',
     )
     if event != WebSocket.Events.Close:
         wait_helper.reject_on_event(self, WebSocket.Events.Close,
                                     Error("Socket closed"))
     if event != WebSocket.Events.Error:
         wait_helper.reject_on_event(self, WebSocket.Events.Error,
                                     Error("Socket error"))
     wait_helper.reject_on_event(self._parent, "close",
                                 Error("Page closed"))
     wait_helper.wait_for_event(self, event, predicate)
     return EventContextManagerImpl(wait_helper.result())
Ejemplo n.º 3
0
 def _expect_event(
     self,
     event: str,
     predicate: Callable = None,
     timeout: float = None,
     log_line: str = None,
 ) -> EventContextManagerImpl:
     if timeout is None:
         timeout = self._timeout_settings.timeout()
     wait_helper = WaitHelper(self, f"page.expect_event({event})")
     wait_helper.reject_on_timeout(
         timeout,
         f'Timeout {timeout}ms exceeded while waiting for event "{event}"')
     if log_line:
         wait_helper.log(log_line)
     if event != Page.Events.Crash:
         wait_helper.reject_on_event(self, Page.Events.Crash,
                                     Error("Page crashed"))
     if event != Page.Events.Close:
         wait_helper.reject_on_event(self, Page.Events.Close,
                                     Error("Page closed"))
     wait_helper.wait_for_event(self, event, predicate)
     return EventContextManagerImpl(wait_helper.result())
Ejemplo n.º 4
0
 async def waitForEvent(
     self, event: str, predicate: Callable[[Any], bool] = None, timeout: int = None
 ) -> Any:
     if timeout is None:
         timeout = self._timeout_settings.timeout()
     wait_helper = WaitHelper(self._loop)
     wait_helper.reject_on_timeout(
         timeout, f'Timeout while waiting for event "{event}"'
     )
     if event != BrowserContext.Events.Close:
         wait_helper.reject_on_event(
             self, BrowserContext.Events.Close, Error("Context closed")
         )
     return await wait_helper.wait_for_event(self, event, predicate)
    def __enter__(self) -> SyncPlaywright:
        try:
            self._loop = asyncio.get_running_loop()
        except RuntimeError:
            self._loop = asyncio.new_event_loop()
            self._own_loop = True
        if self._loop.is_running():
            raise Error(
                """It looks like you are using Playwright Sync API inside the asyncio loop.
Please use the Async API instead."""
            )

        # In Python 3.7, asyncio.Process.wait() hangs because it does not use ThreadedChildWatcher
        # which is used in Python 3.8+. This is unix specific and also takes care about
        # cleaning up zombie processes. See https://bugs.python.org/issue35621
        if (
            sys.version_info[0] == 3
            and sys.version_info[1] == 7
            and sys.platform != "win32"
            and isinstance(asyncio.get_child_watcher(), asyncio.SafeChildWatcher)
        ):
            from ._py37ThreadedChildWatcher import ThreadedChildWatcher  # type: ignore

            self._watcher = ThreadedChildWatcher()
            asyncio.set_child_watcher(self._watcher)  # type: ignore

        def greenlet_main() -> None:
            self._loop.run_until_complete(self._connection.run_as_sync())

        dispatcher_fiber = greenlet(greenlet_main)
        self._connection = Connection(
            dispatcher_fiber,
            create_remote_object,
            PipeTransport(self._loop, compute_driver_executable()),
            self._loop,
        )

        g_self = greenlet.getcurrent()

        def callback_wrapper(playwright_impl: Playwright) -> None:
            self._playwright = SyncPlaywright(playwright_impl)
            g_self.switch()

        self._connection.call_on_object_with_known_name("Playwright", callback_wrapper)

        dispatcher_fiber.switch()
        playwright = self._playwright
        playwright.stop = self.__exit__  # type: ignore
        return playwright
Ejemplo n.º 6
0
 async def register(
     self,
     name: str,
     script: str = None,
     path: Union[str, Path] = None,
     contentScript: bool = None,
 ) -> None:
     if not script and not path:
         raise Error("Either source or path should be specified")
     if path:
         script = (await async_readfile(path)).decode()
     params: Dict[str, Any] = dict(name=name, source=script)
     if contentScript:
         params["contentScript"] = True
     await self._channel.send("register", params)
Ejemplo n.º 7
0
 async def run(self) -> None:
     while not self._stopped:
         try:
             message = await self._connection.recv()
             if self.slow_mo is not None:
                 await asyncio.sleep(self.slow_mo / 1000)
             if self._stopped:
                 self.on_error_future.set_exception(
                     Error("Playwright connection closed"))
                 break
             obj = self.deserialize_message(message)
             self.on_message(obj)
         except (
                 websockets.exceptions.ConnectionClosed,
                 websockets.exceptions.ConnectionClosedError,
         ):
             if not self._stopped:
                 self.emit("close")
             self.on_error_future.set_exception(
                 Error("Playwright connection closed"))
             break
         except Exception as exc:
             self.on_error_future.set_exception(exc)
             break
Ejemplo n.º 8
0
    async def run(self) -> None:
        await self.start()
        self._stopped_future: asyncio.Future = asyncio.Future()

        try:
            self._proc = proc = await asyncio.create_subprocess_exec(
                str(self._driver_executable),
                "run-driver",
                stdin=asyncio.subprocess.PIPE,
                stdout=asyncio.subprocess.PIPE,
                stderr=_get_stderr_fileno(),
                limit=32768,
            )
        except FileNotFoundError:
            self.on_error_future.set_exception(
                Error(
                    "playwright's driver is not found, You can read the contributing guide "
                    "for some guidance on how to get everything setup for working on the code "
                    "https://github.com/microsoft/playwright-python/blob/master/CONTRIBUTING.md"
                ))
            return

        assert proc.stdout
        assert proc.stdin
        self._output = proc.stdin

        while not self._stopped:
            try:
                buffer = await proc.stdout.readexactly(4)
                length = int.from_bytes(buffer,
                                        byteorder="little",
                                        signed=False)
                buffer = bytes(0)
                while length:
                    to_read = min(length, 32768)
                    data = await proc.stdout.readexactly(to_read)
                    length -= to_read
                    if len(buffer):
                        buffer = buffer + data
                    else:
                        buffer = data

                obj = self.deserialize_message(buffer)
                self.on_message(obj)
            except asyncio.IncompleteReadError:
                break
            await asyncio.sleep(0)
        self._stopped_future.set_result(None)
 def to_impl(self, obj: Any) -> Any:
     try:
         if not obj:
             return obj
         if isinstance(obj, dict):
             return {
                 name: self.to_impl(value)
                 for name, value in obj.items()
             }
         if isinstance(obj, list):
             return [self.to_impl(item) for item in obj]
         if isinstance(obj, ImplWrapper):
             return obj._impl_obj
         return obj
     except RecursionError:
         raise Error("Maximum argument depth exceeded")
Ejemplo n.º 10
0
 async def register(
     self,
     name: str,
     source: str = None,
     path: Union[str, Path] = None,
     contentScript: bool = None,
 ) -> None:
     if not source and not path:
         raise Error("Either source or path should be specified")
     if path:
         with open(path, "r") as file:
             source = file.read()
     params: Dict = dict(name=name, source=source)
     if contentScript:
         params["contentScript"] = True
     await self._channel.send("register", params)
Ejemplo n.º 11
0
 def expect_event(
     self,
     event: str,
     predicate: Callable = None,
     timeout: float = None,
 ) -> EventContextManagerImpl:
     if timeout is None:
         timeout = self._timeout_settings.timeout()
     wait_helper = WaitHelper(self._loop)
     wait_helper.reject_on_timeout(
         timeout, f'Timeout while waiting for event "{event}"')
     if event != BrowserContext.Events.Close:
         wait_helper.reject_on_event(self, BrowserContext.Events.Close,
                                     Error("Context closed"))
     wait_helper.wait_for_event(self, event, predicate)
     return EventContextManagerImpl(wait_helper.result())
Ejemplo n.º 12
0
        def greenlet_main() -> None:
            loop = None
            own_loop = None
            try:
                loop = asyncio.get_running_loop()
            except RuntimeError:
                loop = asyncio.new_event_loop()
                own_loop = loop

            if loop.is_running():
                raise Error("Can only run one Playwright at a time.")

            loop.run_until_complete(self._connection.run_as_sync())

            if own_loop:
                loop.run_until_complete(loop.shutdown_asyncgens())
                loop.close()
Ejemplo n.º 13
0
    async def connect(
        self,
        ws_endpoint: str,
        timeout: float = None,
        slow_mo: float = None,
        headers: Dict[str, str] = None,
    ) -> Browser:
        if timeout is None:
            timeout = 30000

        transport = WebSocketTransport(self._connection._loop, ws_endpoint,
                                       headers, slow_mo)
        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())
        future = connection._loop.create_task(
            connection.wait_for_object_with_known_name("Playwright"))
        timeout_future = throw_on_timeout(timeout,
                                          Error("Connection timed out"))
        done, pending = await asyncio.wait(
            {transport.on_error_future, future, timeout_future},
            return_when=asyncio.FIRST_COMPLETED,
        )
        if not future.done():
            future.cancel()
        if not timeout_future.done():
            timeout_future.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
Ejemplo n.º 14
0
        def greenlet_main() -> None:
            loop = None
            own_loop = None
            try:
                loop = asyncio.get_running_loop()
            except RuntimeError:
                loop = asyncio.new_event_loop()
                own_loop = loop

            if loop.is_running():
                raise Error(
                    """It looks like you are using Playwright Sync API inside the asyncio loop.
Please use the Async API instead.""")

            loop.run_until_complete(self._connection.run_as_sync())

            if own_loop:
                loop.run_until_complete(loop.shutdown_asyncgens())
                loop.close()
Ejemplo n.º 15
0
    def __enter__(self) -> SyncPlaywright:
        loop: asyncio.AbstractEventLoop
        own_loop = None
        try:
            loop = asyncio.get_running_loop()
        except RuntimeError:
            loop = asyncio.new_event_loop()
            own_loop = loop
        if loop.is_running():
            raise Error(
                """It looks like you are using Playwright Sync API inside the asyncio loop.
Please use the Async API instead.""")

        def greenlet_main() -> None:
            loop.run_until_complete(self._connection.run_as_sync())

            if own_loop:
                loop.run_until_complete(loop.shutdown_asyncgens())
                loop.close()

        global dispatcher_fiber
        dispatcher_fiber = greenlet(greenlet_main)
        self._connection = Connection(
            dispatcher_fiber,
            create_remote_object,
            PipeTransport(loop, compute_driver_executable()),
            loop,
        )

        g_self = greenlet.getcurrent()

        def callback_wrapper(playwright_impl: Playwright) -> None:
            self._playwright = SyncPlaywright(playwright_impl)
            g_self.switch()

        self._connection.call_on_object_with_known_name(
            "Playwright", callback_wrapper)

        dispatcher_fiber.switch()
        playwright = self._playwright
        playwright.stop = self.__exit__  # type: ignore
        return playwright
Ejemplo n.º 16
0
def serialize_value(value: Any, handles: List[JSHandle], depth: int) -> Any:
    if isinstance(value, JSHandle):
        h = len(handles)
        handles.append(value._channel)
        return dict(h=h)
    if depth > 100:
        raise Error("Maximum argument depth exceeded")
    if value is None:
        return dict(v="undefined")
    if isinstance(value, float):
        if value == float("inf"):
            return dict(v="Infinity")
        if value == float("-inf"):
            return dict(v="-Infinity")
        if value == float("-0"):
            return dict(v="-0")
        if math.isnan(value):
            return dict(v="NaN")
    if isinstance(value, datetime):
        return dict(d=value.isoformat() + "Z")
    if isinstance(value, bool):
        return {"b": value}
    if isinstance(value, (int, float)):
        return {"n": value}
    if isinstance(value, str):
        return {"s": value}

    if isinstance(value, list):
        result = list(
            map(lambda a: serialize_value(a, handles, depth + 1), value))
        return dict(a=result)

    if isinstance(value, dict):
        result = []  # type: ignore
        for name in value:
            result.append({
                "k": name,
                "v": serialize_value(value[name], handles, depth + 1)
            })
        return dict(o=result)
    return dict(v="undefined")
Ejemplo n.º 17
0
    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
Ejemplo n.º 18
0
    async def _wait_for_load_state_impl(
        self, state: DocumentLoadState = None, timeout: float = None
    ) -> None:
        if not state:
            state = "load"
        if state not in ("load", "domcontentloaded", "networkidle", "commit"):
            raise Error(
                "state: expected one of (load|domcontentloaded|networkidle|commit)"
            )
        if state in self._load_states:
            return
        wait_helper = self._setup_navigation_wait_helper("wait_for_load_state", timeout)

        def handle_load_state_event(actual_state: str) -> bool:
            wait_helper.log(f'"{actual_state}" event fired')
            return actual_state == state

        wait_helper.wait_for_event(
            self._event_emitter,
            "loadstate",
            handle_load_state_event,
        )
        await wait_helper.result()
Ejemplo n.º 19
0
 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"))
Ejemplo n.º 20
0
 def send(self, message: Dict) -> None:
     if self._stopped or (hasattr(self, "_connection")
                          and self._connection.closed):
         raise Error("Playwright connection closed")
     data = self.serialize_message(message)
     self._loop.create_task(self._connection.send(data))
Ejemplo n.º 21
0
 async def sizes(self) -> RequestSizes:
     response = await self.response()
     if not response:
         raise Error("Unable to fetch sizes for failed request")
     return await response._channel.send("sizes")
Ejemplo n.º 22
0
 def _check_not_handled(self) -> None:
     if not self._handling_future:
         raise Error("Route is already handled!")