예제 #1
0
파일: client.py 프로젝트: schrodit/cc-utils
    def put_blob(
        self,
        image_reference: str,
        digest: str,
        octets_count: int,
        data: requests.models.Response,
        max_chunk=1024 * 1024 * 1,  # 1 MiB
        mimetype: str = 'application/data',
    ):
        head_res = self.head_blob(
            image_reference=image_reference,
            digest=digest,
        )
        if head_res.ok:
            logger.info(f'skipping blob upload {digest=} - already exists')
            return

        data_is_requests_resp = isinstance(data, requests.models.Response)
        data_is_generator = isinstance(data, typing.Generator)
        data_is_filelike = hasattr(data, 'read')
        data_is_bytes = isinstance(data, bytes)

        if octets_count < max_chunk or data_is_filelike or data_is_requests_resp or data_is_bytes:
            if data_is_requests_resp:
                data = data.content
            elif data_is_generator:
                # at least GCR does not like chunked-uploads; if small enough, workaround this
                # and create one (not-that-big) bytes-obj
                _data = bytes()
                for chunk in data:
                    _data += chunk
            elif data_is_filelike:
                pass  # if filelike, http.client will handle streaming for us

            return self._put_blob_single_post(
                image_reference=image_reference,
                digest=digest,
                octets_count=octets_count,
                data=data,
            )
        else:
            if data_is_requests_resp:
                with data:
                    return self._put_blob_chunked(
                        image_reference=image_reference,
                        digest=digest,
                        octets_count=octets_count,
                        data_iterator=data.iter_content(chunk_size=max_chunk),
                        chunk_size=max_chunk,
                    )
            elif data_is_generator:
                return self._put_blob_chunked(
                    image_reference=image_reference,
                    digest=digest,
                    octets_count=octets_count,
                    data_iterator=data.iter_content(chunk_size=max_chunk),
                    chunk_size=max_chunk,
                )
            else:
                raise NotImplementedError
예제 #2
0
    def put_blob(
            self,
            image_reference: str,
            digest: str,
            octets_count: int,
            data: requests.models.Response,
            max_chunk=1024 * 1024 * 1,  # 1 MiB
    ):
        data_is_requests_response = isinstance(data, requests.models.Response)
        data_is_generator = isinstance(data, typing.Generator)
        data_is_filelike = hasattr(data, 'read')

        if octets_count < max_chunk or data_is_filelike:
            if data_is_requests_response:
                data = data.content
            elif data_is_generator:
                # at least GCR does not like chunked-uploads; if small enough, workaround this
                # and create one (not-that-big) bytes-obj
                _data = bytes()
                for chunk in data:
                    _data += chunk
            elif data_is_filelike:
                pass  # if filelike, http.client will handle streaming for us

            return self._put_blob_single_post(
                image_reference=image_reference,
                digest=digest,
                octets_count=octets_count,
                data=data,
            )
        else:
            if data_is_requests_response:
                with data:
                    return self._put_blob_chunked(
                        image_reference=image_reference,
                        digest=digest,
                        octets_count=octets_count,
                        data_iterator=data.iter_content(chunk_size=max_chunk),
                        chunk_size=max_chunk,
                    )
            elif data_is_generator:
                return self._put_blob_chunked(
                    image_reference=image_reference,
                    digest=digest,
                    octets_count=octets_count,
                    data_iterator=data.iter_content(chunk_size=max_chunk),
                    chunk_size=max_chunk,
                )
            else:
                raise NotImplementedError
예제 #3
0
 def save_response_content(response: requests.models.Response,
                           destination: str,
                           chunk_size: int = 32768) -> None:
     with open(destination, "wb") as f:
         for chunk in response.iter_content(chunk_size):
             if chunk:  # filter out keep-alive new chunksqs
                 f.write(chunk)
