Skip to content

Extract chart studio functionality, optimized imports #1476

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 89 commits into from
Apr 12, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
54c96fa
Initial plotly.io.renderers implementation
jonmmease Mar 16, 2019
8342680
rename 'default' to 'plotly_mimetype'
jonmmease Mar 16, 2019
2cc4f89
Added _repr_mimebundle_
jonmmease Mar 16, 2019
28a669c
Add initial browser renderer to show figure in browser tab
jonmmease Mar 16, 2019
8bf793f
Expose renderer base classes
jonmmease Mar 17, 2019
3dfb24a
Documentation / cleanup of _renderers
jonmmease Mar 17, 2019
2dd92c0
Auto-detect VSCode environment and default to renderer combination of
jonmmease Mar 18, 2019
953bae8
Documentation / cleanup of _base_renderers
jonmmease Mar 18, 2019
da39c34
Update default renderers explanation
jonmmease Mar 18, 2019
c2a6471
Add renderer docstring to repr for easy discoverability
jonmmease Mar 18, 2019
e6b9e45
Make ipython an optional dependency
jonmmease Mar 18, 2019
54ac011
Python 2.7 support
jonmmease Mar 18, 2019
7dc1029
Add parent <html></html. tags for HtmlRenderer with fullhtml=True
jonmmease Mar 18, 2019
c23f76e
Added initial renderers test suite
jonmmease Mar 18, 2019
a1d9d9e
Added IFrameRenderer
jonmmease Mar 19, 2019
9d082f0
Proper HTML tags for fullhtml
jonmmease Mar 19, 2019
b499b35
Added initial to_html functions to plotly.io
jonmmease Mar 19, 2019
63424a5
Reimplement plotly.offline.plot using plotly.io.write_html/to_div.
jonmmease Mar 19, 2019
28463c2
Reimplement plotly.offline.iplot and init_notebook_mode pio.show
jonmmease Mar 19, 2019
e4421bb
Add responsive=True config when figure width/height aren't set
jonmmease Mar 19, 2019
3b11783
Add MathJax configuration when initializing HTML renderer in notebook
jonmmease Mar 19, 2019
2580797
Reimplement HTML Renderers using the plotly.io html functions
jonmmease Mar 19, 2019
8a787fd
Restore plot/iplot image export by adding support for custom JS snippets
jonmmease Mar 20, 2019
c4cb4a7
Remove default renderer and make rendering figure on display an option
jonmmease Mar 20, 2019
a109f86
Update renderer tests with plotly.io.renderers.render_on_display
jonmmease Mar 20, 2019
f7f7cb7
Add download image plotly.offline.plot test
jonmmease Mar 20, 2019
f073a14
add set_v3_defaults and set_v4_defaults renderer methods to make
jonmmease Mar 20, 2019
1058683
Added future flag system under _plotly_future_ to control
jonmmease Mar 20, 2019
df3515e
Roll to_div function into to_html with full_html argument
jonmmease Mar 20, 2019
86eb69a
Rename SideEffectRenderer -> ExternalRenderer
jonmmease Mar 21, 2019
049e304
WIP delaying import in io module.
jonmmease Mar 21, 2019
1d3ac88
Initial chart_studio refactor
jonmmease Mar 21, 2019
2649557
Fix up chart_studio imports. Everything import cleanly now
jonmmease Mar 21, 2019
562a60a
Mapping to deprecated modules
jonmmease Mar 21, 2019
81221de
Per function deprecation of chart_studio tools functions
jonmmease Mar 22, 2019
a51730b
Add extract_chart_studio to v4 future group
jonmmease Mar 22, 2019
b2542c1
whitespace
jonmmease Mar 22, 2019
75562fa
WIP checkpoint on import optimization
jonmmease Mar 22, 2019
7765578
Optimize import time a bit by reducing the number of files create
jonmmease Mar 23, 2019
68f039f
Delay optional imports of pandas/numpy/matplotlib
jonmmease Mar 23, 2019
9aae2c7
Restore proper versioneer _version.py file
jonmmease Mar 23, 2019
c209a18
Fix optional test suite
jonmmease Mar 23, 2019
084ac36
offline fixes
jonmmease Mar 23, 2019
19de7b9
Use correct config property to grab platform url from saved config
jonmmease Mar 23, 2019
ecf4867
Remove legacy unused _plot_html function
jonmmease Mar 23, 2019
b87ebed
Move static image renderer tests to orca test suite
jonmmease Mar 23, 2019
3907d61
Merge enh_renderers
jonmmease Mar 23, 2019
81c4ced
Move optional_imports to plotly_utils so that it can be used in
jonmmease Mar 23, 2019
e11d74f
Move combination renderers test to orca test suite
jonmmease Mar 23, 2019
e8d2f1b
Remove remaining image renderer references from test_io
jonmmease Mar 23, 2019
de80ffc
Add ipython to orca environment for renderer tests
jonmmease Mar 23, 2019
7cba367
Remove pdf image from renderer tests since it seems to be non-determi…
jonmmease Mar 23, 2019
3451340
Merge branch 'enh_renderers' into imports_v4
jonmmease Mar 23, 2019
f19f150
Added get_config_plotly_server_url to retrieve `plotly_domain`
jonmmease Mar 23, 2019
b24bc7e
Fix jupyter connected test
jonmmease Mar 23, 2019
cb699f4
delete tmp files
jonmmease Mar 23, 2019
a58d68c
Fixed optional tests
jonmmease Mar 23, 2019
fc2a716
chart_studio test fixes for new import structure
jonmmease Mar 23, 2019
73752d7
Added chromium browser renderer
jonmmease Mar 26, 2019
8a0f6cc
Fix plotly mimetype renderer when used with numpy arrays/pandas Series
jonmmease Mar 26, 2019
504e342
Lazily initialize default renderers.
jonmmease Mar 26, 2019
1115608
Use 'browser' default renderer if ipython isn't available
jonmmease Mar 26, 2019
1bbbe83
Merge branch 'enh_renderers' into imports_v4
jonmmease Mar 26, 2019
6071473
Remove non_recursive_imports flag for this PR
jonmmease Mar 26, 2019
d8fb7c8
Update setup.py `packages`
jonmmease Mar 26, 2019
3af116a
Add plotly.widgets deprecation package
jonmmease Mar 26, 2019
0b8cfb6
Remove moved packages from setup.py
jonmmease Mar 26, 2019
a49c937
Update tox to run tests from chart_studio package
jonmmease Mar 26, 2019
ea74d44
Add the chart_studio package itself to setup.py
jonmmease Mar 26, 2019
43c99ce
Test fixes
jonmmease Mar 27, 2019
9e5504a
Test fixes
jonmmease Mar 27, 2019
12c58bb
Reorganize exceptions to work around circular import errors
jonmmease Mar 27, 2019
49ecfbf
Move plotly.file to _plotly_utils to avoid circular import errors
jonmmease Mar 27, 2019
574b1b9
Update version constraints on pandas/numpy
jonmmease Mar 27, 2019
db01dd4
Move PlotlyJSONEncoder ot _plotly_utils
jonmmease Mar 27, 2019
6921bf1
Python 2 absolute import
jonmmease Mar 27, 2019
f7456d2
plotly.api -> chart_studio.api within chart_studio package
jonmmease Mar 27, 2019
1945368
Merge branch 'master'
jonmmease Apr 10, 2019
b1c3f34
Fix plotly.tools import
jonmmease Apr 10, 2019
ef9ac99
chart_studio recursive imports
jonmmease Apr 10, 2019
cdf2c40
plotly -> chart_studio import
jonmmease Apr 11, 2019
0b4cd7a
chart_studio -> plotly in templategen
jonmmease Apr 11, 2019
5e4aca9
typo
jonmmease Apr 11, 2019
609d1f7
typo
jonmmease Apr 11, 2019
fe64acf
Code review updates
jonmmease Apr 11, 2019
922458d
Restore all of the original tests to test our backward compatibility
jonmmease Apr 12, 2019
860e078
test fixes
jonmmease Apr 12, 2019
54c33f2
Fix mock modules
jonmmease Apr 12, 2019
4b69d6a
session test fix
jonmmease Apr 12, 2019
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
WIP delaying import in io module.
Importing io by itself is now < 50ms
  • Loading branch information
