Example #1
0
def _marshall_av_media(
    coordinates: str,
    proto: Union[AudioProto, VideoProto],
    data: Data,
    mimetype: str,
) -> None:
    """Fill audio or video proto based on contents of data.

    Given a string, check if it's a url; if so, send it out without modification.
    Otherwise assume strings are filenames and let any OS errors raise.

    Load data either from file or through bytes-processing methods into a
    InMemoryFile object.  Pack proto with generated Tornado-based URL.
    """
    # Audio and Video methods have already checked if this is a URL by this point.

    if isinstance(data, str):
        # Assume it's a filename or blank.  Allow OS-based file errors.
        with open(data, "rb") as fh:
            this_file = in_memory_file_manager.add(fh.read(), mimetype,
                                                   coordinates)
            proto.url = this_file.url
            return

    data_as_bytes: bytes
    if data is None:
        # Allow empty values so media players can be shown without media.
        return
    elif isinstance(data, bytes):
        data_as_bytes = data
    elif isinstance(data, io.BytesIO):
        data.seek(0)
        data_as_bytes = data.getvalue()
    elif isinstance(data, io.RawIOBase) or isinstance(data, io.BufferedReader):
        data.seek(0)
        read_data = data.read()
        if read_data is None:
            return
        else:
            data_as_bytes = read_data
    elif type_util.is_type(data, "numpy.ndarray"):
        data_as_bytes = data.tobytes()
    else:
        raise RuntimeError("Invalid binary data format: %s" % type(data))

    this_file = in_memory_file_manager.add(data_as_bytes, mimetype,
                                           coordinates)
    proto.url = this_file.url
Example #2
0
def marshall_file(coordinates,
                  data,
                  proto_download_button,
                  mimetype,
                  file_name=None):
    if isinstance(data, str):
        data = data.encode()
        mimetype = mimetype or "text/plain"
    elif isinstance(data, io.TextIOWrapper):
        string_data = data.read()
        data = string_data.encode()
        mimetype = mimetype or "text/plain"
    # Assume bytes; try methods until we run out.
    elif isinstance(data, bytes):
        mimetype = mimetype or "application/octet-stream"
    elif isinstance(data, io.BytesIO):
        data.seek(0)
        data = data.getvalue()
        mimetype = mimetype or "application/octet-stream"
    elif isinstance(data, io.RawIOBase) or isinstance(data, io.BufferedReader):
        data.seek(0)
        data = data.read()
        mimetype = mimetype or "application/octet-stream"
    else:
        raise RuntimeError("Invalid binary data format: %s" % type(data))

    this_file = in_memory_file_manager.add(data,
                                           mimetype,
                                           coordinates,
                                           file_name=file_name,
                                           is_for_static_download=True)
    proto_download_button.url = this_file.url
def image_to_url(
    image, width, clamp, channels, output_format, image_id, allow_emoji=False
):
    # PIL Images
    if isinstance(image, ImageFile.ImageFile) or isinstance(image, Image.Image):
        format = _format_from_image_type(image, output_format)
        data = _PIL_to_bytes(image, format)

    # BytesIO
    # Note: This doesn't support SVG. We could convert to png (cairosvg.svg2png)
    # or just decode BytesIO to string and handle that way.
    elif isinstance(image, io.BytesIO):
        data = _BytesIO_to_bytes(image)

    # Numpy Arrays (ie opencv)
    elif type(image) is np.ndarray:
        data = _verify_np_shape(image)
        data = _clip_image(data, clamp)

        if channels == "BGR":
            if len(data.shape) == 3:
                data = data[:, :, [2, 1, 0]]
            else:
                raise StreamlitAPIException(
                    'When using `channels="BGR"`, the input image should '
                    "have exactly 3 color channels"
                )

        data = _np_array_to_bytes(data, output_format=output_format)

    # Strings
    elif isinstance(image, str):
        # If it's a url, then set the protobuf and continue
        try:
            p = urlparse(image)
            if p.scheme:
                return image
        except UnicodeDecodeError:
            pass

        # Finally, see if it's a file.
        try:
            with open(image, "rb") as f:
                data = f.read()
        except:
            if allow_emoji:
                # This might be an emoji string, so just pass it to the frontend
                return image
            else:
                # Allow OS filesystem errors to raise
                raise

    # Assume input in bytes.
    else:
        data = image

    (data, mimetype) = _normalize_to_bytes(data, width, output_format)
    this_file = in_memory_file_manager.add(data, mimetype, image_id)
    return this_file.url