-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # 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