|
import json |
|
import pathlib |
|
import warnings |
|
from typing import IO, Union, Optional, Literal |
|
|
|
from .mimebundle import spec_to_mimebundle |
|
from ..vegalite.v5.data import data_transformers |
|
from altair.utils._vegafusion_data import using_vegafusion |
|
|
|
|
|
def write_file_or_filename( |
|
fp: Union[str, pathlib.PurePath, IO], |
|
content: Union[str, bytes], |
|
mode: str = "w", |
|
encoding: Optional[str] = None, |
|
) -> None: |
|
"""Write content to fp, whether fp is a string, a pathlib Path or a |
|
file-like object""" |
|
if isinstance(fp, str) or isinstance(fp, pathlib.PurePath): |
|
with open(file=fp, mode=mode, encoding=encoding) as f: |
|
f.write(content) |
|
else: |
|
fp.write(content) |
|
|
|
|
|
def set_inspect_format_argument( |
|
format: Optional[str], fp: Union[str, pathlib.PurePath, IO], inline: bool |
|
) -> str: |
|
"""Inspect the format argument in the save function""" |
|
if format is None: |
|
if isinstance(fp, str): |
|
format = fp.split(".")[-1] |
|
elif isinstance(fp, pathlib.PurePath): |
|
format = fp.suffix.lstrip(".") |
|
else: |
|
raise ValueError( |
|
"must specify file format: " |
|
"['png', 'svg', 'pdf', 'html', 'json', 'vega']" |
|
) |
|
|
|
if format != "html" and inline: |
|
warnings.warn("inline argument ignored for non HTML formats.", stacklevel=1) |
|
|
|
return format |
|
|
|
|
|
def set_inspect_mode_argument( |
|
mode: Optional[Literal["vega-lite"]], |
|
embed_options: dict, |
|
spec: dict, |
|
vegalite_version: Optional[str], |
|
) -> Literal["vega-lite"]: |
|
"""Inspect the mode argument in the save function""" |
|
if mode is None: |
|
if "mode" in embed_options: |
|
mode = embed_options["mode"] |
|
elif "$schema" in spec: |
|
mode = spec["$schema"].split("/")[-2] |
|
else: |
|
mode = "vega-lite" |
|
|
|
if mode != "vega-lite": |
|
raise ValueError("mode must be 'vega-lite', " "not '{}'".format(mode)) |
|
|
|
if mode == "vega-lite" and vegalite_version is None: |
|
raise ValueError("must specify vega-lite version") |
|
|
|
return mode |
|
|
|
|
|
def save( |
|
chart, |
|
fp: Union[str, pathlib.PurePath, IO], |
|
vega_version: Optional[str], |
|
vegaembed_version: Optional[str], |
|
format: Optional[Literal["json", "html", "png", "svg", "pdf"]] = None, |
|
mode: Optional[Literal["vega-lite"]] = None, |
|
vegalite_version: Optional[str] = None, |
|
embed_options: Optional[dict] = None, |
|
json_kwds: Optional[dict] = None, |
|
webdriver: Optional[Literal["chrome", "firefox"]] = None, |
|
scale_factor: float = 1, |
|
engine: Optional[Literal["vl-convert", "altair_saver"]] = None, |
|
inline: bool = False, |
|
**kwargs, |
|
) -> None: |
|
"""Save a chart to file in a variety of formats |
|
|
|
Supported formats are [json, html, png, svg, pdf] |
|
|
|
Parameters |
|
---------- |
|
chart : alt.Chart |
|
the chart instance to save |
|
fp : string filename, pathlib.Path or file-like object |
|
file to which to write the chart. |
|
format : string (optional) |
|
the format to write: one of ['json', 'html', 'png', 'svg', 'pdf']. |
|
If not specified, the format will be determined from the filename. |
|
mode : string (optional) |
|
Must be 'vega-lite'. If not specified, then infer the mode from |
|
the '$schema' property of the spec, or the ``opt`` dictionary. |
|
If it's not specified in either of those places, then use 'vega-lite'. |
|
vega_version : string (optional) |
|
For html output, the version of vega.js to use |
|
vegalite_version : string (optional) |
|
For html output, the version of vegalite.js to use |
|
vegaembed_version : string (optional) |
|
For html output, the version of vegaembed.js to use |
|
embed_options : dict (optional) |
|
The vegaEmbed options dictionary. Default is {} |
|
(See https://github.com/vega/vega-embed for details) |
|
json_kwds : dict (optional) |
|
Additional keyword arguments are passed to the output method |
|
associated with the specified format. |
|
webdriver : string {'chrome' | 'firefox'} (optional) |
|
Webdriver to use for png, svg, or pdf output when using altair_saver engine |
|
scale_factor : float (optional) |
|
scale_factor to use to change size/resolution of png or svg output |
|
engine: string {'vl-convert', 'altair_saver'} |
|
the conversion engine to use for 'png', 'svg', and 'pdf' formats |
|
inline: bool (optional) |
|
If False (default), the required JavaScript libraries are loaded |
|
from a CDN location in the resulting html file. |
|
If True, the required JavaScript libraries are inlined into the resulting |
|
html file so that it will work without an internet connection. |
|
The vl-convert-python package is required if True. |
|
**kwargs : |
|
additional kwargs passed to spec_to_mimebundle. |
|
""" |
|
if json_kwds is None: |
|
json_kwds = {} |
|
|
|
format = set_inspect_format_argument(format, fp, inline) |
|
|
|
def perform_save(): |
|
spec = chart.to_dict(context={"pre_transform": False}) |
|
|
|
inner_mode = set_inspect_mode_argument( |
|
mode, embed_options or {}, spec, vegalite_version |
|
) |
|
|
|
if format == "json": |
|
json_spec = json.dumps(spec, **json_kwds) |
|
write_file_or_filename(fp, json_spec, mode="w") |
|
elif format == "html": |
|
if inline: |
|
kwargs["template"] = "inline" |
|
mimebundle = spec_to_mimebundle( |
|
spec=spec, |
|
format=format, |
|
mode=inner_mode, |
|
vega_version=vega_version, |
|
vegalite_version=vegalite_version, |
|
vegaembed_version=vegaembed_version, |
|
embed_options=embed_options, |
|
json_kwds=json_kwds, |
|
**kwargs, |
|
) |
|
write_file_or_filename(fp, mimebundle["text/html"], mode="w") |
|
elif format in ["png", "svg", "pdf", "vega"]: |
|
mimebundle = spec_to_mimebundle( |
|
spec=spec, |
|
format=format, |
|
mode=inner_mode, |
|
vega_version=vega_version, |
|
vegalite_version=vegalite_version, |
|
vegaembed_version=vegaembed_version, |
|
embed_options=embed_options, |
|
webdriver=webdriver, |
|
scale_factor=scale_factor, |
|
engine=engine, |
|
**kwargs, |
|
) |
|
if format == "png": |
|
write_file_or_filename(fp, mimebundle[0]["image/png"], mode="wb") |
|
elif format == "pdf": |
|
write_file_or_filename(fp, mimebundle["application/pdf"], mode="wb") |
|
else: |
|
encoding = kwargs.get("encoding", "utf-8") |
|
write_file_or_filename( |
|
fp, mimebundle["image/svg+xml"], mode="w", encoding=encoding |
|
) |
|
else: |
|
raise ValueError("Unsupported format: '{}'".format(format)) |
|
|
|
if using_vegafusion(): |
|
|
|
|
|
|
|
with data_transformers.disable_max_rows(): |
|
perform_save() |
|
else: |
|
|
|
|
|
|
|
|
|
|
|
with data_transformers.enable("default"), data_transformers.disable_max_rows(): |
|
perform_save() |
|
|