8000 JSON encoding refactor and orjson encoding by jonmmease · Pull Request #2955 · plotly/plotly.py · GitHub
[go: up one dir, main page]

Skip to content

JSON encoding refactor and orjson encoding #2955

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 49 commits into from
May 27, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
40b9af1
WIP accelerated encoding with orjson
jonmmease Dec 5, 2020
f79e318
support fig to dict in io without cloning
jonmmease Dec 5, 2020
55720de
Merge branch 'master' into orjson_encoding
jonmmease Dec 5, 2020
7b3593a
fix clone default
jonmmease Dec 5, 2020
da915d6
Add pio.json.config object to configure default encoder
jonmmease Dec 5, 2020
7b235ef
default_encoder to default_engine
jonmmease Dec 5, 2020
7895b6a
blacken
jonmmease Dec 5, 2020
ce05a68
Handle Dash objects in to_json
jonmmease Dec 6, 2020
4ef6510
add JSON encoding tests
jonmmease Dec 31, 2020
101ba85
add testing of from_plotly_json
jonmmease Dec 31, 2020
67d3670
Better error message when orjson not installed and orjson engine requ…
jonmmease Dec 31, 2020
02c00da
Add orjson as optional testing dependency
jonmmease Dec 31, 2020
99ea6a1
Replace Python 3.5 CI tests with 3.8
jonmmease Dec 31, 2020
d44ec26
Try only install orjson with Python 3.6+
jonmmease Dec 31, 2020
b7d8422
Don't test orjson engine when orjson not installed
jonmmease Dec 31, 2020 8000
ddcd6f5
Try new 3.8.7 docker image since prior guess doesn't exist
jonmmease Dec 31, 2020
33359f3
greater than!
jonmmease Dec 31, 2020
c7c1819
Bump scikit image version for Python 3.8 compatibility
jonmmease Dec 31, 2020
a8d52ab
Try to help Python 2 from getting confused about which json module to…
jonmmease Dec 31, 2020
619838f
Update pandas for Python 3
jonmmease Dec 31, 2020
7c7a272
Revert 3.8 CI updates. Too much for this PR
jonmmease Dec 31, 2020
1708703
Doh
jonmmease Dec 31, 2020
66cab10
Don't skip copying during serialization
jonmmease Dec 31, 2020
56a8945
Rename new JSON functions:
jonmmease Jan 2, 2021
0a51020
Ensure cleaned numpy arrays are contiguous
jonmmease Jan 2, 2021
4e9d64e
Use to_json_plotly in html and orca logic
jonmmease Jan 8, 2021
d4068de
Add orjson documentation dependency
jonmmease Jan 8, 2021
58b7192
Handle pandas Timestamp scalars in orjson engine
jonmmease Jan 8, 2021
974fcba
Rework date and string encoding, add and fix tests
jonmmease Jan 8, 2021
a651a63
default JSON engine to "auto"
jonmmease Jan 8, 2021
af1d88d
Fix expected JSON in html export (no spaces)
jonmmease Jan 8, 2021
1d6acc3
Merge remote-tracking branch 'origin/master' into orjson_encoding
jonmmease Jan 8, 2021
d51fd94
blacken
jonmmease Jan 8, 2021
042c54c
Fix expected JSON in matplotlylib test
jonmmease Jan 8, 2021
ddc1b8f
Fix expected JSON in html repr test
jonmmease Jan 8, 2021
d7928b0
Merge remote-tracking branch 'origin/master' into orjson_encoding
jonmmease Jan 13, 2021
76cc625
Don't drop timezones during serialization, just let Plotly.js ignore …
jonmmease Jan 13, 2021
453461d
Merge branch 'numpy_date_serialization' into orjson_encoding
jonmmease Jan 13, 2021
84ba4b5
no need to skip legacy tests now
jonmmease Jan 13, 2021
340aed3
Only try `datetime_as_string` on datetime kinded numpy arrays
jonmmease Jan 13, 2021
6cea61d
Don't store object or unicode numpy arrays in figure. Coerce to lists
jonmmease Jan 21, 2021
93815c1
Try orjson encoding without cleaning first
jonmmease Jan 21, 2021
242d1fa
Merge remote-tracking branch 'origin/master' into orjson_encoding
jonmmease Jan 21, 2021
8a3a4b3
blacken
jonmmease Jan 21, 2021
1de750a
remove scratch file
jonmmease Jan 21, 2021
81f73d5
Remove unused clone
jonmmease Jan 21, 2021
80be8bd
Remove the new "json" encoder
jonmmease Jan 22, 2021
cb54f88
Reorder dict cleaning for performance
jonmmease Jan 22, 2021
1fbfa0d
Merge remote-tracking branch 'origin/master' into orjson_encoding
jonmmease Apr 29, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Rename new JSON functions:
    - pio.json.to_plotly_json -> pio.json.to_json_plotly
    - pio.json.from_plotly_json -> pio.json.from_json_plotly
  • Loading branch information
jonmmease committed Jan 2, 2021
commit 56a8945a1c3b57dfd286c784dab01471f7fc4e73
16 changes: 10 additions & 6 deletions packages/python/plotly/plotly/io/_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def coerce_to_strict(const):
return const