예제 #4
0
def save_file(filename: str, data: requests.models.Response):
    """Saves a file to the current directory."""
    filename = filter_filename(filename)
    file_size = int(data.headers.get('content-length', 0))
    try:
        with open(filename, 'wb') as f:
            with tqdm(total=file_size, unit='B',
                  unit_scale=True, unit_divisor=1024,
                  desc=filename, initial=0,
                  ascii=True, miniters=1) as pbar:
                pbar.format_meter(n=file_size,total=file_size,elapsed=pbar.format_dict['elapsed'],initial=0,ascii=True,unit_divisor=1024,unit_scale=True, unit='B',miniters=1)

                for chunk in data.iter_content(chunk_size=1024):
                    if chunk:
                        f.write(chunk)
                        pbar.update(len(chunk))
                        
        print(f"Saved file as '{filename}'")
    except OSError as exc:
        if exc.errno == 36:  # filename too long
            (_, extension) = os.path.splitext(filename)  # this can fail
            # 'extension' already contains the leading '.', hence
            # there is no need for a '.' in between "{}{}"
            random_filename = f"{random_string(15)}{extension}"
            save_file(random_filename, data)
        else:
            raise  # re-raise if .errno is different then 36
    except Exception:
        raise
예제 #5
0
 def _download_video(self, fp: str, resp: requests.models.Response) -> None:
     """Write the media to file at given fp from the response"""
     with open(fp, "wb") as outfile:
         for chunk in resp.iter_content(chunk_size=1024):
             if chunk:
                 outfile.write(chunk)
                 outfile.flush()
예제 #6
0
def save_page_to_file(response: requests.models.Response, filename: str):
    """Save content from response to given file."""
    with open(filename, 'wb') as f:
        for chunk in response.iter_content(chunk_size=1024):
            if chunk:  # filter out keep-alive new chunks
                f.write(chunk)
        print("Image saved to file:", filename, "\n")
예제 #7
0
    def save_file(self, filename: str, data: requests.models.Response):
        """Saves a file to the current directory."""
        def filter_filename(filename: str):
            """Filters a filename non alphabetic and non delimiters charaters."""
            valid_chars = "-_.() "
            return "".join(c for c in filename
                           if c.isalnum() or c in valid_chars)

        filename = filter_filename(filename)
        try:
            with open(filename, "wb") as f:
                for chunk in data.iter_content(chunk_size=1024):
                    if chunk:
                        f.write(chunk)
            self.logger.info(f'Saved file as "{filename}".')
        except OSError as exc:
            if (platform.system() == "Linux" and exc.errno
                    == 36) or (platform.system() == "Darwin"
                               and exc.errno == 63):  # filename too long
                (_, extension) = os.path.splitext(filename)  # this can fail
                # 'extension' already contains the leading '.', hence
                # there is no need for a '.' in between "{}{}"
                random_filename = f"{random_string(15)}{extension}"
                self.save_file(random_filename, data)
            else:
                raise  # re-raise if .errno is different than 36 or 63
        except Exception:
            raise
def download(filename: str, request: requests.models.Response):
    """
    Takes a filename and get or post request, then downloads the file
    while outputting a download status bar.
    Preconditions: filename must be valid
    """
    assert type(filename) == str, 'Error: filename must be a string'
    assert type(request) == requests.models.Response, 'Error: request must be a class<requests.models.Response>'
    
    with open(filename, 'wb') as f:
        start = time.perf_counter()
        if request is None:
            f.write(request.content)
        else:
            total_length = int(request.headers.get('content-length'))
            dl = 0
            for chunk in request.iter_content(chunk_size=1024*1024):
                dl += len(chunk)
                if chunk:
                    f.write(chunk)
                    f.flush()
                    done = int(50 * dl / int(total_length))
                    stars = '=' * done
                    spaces = ' ' * (50-done)
                    bps = dl//(time.perf_counter() - start)
                    percent = int((100*dl)/total_length)
                    print(f"\r[{stars}{spaces}] {bps} bps, {percent}%    ", end='\r', flush=True)
예제 #9
0
def save_document(response: requests.models.Response, doc_control_num: str,
                  date: datetime.date, doc_type: str):
    str_date = date.strftime("%Y-%m-%d")
    filepath = os.path.join(OUTPUT_DIR, str_date, doc_type,
                            f"{doc_control_num}.zip")
    with open(filepath, 'wb') as file:
        for chunk in response.iter_content(chunk_size=1024):
            file.write(chunk)
