Skip to content

Commit 9ccc3c7

Browse files
committed
Merge pull request plotly#466 from plotly/ensure-plotlyjs-loaded
Ensure plotlyjs loaded when page or kernel restarts
2 parents 9caf1c1 + abd4169 commit 9ccc3c7

File tree

3 files changed

+170
-51
lines changed

3 files changed

+170
-51
lines changed

plotly/graph_reference/default-schema.json

Lines changed: 132 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,8 @@
712712
"mollweide",
713713
"hammer",
714714
"transverse mercator",
715-
"albers usa"
715+
"albers usa",
716+
"winkel tripel"
716717
]
717718
}
718719
},
@@ -838,6 +839,114 @@
838839
false
839840
]
840841
},
842+
"images": {
843+
"items": {
844+
"image": {
845+
"layer": {
846+
"description": "Specifies whether images are drawn below or above traces. When `xref` and `yref` are both set to `paper`, image is drawn below the entire plot area.",
847+
"dflt": "above",
848+
"role": "info",
849+
"valType": "enumerated",
850+
"values": [
851+
"below",
852+
"above"
853+
]
854+
},
855+
"opacity": {
856+
"description": "Sets the opacity of the image.",
857+
"dflt": 1,
858+
"max": 1,
859+
"min": 0,
860+
"role": "info",
861+
"valType": "number"
862+
},
863+
"role": "object",
864+
"sizex": {
865+
"description": "Sets the image container size horizontally. The image will be sized based on the `position` value. When `xref` is set to `paper`, units are sized relative to the plot width.",
866+
"dflt": 0,
867+
"role": "info",
868+
"valType": "number"
869+
},
870+
"sizey": {
871+
"description": "Sets the image container size vertically. The image will be sized based on the `position` value. When `yref` is set to `paper`, units are sized relative to the plot height.",
872+
"dflt": 0,
873+
"role": "info",
874+
"valType": "number"
875+
},
876+
"sizing": {
877+
"description": "Specifies which dimension of the image to constrain.",
878+
"dflt": "contain",
879+
"role": "info",
880+
"valType": "enumerated",
881+
"values": [
882+
"fill",
883+
"contain",
884+
"stretch"
885+
]
886+
},
887+
"source": {
888+
"description": "Specifies the URL of the image to be used. The URL must be accessible from the domain where the plot code is run, and can be either relative or absolute.",
889+
"role": "info",
890+
"valType": "string"
891+
},
892+
"x": {
893+
"description": "Sets the image's x position. When `xref` is set to `paper`, units are sized relative to the plot height. See `xref` for more info",
894+
"dflt": 0,
895+
"role": "info",
896+
"valType": "number"
897+
},
898+
"xanchor": {
899+
"description": "Sets the anchor for the x position",
900+
"dflt": "left",
901+
"role": "info",
902+
"valType": "enumerated",
903+
"values": [
904+
"left",
905+
"center",
906+
"right"
907+
]
908+
},
909+
"xref": {
910+
"description": "Sets the images's x coordinate axis. If set to a x axis id (e.g. *x* or *x2*), the `x` position refers to an x data coordinate If set to *paper*, the `x` position refers to the distance from the left of plot in normalized coordinates where *0* (*1*) corresponds to the left (right).",
911+
"dflt": "paper",
912+
"role": "info",
913+
"valType": "enumerated",
914+
"values": [
915+
"paper",
916+
"/^x([2-9]|[1-9][0-9]+)?$/"
917+
]
918+
},
919+
"y": {
920+
"description": "Sets the image's y position. When `yref` is set to `paper`, units are sized relative to the plot height. See `yref` for more info",
921+
"dflt": 0,
922+
"role": "info",
923+
"valType": "number"
924+
},
925+
"yanchor": {
926+
"description": "Sets the anchor for the y position.",
927+
"dflt": "top",
928+
"role": "info",
929+
"valType": "enumerated",
930+
"values": [
931+
"top",
932+
"middle",
933+
"bottom"
934+
]
935+
},
936+
"yref": {
937+
"description": "Sets the images's y coordinate axis. If set to a y axis id (e.g. *y* or *y2*), the `y` position refers to a y data coordinate. If set to *paper*, the `y` position refers to the distance from the bottom of the plot in normalized coordinates where *0* (*1*) corresponds to the bottom (top).",
938+
"dflt": "paper",
939+
"role": "info",
940+
"valType": "enumerated",
941+
"values": [
942+
"paper",
943+
"/^y([2-9]|[1-9][0-9]+)?$/"
944+
]
945+
}
946+
}
947+
},
948+
"role": "object"
949+
},
841950
"legend": {
842951
"bgcolor": {
843952
"description": "Sets the legend background color.",
@@ -877,6 +986,16 @@
877986
"valType": "number"
878987
}
879988
},
989+
"orientation": {
990+
"description": "Sets the orientation of the legend.",
991+
"dflt": "v",
992+
"role": "info",
993+
"valType": "enumerated",
994+
"values": [
995+
"v",
996+
"h"
997+
]
998+
},
880999
"role": "object",
8811000
"tracegroupgap": {
8821001
"description": "Sets the amount of vertical space (in px) between legend groups.",
@@ -6018,14 +6137,15 @@
60186137
"valType": "number"
60196138
},
60206139
"barmode": {
6021-
"description": "Determines how bars at the same location coordinate are displayed on the graph. With *stack*, the bars are stacked on top of one another With *group*, the bars are plotted next to one another centered around the shared location. With *overlay*, the bars are plotted over one another, you might need to an *opacity* to see multiple bars.",
6140+
"description": "Determines how bars at the same location coordinate are displayed on the graph. With *stack*, the bars are stacked on top of one another With *relative*, the bars are stacked on top of one another, with negative values below the axis, positive values above With *group*, the bars are plotted next to one another centered around the shared location. With *overlay*, the bars are plotted over one another, you might need to an *opacity* to see multiple bars.",
60226141
"dflt": "group",
60236142
"role": "info",
60246143
"valType": "enumerated",
60256144
"values": [
60266145
"stack",
60276146
"group",
6028-
"overlay"
6147+
"overlay",
6148+
"relative"
60296149
]
60306150
},
60316151
"barnorm": {
@@ -9298,14 +9418,15 @@
92989418
"valType": "number"
92999419
},
93009420
"barmode": {
9301-
"description": "Determines how bars at the same location coordinate are displayed on the graph. With *stack*, the bars are stacked on top of one another With *group*, the bars are plotted next to one another centered around the shared location. With *overlay*, the bars are plotted over one another, you might need to an *opacity* to see multiple bars.",
9421+
"description": "Determines how bars at the same location coordinate are displayed on the graph. With *stack*, the bars are stacked on top of one another With *relative*, the bars are stacked on top of one another, with negative values below the axis, positive values above With *group*, the bars are plotted next to one another centered around the shared location. With *overlay*, the bars are plotted over one another, you might need to an *opacity* to see multiple bars.",
93029422
"dflt": "group",
93039423
"role": "info",
93049424
"valType": "enumerated",
93059425
"values": [
93069426
"stack",
93079427
"group",
9308-
"overlay"
9428+
"overlay",
9429+
"relative"
93099430
]
93109431
},
93119432
"barnorm": {
@@ -15156,6 +15277,12 @@
1515615277
},
1515715278
"scattergl": {
1515815279
"attributes": {
15280+
"connectgaps": {
15281+
"description": "Determines whether or not gaps (i.e. {nan} or missing values) in the provided data arrays are connected.",
15282+
"dflt": false,
15283+
"role": "info",
15284+
"valType": "boolean"
15285+
},
1515915286
"dx": {
1516015287
"description": "Sets the x coordinate step. See `x0` for more info.",
1516115288
"dflt": 1,

plotly/offline/offline.py

Lines changed: 36 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,10 @@
1414

1515
import plotly
1616
from plotly import tools, utils
17-
from plotly.exceptions import PlotlyError
18-
1917

2018
try:
2119
import IPython
20+
from IPython.display import HTML, display
2221
_ipython_imported = True
2322
except ImportError:
2423
_ipython_imported = False
@@ -30,9 +29,6 @@
3029
_matplotlib_imported = False
3130

3231

33-
__PLOTLY_OFFLINE_INITIALIZED = False
34-
35-
3632
def download_plotlyjs(download_url):
3733
warnings.warn('''
3834
`download_plotlyjs` is deprecated and will be removed in the
@@ -50,26 +46,36 @@ def get_plotlyjs():
5046

5147
def init_notebook_mode():
5248
"""
53-
Initialize Plotly Offline mode in an IPython Notebook.
54-
Run this function at the start of an IPython notebook
55-
to load the necessary javascript files for creating
56-
Plotly graphs with plotly.offline.iplot.
49+
Initialize plotly.js in the browser if it hasn't been loaded into the DOM
50+
yet. This is an idempotent method and can and should be called from any
51+
offline methods that require plotly.js to be loaded into the notebook dom.
5752
"""
58-
if not tools._ipython_imported:
53+
warnings.warn('''
54+
`init_notebook_mode` is deprecated and will be removed in the
55+
next release. Notebook mode is now automatically initialized when
56+
notebook methods are invoked, so it is no
57+
longer necessary to manually initialize.
58+
''', DeprecationWarning)
59+
60+
if not _ipython_imported:
5961
raise ImportError('`iplot` can only run inside an IPython Notebook.')
60-
from IPython.display import HTML, display
6162

62-
global __PLOTLY_OFFLINE_INITIALIZED
63-
if not __PLOTLY_OFFLINE_INITIALIZED:
64-
display(HTML("<script type='text/javascript'>" +
65-
"define('plotly', function(require, exports, module) {" +
66-
get_plotlyjs() +
67-
"});" +
68-
"require(['plotly'], function(Plotly) {" +
69-
"window.Plotly = Plotly;" +
70-
"});" +
71-
"</script>"))
72-
__PLOTLY_OFFLINE_INITIALIZED = True
63+
script_inject = (
64+
''
65+
'<script type=\'text/javascript\'>'
66+
'if(!window.Plotly){{'
67+
'define(\'plotly\', function(require, exports, module) {{'
68+
'{script}'
69+
'}});'
70+
'require([\'plotly\'], function(Plotly) {{'
71+
'console.log(Plotly);'
72+
'window.Plotly = Plotly;'
73+
'}});'
74+
'}}'
75+
'</script>'
76+
'').format(script=get_plotlyjs())
77+
78+
display(HTML(script_inject))
7379

7480

7581
def _plot_html(figure_or_data, show_link, link_text,
@@ -171,25 +177,13 @@ def iplot(figure_or_data, show_link=True, link_text='Export to plot.ly',
171177
172178
Example:
173179
```
174-
from plotly.offline import init_notebook_mode, iplot
175-
init_notebook_mode()
180+
from plotly.offline import iplot
176181
177182
iplot([{'x': [1, 2, 3], 'y': [5, 2, 7]}])
178183
```
179184
"""
180-
if not __PLOTLY_OFFLINE_INITIALIZED:
181-
raise PlotlyError('\n'.join([
182-
'Plotly Offline mode has not been initialized in this notebook. '
183-
'Run: ',
184-
'',
185-
'import plotly',
186-
'plotly.offline.init_notebook_mode() '
187-
'# run at the start of every ipython notebook',
188-
]))
189-
if not tools._ipython_imported:
190-
raise ImportError('`iplot` can only run inside an IPython Notebook.')
191185

192-
from IPython.display import HTML, display
186+
init_notebook_mode()
193187

194188
plot_html, plotdivid, width, height = _plot_html(
195189
figure_or_data, show_link, link_text, validate,
@@ -421,11 +415,9 @@ def iplot_mpl(mpl_fig, resize=False, strip_style=False,
421415
422416
Example:
423417
```
424-
from plotly.offline import init_notebook_mode, iplot_mpl
418+
from plotly.offline import iplot_mpl
425419
import matplotlib.pyplot as plt
426420
427-
init_notebook_mode()
428-
429421
fig = plt.figure()
430422
x = [10, 15, 20, 25, 30]
431423
y = [100, 250, 200, 150, 300]
@@ -434,6 +426,8 @@ def iplot_mpl(mpl_fig, resize=False, strip_style=False,
434426
iplot_mpl(fig)
435427
```
436428
"""
429+
init_notebook_mode()
430+
437431
plotly_plot = tools.mpl_to_plotly(mpl_fig, resize, strip_style, verbose)
438432
return iplot(plotly_plot, show_link, link_text, validate)
439433

@@ -454,10 +448,9 @@ def enable_mpl_offline(resize=False, strip_style=False,
454448
455449
Example:
456450
```
457-
from plotly.offline import init_notebook_mode, enable_mpl_offline
451+
from plotly.offline import enable_mpl_offline
458452
import matplotlib.pyplot as plt
459453
460-
init_notebook_mode()
461454
enable_mpl_offline()
462455
463456
fig = plt.figure()
@@ -467,8 +460,8 @@ def enable_mpl_offline(resize=False, strip_style=False,
467460
fig
468461
```
469462
"""
470-
if not __PLOTLY_OFFLINE_INITIALIZED:
471-
init_notebook_mode()
463+
init_notebook_mode()
464+
472465
ip = IPython.core.getipython.get_ipython()
473466
formatter = ip.display_formatter.formatters['text/html']
474467
formatter.for_type(matplotlib.figure.Figure,

plotly/tests/test_optional/test_offline/test_offline.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,9 @@
2727

2828
class PlotlyOfflineTestCase(TestCase):
2929
def setUp(self):
30-
plotly.offline.offline.__PLOTLY_OFFLINE_INITIALIZED = False
30+
pass
3131

32-
@raises(plotly.exceptions.PlotlyError)
33-
def test_iplot_doesnt_work_before_you_call_init_notebook_mode(self):
32+
def test_iplot_works_wihout_calling_init_notebook_mode(self):
3433
plotly.offline.iplot([{}])
3534

3635
def test_iplot_works_after_you_call_init_notebook_mode(self):

0 commit comments

Comments
 (0)