Beispiel #1
0
 async def path(self) -> pathlib.Path:
     if self._page._connection.is_remote:
         raise Error(
             "Path is not available when using browserType.connect(). Use save_as() to save a local copy."
         )
     artifact = await self._artifact_future
     if not artifact:
         raise Error("Page did not produce any video frames")
     return artifact.absolute_path
Beispiel #2
0
 async def body(self) -> bytes:
     try:
         result = await self._request._channel.send_return_as_dict(
             "fetchResponseBody",
             {
                 "fetchUid": self._fetch_uid(),
             },
         )
         if result is None:
             raise Error("Response has been disposed")
         return base64.b64decode(result["binary"])
     except Error as exc:
         if is_safe_close_error(exc):
             raise Error("Response has been disposed")
         raise exc
Beispiel #3
0
    def __init__(
        self,
        frame: "Frame",
        selector: str,
        has_text: Union[str, Pattern[str]] = None,
        has: "Locator" = None,
    ) -> None:
        self._frame = frame
        self._selector = selector
        self._loop = frame._loop
        self._dispatcher_fiber = frame._connection._dispatcher_fiber

        if has_text:
            if isinstance(has_text, Pattern):
                js_regex = f"/{has_text.pattern}/{escape_regex_flags(has_text)}"
                self._selector += (
                    f' >> has={json.dumps("text=" + js_regex, ensure_ascii=False)}'
                )
            else:
                escaped = escape_with_quotes(has_text, '"')
                self._selector += f" >> :scope:has-text({escaped})"

        if has:
            if has._frame != frame:
                raise Error(
                    'Inner "has" locator must belong to the same frame.')
            self._selector += " >> has=" + json.dumps(has._selector,
                                                      ensure_ascii=False)
Beispiel #4
0
    def __init__(
        self,
        frame: "Frame",
        selector: str,
        has_text: Union[str, Pattern] = None,
        has: "Locator" = None,
    ) -> None:
        self._frame = frame
        self._selector = selector
        self._loop = frame._loop
        self._dispatcher_fiber = frame._connection._dispatcher_fiber

        if has_text:
            if isinstance(has_text, Pattern):
                pattern = escape_with_quotes(has_text.pattern, '"')
                flags = escape_regex_flags(has_text)
                self._selector += f' >> :scope:text-matches({pattern}, "{flags}")'
            else:
                escaped = escape_with_quotes(has_text, '"')
                self._selector += f" >> :scope:has-text({escaped})"

        if has:
            if has._frame != frame:
                raise Error(
                    'Inner "has" locator must belong to the same frame.')
            self._selector += " >> has=" + json.dumps(has._selector)
Beispiel #5
0
 async def _with_element(
     self,
     task: Callable[[ElementHandle, float], Awaitable[T]],
     timeout: float = None,
 ) -> T:
     timeout = self._frame.page._timeout_settings.timeout(timeout)
     deadline = (monotonic_time() + timeout) if timeout else 0
     handle = await self.element_handle(timeout=timeout)
     if not handle:
         raise Error(f"Could not resolve {self._selector} to DOM Element")
     try:
         return await task(
             handle,
             (deadline - monotonic_time()) if deadline else 0,
         )
     finally:
         await handle.dispose()
 async def set_input_files(
     self,
     files: Union[str, Path, FilePayload, List[Union[str, Path]], List[FilePayload]],
     timeout: float = None,
     noWaitAfter: bool = None,
 ) -> None:
     params = locals_to_params(locals())
     frame = await self.owner_frame()
     if not frame:
         raise Error("Cannot set input files to detached element")
     converted = await convert_input_files(files, frame.page.context)
     if converted["files"] is not None:
         await self._channel.send(
             "setInputFiles", {**params, "files": converted["files"]}
         )
     else:
         await self._channel.send(
             "setInputFilePaths",
             locals_to_params({**params, **converted, "files": None}),
         )
Beispiel #7
0
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))
Beispiel #8
0
 async def delete(self) -> None:
     artifact = await self._artifact_future
     if not artifact:
         raise Error("Page did not produce any video frames")
     await artifact.delete()
