def handle_save_request(self, ws): """Save serialized version of report deltas to the cloud.""" @tornado.gen.coroutine def progress(percent): progress_msg = ForwardMsg() progress_msg.upload_report_progress = percent yield ws.write_message(progress_msg.SerializeToString(), binary=True) # Indicate that the save is starting. try: yield progress(0) url = yield self._save_final_report(progress) # Indicate that the save is done. progress_msg = ForwardMsg() progress_msg.report_uploaded = url yield ws.write_message(progress_msg.SerializeToString(), binary=True) except Exception as e: # Horrible hack to show something if something breaks. err_msg = '%s: %s' % (type(e).__name__, str(e) or 'No further details.') progress_msg = ForwardMsg() progress_msg.report_uploaded = err_msg yield ws.write_message(progress_msg.SerializeToString(), binary=True) raise e
def populate_hash_if_needed(msg: ForwardMsg) -> str: """Computes and assigns the unique hash for a ForwardMsg. If the ForwardMsg already has a hash, this is a no-op. Parameters ---------- msg : ForwardMsg Returns ------- string The message's hash, returned here for convenience. (The hash will also be assigned to the ForwardMsg; callers do not need to do this.) """ if msg.hash == "": # Move the message's metadata aside. It's not part of the # hash calculation. metadata = msg.metadata msg.ClearField("metadata") # MD5 is good enough for what we need, which is uniqueness. hasher = hashlib.md5() hasher.update(msg.SerializeToString()) msg.hash = hasher.hexdigest() # Restore metadata. msg.metadata.CopyFrom(metadata) return msg.hash
def serialize_forward_msg(msg: ForwardMsg) -> bytes: """Serialize a ForwardMsg to send to a client. If the message is too large, it will be converted to an exception message instead. """ populate_hash_if_needed(msg) msg_str = msg.SerializeToString() if len(msg_str) > get_max_message_size_bytes(): import streamlit.elements.exception as exception # Overwrite the offending ForwardMsg.delta with an error to display. # This assumes that the size limit wasn't exceeded due to metadata. exception.marshall(msg.delta.new_element.exception, MessageSizeError(msg_str)) msg_str = msg.SerializeToString() return msg_str
def serialize_forward_msg(msg: ForwardMsg) -> bytes: """Serialize a ForwardMsg to send to a client. If the message is too large, it will be converted to an exception message instead. """ populate_hash_if_needed(msg) msg_str = msg.SerializeToString() if len(msg_str) > MESSAGE_SIZE_LIMIT: import streamlit.elements.exception as exception error = RuntimeError( f"Data of size {len(msg_str)/1e6:.1f}MB exceeds write limit of {MESSAGE_SIZE_LIMIT/1e6}MB" ) # Overwrite the offending ForwardMsg.delta with an error to display. # This assumes that the size limit wasn't exceeded due to metadata. exception.marshall(msg.delta.new_element.exception, error) msg_str = msg.SerializeToString() return msg_str
def progress(percent): progress_msg = ForwardMsg() progress_msg.upload_report_progress = percent yield ws.write_message(progress_msg.SerializeToString(), binary=True)