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)