-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Add to/from/read/write json functions to the plotly.io module #1188
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
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
38b0588
Added to/from/read/write json functions to plotly.io module
jonmmease b6fc5ae
Add ipywidgets to optional dependencies so that FigureWidget can be
jonmmease 97f4de4
pin matplotlib to version 2.2.3
jonmmease d616f3a
Don't assume FigureWidget is available in plotly.io._utils
jonmmease d84a4dd
Add backports.tempfile for Python 2.7 testing compatibility
jonmmease 44738d1
Review formatting updates
jonmmease File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
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', | ||
graph_objs.FigureWidget, 'FigureWidget' | ||
|
||
skip_invalid: bool (default False) | ||
False if invalid figure properties should result in an exception. | ||
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' | ||
|
||
skip_invalid: bool (default False) | ||
False if invalid figure properties should result in an exception. | ||
True if invalid figure properties should be silently ignored. | ||
|
||
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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