jonmmease committed Mar 22, 2019
commit 049e304e8725d3dbddecd77a85d4bb66e192c25a
32 changes: 21 additions & 11 deletions plotly/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,25 @@

from __future__ import absolute_import

from plotly import (plotly, dashboard_objs, graph_objs, grid_objs, tools,
utils, session, offline, colors, io)
from plotly.version import __version__
from plotly import (
# plotly,
# dashboard_objs,
# graph_objs,
# grid_objs,
# tools,
# utils,
# session,
# offline,
# colors,
io
)
# from plotly.version import __version__
from _plotly_future_ import _future_flags

from ._version import get_versions
__version__ = get_versions()['version']
del get_versions

# Set default template here to make sure import process is complet
if 'template_defaults' in _future_flags:
io.templates._default = 'plotly'
#
# from ._version import get_versions
# __version__ = get_versions()['version']
# del get_versions

# # Set default template here to make sure import process is complete
# if 'template_defaults' in _future_flags:
# io.templates._default = 'plotly'
6 changes: 4 additions & 2 deletions plotly/io/_base_renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@

import six
from plotly.io import to_json, to_image
from plotly import utils, optional_imports
from plotly import optional_imports

from plotly.io._orca import ensure_server
from plotly.offline.offline import _get_jconfig, get_plotlyjs

