-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add to/from/read/write json functions to the plotly.io module #1188
Changes from 5 commits
38b0588
b6fc5ae
97f4de4
d616f3a
d84a4dd
44738d1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ coverage==4.3.1 | |
mock==2.0.0 | ||
nose==1.3.3 | ||
pytest==3.5.1 | ||
backports.tempfile==1.0 | ||
|
||
## orca ## | ||
psutil | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
from ._orca import to_image, write_image | ||
from . import orca | ||
|
||
from ._json import to_json, from_json, read_json, write_json |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
from six import string_types | ||
import json | ||
|
||
from plotly.utils import PlotlyJSONEncoder | ||
from plotly.io._utils import (validate_coerce_fig_to_dict, | ||
validate_coerce_output_type) | ||
|
||
|
||
def to_json(fig, | ||
validate=True, | ||
pretty=False, | ||
remove_uids=True): | ||
""" | ||
Convert a figure to a JSON string representation | ||
|
||
Parameters | ||
---------- | ||
fig: | ||
Figure object or dict representing a figure | ||
|
||
validate: bool (default True) | ||
True if the figure should be validated before being converted to | ||
JSON, False otherwise. | ||
|
||
pretty: bool (default False) | ||
True if JSON representation should be pretty-printed, False if | ||
representation should be as compact as possible. | ||
|
||
remove_uids: bool (default True) | ||
True if trace UIDs should be omitted from the JSON representation | ||
|
||
Returns | ||
------- | ||
str | ||
Representation of figure as a JSON string | ||
""" | ||
# Validate figure | ||
# --------------- | ||
fig_dict = validate_coerce_fig_to_dict(fig, validate) | ||
|
||
# Remove trace uid | ||
# ---------------- | ||
if remove_uids: | ||
for trace in fig_dict.get('data', []): | ||
trace.pop('uid') | ||
|
||
# Dump to a JSON string and return | ||
# -------------------------------- | ||
opts = {'sort_keys': True} | ||
if pretty: | ||
opts['indent'] = 2 | ||
else: | ||
# Remove all whitespace | ||
opts['separators'] = (',', ':') | ||
|
||
return json.dumps(fig_dict, cls=PlotlyJSONEncoder, **opts) | ||
|
||
|
||
def write_json(fig, file, validate=True, pretty=False, remove_uids=True): | ||
""" | ||
Convert a figure to JSON and write it to a file or writeable | ||
object | ||
|
||
Parameters | ||
---------- | ||
fig: | ||
Figure object or dict representing a figure | ||
|
||
file: str or writeable | ||
A string representing a local file path or a writeable object | ||
(e.g. an open file descriptor) | ||
|
||
pretty: bool (default False) | ||
True if JSON representation should be pretty-printed, False if | ||
representation should be as compact as possible. | ||
|
||
remove_uids: bool (default True) | ||
True if trace UIDs should be omitted from the JSON representation | ||
|
||
Returns | ||
------- | ||
None | ||
""" | ||
|
||
# Get JSON string | ||
# --------------- | ||
# Pass through validate argument and let to_json handle validation logic | ||
json_str = to_json( | ||
fig, validate=validate, pretty=pretty, remove_uids=remove_uids) | ||
|
||
# Check if file is a string | ||
# ------------------------- | ||
file_is_str = isinstance(file, string_types) | ||
|
||
# Open file | ||
# --------- | ||
if file_is_str: | ||
with open(file, 'w') as f: | ||
f.write(json_str) | ||
else: | ||
file.write(json_str) | ||
|
||
|
||
def from_json(value, output_type='Figure', skip_invalid=False): | ||
""" | ||
Construct a figure from a JSON string | ||
|
||
Parameters | ||
---------- | ||
value: str | ||
String containing the JSON representation of a figure | ||
output_type: type or str (default 'Figure') | ||
The output figure type or type name. | ||
One of: graph_objs.Figure, 'Figure, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. missing quote character |
||
graph_objs.FigureWidget, 'FigureWidget' | ||
skip_invalid: bool (default False) | ||
False if invalid figure properties should result in an exception | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and "True if invalid figure properties should be silently ignored." |
||
|
||
Raises | ||
------ | ||
ValueError | ||
if value is not a string, or if skip_invalid=False and value contains | ||
invalid figure properties | ||
|
||
Returns | ||
------- | ||
Figure or FigureWidget | ||
""" | ||
|
||
# Validate value | ||
# -------------- | ||
if not isinstance(value, string_types): | ||
raise ValueError(""" | ||
from_json requires a string argument but received value of type {typ} | ||
Received value: {value}""".format(typ=type(value), | ||
value=value)) | ||
|
||
# Decode JSON | ||
# ----------- | ||
fig_dict = json.loads(value) | ||
|
||
# Validate coerce output type | ||
# --------------------------- | ||
cls = validate_coerce_output_type(output_type) | ||
|
||
# Create and return figure | ||
# ------------------------ | ||
fig = cls(fig_dict, skip_invalid=skip_invalid) | ||
return fig | ||
|
||
|
||
def read_json(file, output_type='Figure', skip_invalid=False): | ||
""" | ||
Construct a figure from the JSON contents of a local file or readable | ||
Python object | ||
|
||
Parameters | ||
---------- | ||
file: str or readable | ||
A string containing the path to a local file or a read-able Python | ||
object (e.g. an open file descriptor) | ||
|
||
output_type: type or str (default 'Figure') | ||
The output figure type or type name. | ||
One of: graph_objs.Figure, 'Figure, | ||
graph_objs.FigureWidget, 'FigureWidget' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add newline |
||
skip_invalid: bool (default False) | ||
False if invalid figure properties should result in an exception | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update description as above |
||
|
||
Returns | ||
------- | ||
Figure or FigureWidget | ||
""" | ||
|
||
# Check if file is a string | ||
# ------------------------- | ||
# If it's a string we assume it's a local file path. If it's not a string | ||
# then we assume it's a read-able Python object | ||
file_is_str = isinstance(file, string_types) | ||
|
||
# Read file contents into JSON string | ||
# ----------------------------------- | ||
if file_is_str: | ||
with open(file, 'r') as f: | ||
json_str = f.read() | ||
else: | ||
json_str = file.read() | ||
|
||
# Construct and return figure | ||
# --------------------------- | ||
return from_json(json_str, | ||
skip_invalid=skip_invalid, | ||
output_type=output_type) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import plotly | ||
from plotly.basedatatypes import BaseFigure | ||
import plotly.graph_objs as go | ||
|
||
|
||
def validate_coerce_fig_to_dict(fig, validate): | ||
if isinstance(fig, BaseFigure): | ||
fig_dict = fig.to_dict() | ||
elif isinstance(fig, dict): | ||
if validate: | ||
# This will raise an exception if fig is not a valid plotly figure | ||
fig_dict = plotly.graph_objs.Figure(fig).to_plotly_json() | ||
else: | ||
fig_dict = fig | ||
else: | ||
raise ValueError(""" | ||
The fig parameter must be a dict or Figure. | ||
Received value of type {typ}: {v}""".format(typ=type(fig), v=fig)) | ||
return fig_dict | ||
|
||
|
||
def validate_coerce_output_type(output_type): | ||
if output_type == 'Figure' or output_type == go.Figure: | ||
cls = go.Figure | ||
elif (output_type == 'FigureWidget' or | ||
(hasattr(go, 'FigureWidget') and output_type == go.FigureWidget)): | ||
cls = go.FigureWidget | ||
else: | ||
raise ValueError(""" | ||
Invalid output type: {output_type} | ||
Must be one of: 'Figure', 'FigureWidget'""") | ||
return cls |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one of my traces was a Heatmap... which does not have a pop method
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, did you set
validate=False
? If not, thenvalidate_coerce_fig_to_dict()
should have made sure that the traces were converted intodict
s.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ended up using validate=False and remove_uids=False