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
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