ipython_display = optional_imports.get_module('IPython.display')
IPython = optional_imports.get_module('IPython')
Expand Down Expand Up @@ -80,6 +80,7 @@ def __init__(self, config=None):
self.config = dict(config) if config else {}

def to_mimebundle(self, fig_dict):
from plotly.offline.offline import _get_jconfig
config = _get_jconfig(self.config)
if config:
fig_dict['config'] = config
Expand Down Expand Up @@ -267,6 +268,7 @@ def activate(self):
mathjax_config=_mathjax_config)

else:
from plotly.offline.offline import get_plotlyjs
# If not connected then we embed a copy of the plotly.js
# library in the notebook
script = """\
Expand Down
7 changes: 4 additions & 3 deletions plotly/io/_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@
import six

from plotly.io._utils import validate_coerce_fig_to_dict
from plotly.offline.offline import _get_jconfig, get_plotlyjs
from plotly import utils


# Build script to set global PlotlyConfig object. This must execute before
# plotly.js is loaded.
Expand Down Expand Up @@ -118,6 +115,7 @@ def to_html(fig,
plotdivid = str(uuid.uuid4())

# ## Serialize figure ##
from plotly import utils
jdata = json.dumps(
fig_dict.get('data', []), cls=utils.PlotlyJSONEncoder)
jlayout = json.dumps(
Expand All @@ -130,6 +128,7 @@ def to_html(fig,
jframes = None

# ## Serialize figure config ##
from plotly.offline.offline import _get_jconfig
config = _get_jconfig(config)

# Check whether we should add responsive
Expand Down Expand Up @@ -233,6 +232,7 @@ def to_html(fig,
url=include_plotlyjs_orig)

elif include_plotlyjs:
from plotly.offline.offline import get_plotlyjs
load_plotlyjs = """\
{win_config}
<script type="text/javascript">{plotlyjs}</script>\
Expand Down Expand Up @@ -438,6 +438,7 @@ def write_html(fig,
os.path.dirname(file), 'plotly.min.js')

if not os.path.exists(bundle_path):
from plotly.offline.offline import get_plotlyjs
with open(bundle_path, 'w') as f:
f.write(get_plotlyjs())