Beispiel #9
0
 async def save_as(self, path: Union[str, pathlib.Path]) -> None:
     artifact = await self._artifact_future
     if not artifact:
         raise Error("Page did not produce any video frames")
     await artifact.save_as(path)
Beispiel #10
0
 async def path(self) -> pathlib.Path:
     artifact = await self._artifact_future
     if not artifact:
         raise Error("Page did not produce any video frames")
     return artifact.absolute_path
Beispiel #11
0
 def _page_closed(self) -> None:
     if not self._artifact_future.done():
         self._artifact_future.set_exception(Error("Page closed"))
Beispiel #12
0
    async def fetch(
        self,
        urlOrRequest: Union[str, network.Request],
        params: Dict[str, Union[bool, float, str]] = None,
        method: str = None,
        headers: Headers = None,
        data: Union[Any, bytes, str] = None,
        form: Dict[str, Union[bool, float, str]] = None,
        multipart: Dict[str, Union[bytes, bool, float, str,
                                   FilePayload]] = None,
        timeout: float = None,
        failOnStatusCode: bool = None,
        ignoreHTTPSErrors: bool = None,
    ) -> "APIResponse":
        request = urlOrRequest if isinstance(urlOrRequest,
                                             network.Request) else None
        assert request or isinstance(
            urlOrRequest,
            str), "First argument must be either URL string or Request"
        assert (
            (1 if data else 0) + (1 if form else 0) + (1 if multipart else 0)
        ) <= 1, "Only one of 'data', 'form' or 'multipart' can be specified"
        url = request.url if request else urlOrRequest
        method = method or (request.method if request else "GET")
        # Cannot call allHeaders() here as the request may be paused inside route handler.
        headers_obj = headers or (request.headers if request else None)
        serialized_headers = serialize_headers(
            headers_obj) if headers_obj else None
        json_data = None
        form_data: Optional[List[NameValue]] = None
        multipart_data: Optional[List[FormField]] = None
        post_data_buffer: Optional[bytes] = None
        if data:
            if isinstance(data, str):
                post_data_buffer = data.encode()
            elif isinstance(data, bytes):
                post_data_buffer = data
            elif isinstance(data, (dict, list)):
                json_data = data
            else:
                raise Error(f"Unsupported 'data' type: {type(data)}")
        elif form:
            form_data = object_to_array(form)
        elif multipart:
            multipart_data = []
            # Convert file-like values to ServerFilePayload structs.
            for name, value in multipart.items():
                if is_file_payload(value):
                    payload = cast(FilePayload, value)
                    assert isinstance(
                        payload["buffer"],
                        bytes), f"Unexpected buffer type of 'data.{name}'"
                    multipart_data.append(
                        FormField(name=name,
                                  file=file_payload_to_json(payload)))
                elif isinstance(value, str):
                    multipart_data.append(FormField(name=name, value=value))
        if (post_data_buffer is None and json_data is None
                and form_data is None and multipart_data is None):
            post_data_buffer = request.post_data_buffer if request else None
        post_data = (base64.b64encode(post_data_buffer).decode()
                     if post_data_buffer else None)

        def filter_none(input: Dict) -> Dict:
            return {k: v for k, v in input.items() if v is not None}

        result = await self._channel.send_return_as_dict(
            "fetch",
            filter_none({
                "url": url,
                "params": object_to_array(params),
                "method": method,
                "headers": serialized_headers,
                "postData": post_data,
                "jsonData": json_data,
                "formData": form_data,
                "multipartData": multipart_data,
                "timeout": timeout,
                "failOnStatusCode": failOnStatusCode,
                "ignoreHTTPSErrors": ignoreHTTPSErrors,
            }),
        )
        if result.get("error"):
            raise Error(result["error"])
        return APIResponse(self, result["response"])
 async def path_after_finished(self) -> Optional[pathlib.Path]:
     if self._is_remote:
         raise Error(
             "Path is not available when using browser_type.connect(). Use save_as() to save a local copy."
         )
     return pathlib.Path(await self._channel.send("pathAfterFinished"))