def to_plotly_json(plotly_object, pretty=False, engine=None):
def to_json_plotly(plotly_object, pretty=False, engine=None):
"""
Convert a plotly/Dash object to a JSON string representation

Expand Down Expand Up @@ -198,7 +198,7 @@ def to_json(fig, validate=True, pretty=False, remove_uids=True, engine=None):

See Also
--------
to_plotly_json : Convert an arbitrary plotly graph_object or Dash component to JSON
to_json_plotly : Convert an arbitrary plotly graph_object or Dash component to JSON
"""
# Validate figure
# ---------------
Expand All @@ -210,7 +210,7 @@ def to_json(fig, validate=True, pretty=False, remove_uids=True, engine=None):
for trace in fig_dict.get("data", []):
trace.pop("uid", None)

return to_plotly_json(fig_dict, pretty=pretty, engine=engine)
return to_json_plotly(fig_dict, pretty=pretty, engine=engine)


def write_json(fig, file, validate=True, pretty=False, remove_uids=True, engine=None):
Expand Down Expand Up @@ -267,7 +267,7 @@ def write_json(fig, file, validate=True, pretty=False, remove_uids=True, engine=
file.write(json_str)


def from_plotly_json(value, engine=None):
def from_json_plotly(value, engine=None):
"""
Parse JSON string using the specified JSON engine

Expand All @@ -289,6 +289,10 @@ def from_plotly_json(value, engine=None):
Returns
-------
dict

See Also
--------
from_json_plotly : Parse JSON with plotly conventions into a dict
"""
orjson = get_module("orjson", should_load=True)

Expand All @@ -297,7 +301,7 @@ def from_plotly_json(value, engine=None):
if not isinstance(value, (string_types, bytes)):
raise ValueError(
"""
from_plotly_json requires a string or bytes argument but received value of type {typ}
from_json_plotly requires a string or bytes argument but received value of type {typ}
Received value: {value}""".format(
typ=type(value), value=value
)
Expand Down Expand Up @@ -368,7 +372,7 @@ def from_json(value, output_type="Figure", skip_invalid=False, engine=None):

# Decode JSON
# -----------
fig_dict = from_plotly_json(value, engine=engine)
fig_dict = from_json_plotly(value, engine=engine)

# Validate coerce output type
# ---------------------------
Expand Down
4 changes: 2 additions & 2 deletions packages/python/plotly/plotly/io/json.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
from_json,
read_json,
config,
to_plotly_json,
from_plotly_json,
to_json_plotly,
from_json_plotly,
)
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,15 @@ def build_test_dict_string(value_string, pretty=False):


def check_roundtrip(value, engine, pretty):
encoded = pio.to_plotly_json(value, engine=engine, pretty=pretty)
decoded = pio.from_plotly_json(encoded, engine=engine)
reencoded = pio.to_plotly_json(decoded, engine=engine, pretty=pretty)
encoded = pio.to_json_plotly(value, engine=engine, pretty=pretty)
decoded = pio.from_json_plotly(encoded, engine=engine)
reencoded = pio.to_json_plotly(decoded, engine=engine, pretty=pretty)
assert encoded == reencoded

# Check from_plotly_json with bytes on Python 3
if sys.version_info.major == 3:
encoded_bytes = encoded.encode("utf8")
decoded_from_bytes = pio.from_plotly_json(encoded_bytes, engine=engine)
decoded_from_bytes = pio.from_json_plotly(encoded_bytes, engine=engine)
assert decoded == decoded_from_bytes


Expand Down Expand Up @@ -124,15 +124,15 @@ def datetime_array(request, datetime_value):
# Encoding tests
def test_graph_object_input(engine, pretty):
scatter = go.Scatter(x=[1, 2, 3], y=np.array([4, 5, 6]))
result = pio.to_plotly_json(scatter, engine=engine)
result = pio.to_json_plotly(scatter, engine=engine)
expected = """{"type":"scatter","x":[1,2,3],"y":[4,5,6]}"""
assert result == expected
check_roundtrip(result, engine=engine, pretty=pretty)


def test_numeric_numpy_encoding(numeric_numpy_array, engine, pretty):
value = build_test_dict(numeric_numpy_array)
result = pio.to_plotly_json(value, engine=engine, pretty=pretty)
result = pio.to_json_plotly(value, engine=engine, pretty=pretty)

array_str = to_json_test(numeric_numpy_array.tolist())
expected = build_test_dict_string(array_str, pretty=pretty)
Expand All @@ -142,7 +142,7 @@ def test_numeric_numpy_encoding(numeric_numpy_array, engine, pretty):

def test_object_numpy_encoding(object_numpy_array, engine, pretty):
value = build_test_dict(object_numpy_array)
result = pio.to_plotly_json(value, engine=engine, pretty=pretty)
result = pio.to_json_plotly(value, engine=engine, pretty=pretty)

array_str = to_json_test(object_numpy_array.tolist())
expected = build_test_dict_string(array_str)
Expand All @@ -155,15 +155,15 @@ def test_datetime(datetime_value, engine, pretty):
pytest.skip("legacy encoder doesn't strip timezone from scalar datetimes")

value = build_test_dict(datetime_value)
result = pio.to_plotly_json(value, engine=engine, pretty=pretty)
result = pio.to_json_plotly(value, engine=engine, pretty=pretty)
expected = build_test_dict_string('"{}"'.format(isoformat_test(datetime_value)))
assert result == expected
check_roundtrip(result, engine=engine, pretty=pretty)


def test_datetime_arrays(datetime_array, engine, pretty):
value = build_test_dict(datetime_array)
result = pio.to_plotly_json(value, engine=engine)
result = pio.to_json_plotly(value, engine=engine)

if isinstance(datetime_array, pd.Series):
dt_values = [d.isoformat() for d in datetime_array.dt.to_pydatetime().tolist()]
Expand Down
0