Skip to content
Merged
1 change: 1 addition & 0 deletions src/py/CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
v1.0.0rc11
- Write mocker tool to parameterize opts in tests
- Crop page to pdf size
- Add type checks to user input for improved error messages
v1.0.0rc10
- Allow user to pass Figure-like dicts
- Fix bug by which calc fig rejected plotly figures
Expand Down
28 changes: 24 additions & 4 deletions src/py/kaleido/_fig_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@


def _is_figurish(o):
return hasattr(o, "to_dict") or (
isinstance(o, dict) and "data" in o and "layout" in o
)
valid = hasattr(o, "to_dict") or (isinstance(o, dict) and "data" in o)
if not valid:
_logger.debug(
f"Figure has to_dict? {hasattr(o, 'to_dict')} "
f"is dict? {isinstance(o, dict)} "
f"Keys: {o.keys() if hasattr(o, 'keys') else None!s}",
)
return valid


def _get_figure_dimensions(layout, width, height):
Expand Down Expand Up @@ -56,6 +61,16 @@ def to_spec(figure, layout_opts):
# Get figure layout
layout = figure.get("layout", {})

for k, v in layout_opts.items():
if k == "format":
if v is not None and not isinstance(v, (str)):
raise TypeError(f"{v} must be string or None")
elif k in ("scale", "height", "width"):
if v is not None and not isinstance(v, (float, int)):
raise TypeError(f"{v} must be numeric or None")
else:
raise AttributeError(f"Unknown key in layout options, {k}")

# Extract info
extension = _get_format(layout_opts.get("format") or DEFAULT_EXT)
width, height = _get_figure_dimensions(
Expand Down Expand Up @@ -86,15 +101,20 @@ def _next_filename(path, prefix, ext):
return f"{prefix}.{ext}" if n == 1 else f"{prefix}-{n}.{ext}"


def build_fig_spec(fig, path, opts):
def build_fig_spec(fig, path, opts): # noqa: C901
if not opts:
opts = {}

if not _is_figurish(fig):
raise TypeError("Figure supplied doesn't seem to be a valid plotly figure.")

if hasattr(fig, "to_dict"):
fig = fig.to_dict()

if isinstance(path, str):
path = Path(path)
elif path and not isinstance(path, Path):
raise TypeError("Path should be a string or `pathlib.Path` object (or None)")

if path and path.suffix and not opts.get("format"):
opts["format"] = path.suffix.lstrip(".")
Expand Down