예제 #10
0
def save_file(filename: str, data: requests.models.Response):
    """Saves a file to the current directory."""
    try:
        with open(filename, 'wb') as f:
            for chunk in data.iter_content(chunk_size=1024):
                if chunk:
                    f.write(chunk)
        print(f"Saved file as '{filename}'")
    except OSError as exc:
        if exc.errno == 36:  # filename too long
            (_, extension) = os.path.splitext(filename)  # this can fail
            # 'extension' already contains the leading '.', hence
            # there is no need for a '.' in between "{}{}"
            random_filename = f"{random_string(15)}{extension}"
            save_file(random_filename, data)
        else:
            raise  # re-raise if .errno is different then 36
    except Exception:
        raise
예제 #11
0
def save_file(filename: str, data: requests.models.Response):
    """Saves a file to the current directory."""
    filename = filter_filename(filename)
    try:
        with open(filename, 'wb') as f:
            for chunk in data.iter_content(chunk_size=1024):
                if chunk:
                    f.write(chunk)
        print(f"Saved file as '{filename}'")
    except OSError as exc:
        if exc.errno == 36:  # filename too long
            (_, extension) = os.path.splitext(filename)  # this can fail
            # 'extension' already contains the leading '.', hence
            # there is no need for a '.' in between "{}{}"
            random_filename = f"{random_string(15)}{extension}"
            save_file(random_filename, data)
        else:
            raise  # re-raise if .errno is different then 36
    except Exception:
        raise
예제 #12
0
def save_file(filename: str, data: requests.models.Response):
    """Saves a file to the current directory."""
    valid_chars = '-_.() abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
    filename = ''.join(c for c in filename if c in valid_chars)
    try:
        with open(filename, 'wb') as f:
            for chunk in data.iter_content(chunk_size=1024):
                if chunk:
                    f.write(chunk)
        print(f"Saved file as '{filename}'")
    except OSError as exc:
        if exc.errno == 36:  # filename too long
            (_, extension) = os.path.splitext(filename)  # this can fail
            # 'extension' already contains the leading '.', hence
            # there is no need for a '.' in between "{}{}"
            random_filename = f"{random_string(15)}{extension}"
            save_file(random_filename, data)
        else:
            raise  # re-raise if .errno is different then 36
    except Exception:
        raise
예제 #13
0
파일: client.py 프로젝트: gardener/cc-utils
    def put_blob(
        self,
        image_reference: typing.Union[str, om.OciImageReference],
        digest: str,
        octets_count: int,
        data: requests.models.Response,
        max_chunk=1024 * 1024 * 1, # 1 MiB
        mimetype: str='application/data',
    ):
        image_reference = om.OciImageReference(image_reference)
        head_res = self.head_blob(
            image_reference=image_reference,
            digest=digest,
        )
        if head_res.ok:
            logger.info(f'skipping blob upload {digest=} - already exists')
            return

        data_is_requests_resp = isinstance(data, requests.models.Response)
        data_is_generator = isinstance(data, typing.Generator)
        data_is_filelike = hasattr(data, 'read')
        data_is_bytes = isinstance(data, bytes)

        if octets_count < max_chunk or data_is_filelike or data_is_requests_resp or data_is_bytes:
            if data_is_requests_resp:
                data = data.content
            elif data_is_generator:
                # at least GCR does not like chunked-uploads; if small enough, workaround this
                # and create one (not-that-big) bytes-obj
                _data = bytes()
                for chunk in data:
                    _data += chunk
                data = _data
            elif data_is_filelike:
                pass # if filelike, http.client will handle streaming for us

            return self._put_blob_single_post(
                image_reference=image_reference,
                digest=digest,
                octets_count=octets_count,
                data=data,
            )
        elif octets_count >= max_chunk and data_is_generator:
            # workaround: write into temporary file, as at least GCR does not implement
            # chunked-upload, and requests will not properly work w/ all generators
            # (in particular, it will not work w/ our "fake" on)
            with tempfile.TemporaryFile() as tf:
                for chunk in data:
                    tf.write(chunk)
                tf.seek(0)

                return self._put_blob_single_post(
                    image_reference=image_reference,
                    digest=digest,
                    octets_count=octets_count,
                    data=tf,
                )
        else:
            if data_is_requests_resp:
                with data:
                  return self._put_blob_chunked(
                      image_reference=image_reference,
                      digest=digest,
                      octets_count=octets_count,
                      data_iterator=data.iter_content(chunk_size=max_chunk),
                      chunk_size=max_chunk,
                  )
            else:
              raise NotImplementedError