def save()

in lucid/misc/io/saving.py [0:0]


def save(thing, url_or_handle, allow_unsafe_formats=False, save_context: Optional[CaptureSaveContext] = None, **kwargs):
    """Save object to file on CNS.

    File format is inferred from path. Use save_img(), save_npy(), or save_json()
    if you need to force a particular format.

    Args:
      obj: object to save.
      path: CNS path.
      allow_unsafe_formats: set to True to allow saving unsafe formats (eg. pickles)
      save_context: a context into which to capture saves, otherwise will try to use global context

    Raises:
      RuntimeError: If file extension not supported.
    """

    # Determine context
    # Is this a handle? What is the extension? Are we saving to GCS?
    is_handle = hasattr(url_or_handle, "write") and hasattr(url_or_handle, "name")
    if is_handle:
        path = url_or_handle.name
    else:
        path = url_or_handle

    path_without_ext, ext = os.path.splitext(path)
    is_gcs = path.startswith("gs://")

    if ext in compressors:
        compressor = compressors[ext]
        _, ext = os.path.splitext(path_without_ext)
    else:
        compressor = nullcontext

    if not ext:
        raise RuntimeError("No extension in URL: " + path)

    # Determine which saver should be used
    if ext in savers:
        saver = savers[ext]
    elif ext in unsafe_savers:
        if not allow_unsafe_formats:
            raise ValueError(f"{ext} is considered unsafe, you must explicitly allow its use by passing allow_unsafe_formats=True")
        saver = unsafe_savers[ext]
    elif isinstance(thing, str):
        saver = save_str
    else:
        message = "Unknown extension '{}'. As a result, only strings can be saved, not {}. Supported extensions: {}"
        raise ValueError(message.format(ext, type(thing).__name__, list(savers.keys())))

    # Actually save
    if is_handle:
        handle_provider = nullcontext
    else:
        handle_provider = write_handle

    with handle_provider(url_or_handle) as handle:
        with compressor(handle) as compressed_handle:
            result = saver(thing, compressed_handle, **kwargs)

    # Set mime type on gcs if html -- usually, when one saves an html to GCS,
    # they want it to be viewsable as a website.
    if is_gcs and ext == ".html":
        subprocess.run(
            ["gsutil", "setmeta", "-h", "Content-Type: text/html; charset=utf-8", path]
        )
    if is_gcs and ext == ".json":
        subprocess.run(
            ["gsutil", "setmeta", "-h", "Content-Type: application/json", path]
        )

    # capture save if a save context is available
    save_context = save_context if save_context is not None else CaptureSaveContext.current_save_context()
    if save_context:
        log.debug(
            "capturing save: resulted in {} -> {} in save_context {}".format(
                result, path, save_context
            )
        )
        save_context.capture(result)

    if result is not None and "url" in result and result["url"].startswith("gs://"):
        result["serve"] = "https://storage.googleapis.com/{}".format(result["url"][5:])

    return result