Expand Down
5 changes: 3 additions & 2 deletions plotly/io/_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
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,
Expand Down Expand Up @@ -36,6 +35,8 @@ def to_json(fig,
str
Representation of figure as a JSON string
"""
from plotly.utils import PlotlyJSONEncoder

# Validate figure
# ---------------
fig_dict = validate_coerce_fig_to_dict(fig, validate)
Expand Down
26 changes: 13 additions & 13 deletions plotly/io/_orca.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from copy import copy
from contextlib import contextmanager

import requests
import retrying
from six import string_types

Expand Down Expand Up @@ -707,7 +706,7 @@ def __repr__(self):

constants
---------
plotlyjs: {plotlyjs}
plotlyjs: {plotlyjs}
config_file: {config_file}

""".format(port=self.port,
Expand Down Expand Up @@ -822,7 +821,7 @@ def __repr__(self):
port: {port}
pid: {pid}
command: {command}

""".format(executable=self.executable,
version=self.version,
port=self.port,
Expand Down Expand Up @@ -910,7 +909,7 @@ def validate_executable():
Alternatively, see other installation methods in the orca project README at
https://github.com/plotly/orca.

After installation is complete, no further configuration should be needed.
After installation is complete, no further configuration should be needed.

If you have installed orca, then for some reason plotly.py was unable to
locate it. In this case, set the `plotly.io.orca.config.executable`
Expand All @@ -922,7 +921,7 @@ def validate_executable():
If it is successful then you may want to save this configuration so that it
will be applied automatically in future sessions. You can do this as follows:

>>> plotly.io.orca.config.save()
>>> plotly.io.orca.config.save()

If you're still having trouble, feel free to ask for help on the forums at
https://community.plot.ly/c/api/python
Expand Down Expand Up @@ -1038,7 +1037,7 @@ def validate_executable():
The error encountered is that no version was reported by the orca executable.
Here is the command that plotly.py ran to request the version:

$ {executable} --version
$ {executable} --version
""".format(executable=executable))
else:
version_result = version_result.decode()
Expand Down Expand Up @@ -1153,7 +1152,7 @@ def ensure_server():

Install using pip:
$ pip install psutil

Install using conda:
$ conda install psutil
""")
Expand Down Expand Up @@ -1224,12 +1223,13 @@ def request_image_with_retrying(**kwargs):
Helper method to perform an image request to a running orca server process
with retrying logic.
"""
from requests import post
server_url = 'http://{hostname}:{port}'.format(
hostname='localhost', port=orca_state['port'])

request_params = {k: v for k, v, in kwargs.items() if v is not None}
json_str = json.dumps(request_params, cls=plotly.utils.PlotlyJSONEncoder)
response = requests.post(server_url + '/', data=json_str)
response = post(server_url + '/', data=json_str)
return response


Expand Down Expand Up @@ -1351,7 +1351,7 @@ def to_image(fig,

{info}
plotly.py will attempt to start the local server process again the next time
an image export operation is performed.
an image export operation is performed.
""".format(info=status_str))

# Check response
Expand Down Expand Up @@ -1393,7 +1393,7 @@ def to_image(fig,

>>> plotly.io.orca.config.mapbox_access_token = 'pk.abc...'

If you would like this token to be applied automatically in
If you would like this token to be applied automatically in
future sessions, then save your orca configuration as follows:

>>> plotly.io.orca.config.save()
Expand All @@ -1402,9 +1402,9 @@ def to_image(fig,
err_message += """
Exporting to EPS format requires the poppler library. You can install
poppler on MacOS or Linux with:

$ conda install poppler

Or, you can install it on MacOS using homebrew with:

$ brew install poppler
Expand Down Expand Up @@ -1498,7 +1498,7 @@ def write_image(fig,
For example:

>>> import plotly.io as pio
>>> pio.write_image(fig, file_path, format='png')
>>> pio.write_image(fig, file_path, format='png')
""".format(file=file))

# Request image
Expand Down
21 changes: 14 additions & 7 deletions plotly/io/_templates.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
from __future__ import absolute_import
from plotly.basedatatypes import BaseFigure
from plotly.graph_objs import Figure
from plotly.validators.layout import TemplateValidator
from plotly.graph_objs.layout import Template
from _plotly_utils.basevalidators import (
CompoundValidator, CompoundArrayValidator, is_array)

import textwrap
import pkgutil
Expand Down Expand Up @@ -44,7 +38,7 @@ def __init__(self):
for template_name in default_templates:
self._templates[template_name] = Lazy

self._validator = TemplateValidator()
self._validator = None
self._default = None

# ### Magic methods ###
Expand All @@ -61,6 +55,8 @@ def __iter__(self):
def __getitem__(self, item):
template = self._templates[item]
if template is Lazy:
from plotly.graph_objs.layout._template import Template

# Load template from package data
path = os.path.join('package_data', 'templates', item + '.json')
template_str = pkgutil.get_data('plotly', path).decode('utf-8')
Expand All @@ -81,6 +77,11 @@ def __delitem__(self, key):
if self._default == key:
self._default = None

def _validate(self, template):
if not self._validator:
from plotly.validators.layout import TemplateValidator
self._validator = TemplateValidator()

def keys(self):
return self._templates.keys()

Expand Down Expand Up @@ -189,6 +190,7 @@ def merge_templates(self, *args):
if args:
return reduce(self._merge_2_templates, args)
else:
from plotly.graph_objs.layout._template import Template
return Template()

def _merge_2_templates(self, template1, template2):
Expand Down Expand Up @@ -250,6 +252,9 @@ def walk_push_to_template(fig_obj, template_obj, skip):
skip: set of str
Set of names of properties to skip
"""
from _plotly_utils.basevalidators import (
CompoundValidator, CompoundArrayValidator, is_array)

for prop in list(fig_obj._props):
if prop == 'template' or prop in skip:
# Avoid infinite recursion
Expand Down Expand Up @@ -393,6 +398,8 @@ def to_templated(fig, skip=('title', 'text')):
"""

# process fig
from plotly.basedatatypes import BaseFigure
from plotly.graph_objs import Figure
if not isinstance(fig, BaseFigure):
fig = Figure(fig)

Expand Down
12 changes: 6 additions & 6 deletions plotly/io/_utils.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
from __future__ import absolute_import

import plotly
from plotly.basedatatypes import BaseFigure
import plotly.graph_objs as go


def validate_coerce_fig_to_dict(fig, validate):
from plotly.basedatatypes import BaseFigure
from plotly.graph_objs import Figure
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()
fig_dict = Figure(fig).to_plotly_json()
else:
fig_dict = fig
else:
Expand All @@ -22,6 +20,8 @@ def validate_coerce_fig_to_dict(fig, validate):


def validate_coerce_output_type(output_type):
import plotly.graph_objs as go

if output_type == 'Figure' or output_type == go.Figure:
cls = go.Figure
elif (output_type == 'FigureWidget' or
Expand All @@ -31,4 +31,4 @@ def validate_coerce_output_type(output_type):
raise ValueError("""
Invalid output type: {output_type}
Must be one of: 'Figure', 'FigureWidget'""")
return cls
return cls