-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add to/from/read/write json functions to the plotly.io module (#1188)
* Added to/from/read/write json functions to plotly.io module * pin matplotlib to version 2.2.3 as version 3.0.0 breaks some matplotlylib tests
- Loading branch information
Showing
7 changed files
with
459 additions
and
13 deletions.
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.