##// END OF EJS Templates
Initial support for supplying kernel logos in kernel spec
Thomas Kluyver -
Show More
1 NO CONTENT: new file 100644, binary diff hidden
@@ -1,102 +1,103 b''
1 1 // Copyright (c) IPython Development Team.
2 2 // Distributed under the terms of the Modified BSD License.
3 3
4 4 define([
5 5 'base/js/namespace',
6 6 'jquery',
7 7 'base/js/utils',
8 8 ], function(IPython, $, utils) {
9 9 "use strict";
10 10
11 11 var KernelSelector = function(selector, notebook) {
12 12 this.selector = selector;
13 13 this.notebook = notebook;
14 14 this.events = notebook.events;
15 15 this.current_selection = null;
16 16 this.kernelspecs = {};
17 17 if (this.selector !== undefined) {
18 18 this.element = $(selector);
19 19 this.request_kernelspecs();
20 20 }
21 21 this.bind_events();
22 22 // Make the object globally available for user convenience & inspection
23 23 IPython.kernelselector = this;
24 24 };
25 25
26 26 KernelSelector.prototype.request_kernelspecs = function() {
27 27 var url = utils.url_join_encode(this.notebook.base_url, 'api/kernelspecs');
28 28 utils.promising_ajax(url).then($.proxy(this._got_kernelspecs, this));
29 29 };
30 30
31 31 KernelSelector.prototype._got_kernelspecs = function(data) {
32 32 this.kernelspecs = data.kernelspecs;
33 33 var menu = this.element.find("#kernel_selector");
34 34 var change_kernel_submenu = $("#menu-change-kernel-submenu");
35 35 var keys = Object.keys(data.kernelspecs).sort(function (a, b) {
36 36 // sort by display_name
37 37 var da = data.kernelspecs[a].display_name;
38 38 var db = data.kernelspecs[b].display_name;
39 39 if (da === db) {
40 40 return 0;
41 41 } else if (da > db) {
42 42 return 1;
43 43 } else {
44 44 return -1;
45 45 }
46 46 });
47 47 for (var i = 0; i < keys.length; i++) {
48 48 var ks = this.kernelspecs[keys[i]];
49 49 var ksentry = $("<li>").attr("id", "kernel-" +ks.name).append($('<a>')
50 50 .attr('href', '#')
51 51 .click($.proxy(this.change_kernel, this, ks.name))
52 52 .text(ks.display_name));
53 53 menu.append(ksentry);
54 54
55 55 var ks_submenu_entry = $("<li>").attr("id", "kernel-submenu-"+ks.name).append($('<a>')
56 56 .attr('href', '#')
57 57 .click($.proxy(this.change_kernel, this, ks.name))
58 58 .text(ks.display_name));
59 59 change_kernel_submenu.append(ks_submenu_entry);
60 60 }
61 61 };
62 62
63 63 KernelSelector.prototype.change_kernel = function(kernel_name) {
64 64 if (kernel_name === this.current_selection) {
65 65 return;
66 66 }
67 67 var ks = this.kernelspecs[kernel_name];
68 68 try {
69 69 this.notebook.start_session(kernel_name);
70 70 } catch (e) {
71 71 if (e.name === 'SessionAlreadyStarting') {
72 72 console.log("Cannot change kernel while waiting for pending session start.");
73 73 } else {
74 74 // unhandled error
75 75 throw e;
76 76 }
77 77 // only trigger spec_changed if change was successful
78 78 return;
79 79 }
80 80 this.events.trigger('spec_changed.Kernel', ks);
81 81 };
82 82
83 83 KernelSelector.prototype.bind_events = function() {
84 84 var that = this;
85 85 this.events.on('spec_changed.Kernel', function(event, data) {
86 86 that.current_selection = data.name;
87 87 that.element.find("#current_kernel_spec").find('.kernel_name').text(data.display_name);
88 that.element.find("#current_kernel_logo").attr("src", "/kernelspecs/"+data.name+"/logo-32.png");
88 89 });
89 90
90 91 this.events.on('kernel_created.Session', function(event, data) {
91 92 if (data.kernel.name !== that.current_selection) {
92 93 // If we created a 'python' session, we only know if it's Python
93 94 // 3 or 2 on the server's reply, so we fire the event again to
94 95 // set things up.
95 96 var ks = that.kernelspecs[data.kernel.name];
96 97 that.events.trigger('spec_changed.Kernel', ks);
97 98 }
98 99 });
99 100 };
100 101
101 102 return {'KernelSelector': KernelSelector};
102 103 });
@@ -1,331 +1,332 b''
1 1 {% extends "page.html" %}
2 2
3 3 {% block stylesheet %}
4 4
5 5 {% if mathjax_url %}
6 6 <script type="text/javascript" src="{{mathjax_url}}?config=TeX-AMS_HTML-full&delayStartupUntil=configured" charset="utf-8"></script>
7 7 {% endif %}
8 8 <script type="text/javascript">
9 9 // MathJax disabled, set as null to distingish from *missing* MathJax,
10 10 // where it will be undefined, and should prompt a dialog later.
11 11 window.mathjax_url = "{{mathjax_url}}";
12 12 </script>
13 13
14 14 <link rel="stylesheet" href="{{ static_url("components/bootstrap-tour/build/css/bootstrap-tour.min.css") }}" type="text/css" />
15 15 <link rel="stylesheet" href="{{ static_url("components/codemirror/lib/codemirror.css") }}">
16 16
17 17 {{super()}}
18 18
19 19 <link rel="stylesheet" href="{{ static_url("notebook/css/override.css") }}" type="text/css" />
20 20
21 21 {% endblock %}
22 22
23 23 {% block params %}
24 24
25 25 data-project="{{project}}"
26 26 data-base-url="{{base_url}}"
27 27 data-ws-url="{{ws_url}}"
28 28 data-notebook-name="{{notebook_name}}"
29 29 data-notebook-path="{{notebook_path}}"
30 30 class="notebook_app"
31 31
32 32 {% endblock %}
33 33
34 34
35 35 {% block headercontainer %}
36 36
37 37
38 38 <span id="save_widget" class="nav pull-left">
39 39 <span id="notebook_name"></span>
40 40 <span id="checkpoint_status"></span>
41 41 <span id="autosave_status"></span>
42 42 </span>
43 43
44 44 <span id="kernel_selector_widget" class="pull-right dropdown">
45 <img id="current_kernel_logo" src="/kernelspecs/python/logo-32.png"/>
45 46 <button class="dropdown-toggle btn btn-sm navbar-btn" data-toggle="dropdown" type='button' id="current_kernel_spec">
46 47 <span class='kernel_name'>Kernel</span>
47 48 <span class="caret"></span>
48 49 </button>
49 50 <ul id="kernel_selector" class="dropdown-menu">
50 51 </ul>
51 52 </span>
52 53
53 54 {% endblock headercontainer %}
54 55
55 56 {% block header %}
56 57 <div id="menubar-container" class="container">
57 58 <div id="menubar">
58 59 <div id="menus" class="navbar navbar-default" role="navigation">
59 60 <div class="container-fluid">
60 61 <button type="button" class="btn btn-default navbar-btn navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
61 62 <i class="fa fa-bars"></i>
62 63 <span class="navbar-text">Menu</span>
63 64 </button>
64 65 <p id="kernel_indicator" class="navbar-text">
65 66 <i id="kernel_indicator_icon"></i>
66 67 </p>
67 68 <p id="modal_indicator" class="navbar-text">
68 69 <i id="modal_indicator_icon"></i>
69 70 </p>
70 71 <span id="notification_area"></span>
71 72 <div class="navbar-collapse collapse">
72 73 <ul class="nav navbar-nav">
73 74 <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">File</a>
74 75 <ul id="file_menu" class="dropdown-menu">
75 76 <li id="new_notebook"
76 77 title="Make a new notebook (Opens a new window)">
77 78 <a href="#">New</a></li>
78 79 <li id="open_notebook"
79 80 title="Opens a new window with the Dashboard view">
80 81 <a href="#">Open...</a></li>
81 82 <!-- <hr/> -->
82 83 <li class="divider"></li>
83 84 <li id="copy_notebook"
84 85 title="Open a copy of this notebook's contents and start a new kernel">
85 86 <a href="#">Make a Copy...</a></li>
86 87 <li id="rename_notebook"><a href="#">Rename...</a></li>
87 88 <li id="save_checkpoint"><a href="#">Save and Checkpoint</a></li>
88 89 <!-- <hr/> -->
89 90 <li class="divider"></li>
90 91 <li id="restore_checkpoint" class="dropdown-submenu"><a href="#">Revert to Checkpoint</a>
91 92 <ul class="dropdown-menu">
92 93 <li><a href="#"></a></li>
93 94 <li><a href="#"></a></li>
94 95 <li><a href="#"></a></li>
95 96 <li><a href="#"></a></li>
96 97 <li><a href="#"></a></li>
97 98 </ul>
98 99 </li>
99 100 <li class="divider"></li>
100 101 <li id="print_preview"><a href="#">Print Preview</a></li>
101 102 <li class="dropdown-submenu"><a href="#">Download as</a>
102 103 <ul class="dropdown-menu">
103 104 <li id="download_ipynb"><a href="#">IPython Notebook (.ipynb)</a></li>
104 105 <li id="download_script"><a href="#">Script</a></li>
105 106 <li id="download_html"><a href="#">HTML (.html)</a></li>
106 107 <li id="download_rst"><a href="#">reST (.rst)</a></li>
107 108 <li id="download_pdf"><a href="#">PDF (.pdf)</a></li>
108 109 </ul>
109 110 </li>
110 111 <li class="divider"></li>
111 112 <li id="trust_notebook"
112 113 title="Trust the output of this notebook">
113 114 <a href="#" >Trust Notebook</a></li>
114 115 <li class="divider"></li>
115 116 <li id="kill_and_exit"
116 117 title="Shutdown this notebook's kernel, and close this window">
117 118 <a href="#" >Close and halt</a></li>
118 119 </ul>
119 120 </li>
120 121 <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Edit</a>
121 122 <ul id="edit_menu" class="dropdown-menu">
122 123 <li id="cut_cell"><a href="#">Cut Cell</a></li>
123 124 <li id="copy_cell"><a href="#">Copy Cell</a></li>
124 125 <li id="paste_cell_above" class="disabled"><a href="#">Paste Cell Above</a></li>
125 126 <li id="paste_cell_below" class="disabled"><a href="#">Paste Cell Below</a></li>
126 127 <li id="paste_cell_replace" class="disabled"><a href="#">Paste Cell &amp; Replace</a></li>
127 128 <li id="delete_cell"><a href="#">Delete Cell</a></li>
128 129 <li id="undelete_cell" class="disabled"><a href="#">Undo Delete Cell</a></li>
129 130 <li class="divider"></li>
130 131 <li id="split_cell"><a href="#">Split Cell</a></li>
131 132 <li id="merge_cell_above"><a href="#">Merge Cell Above</a></li>
132 133 <li id="merge_cell_below"><a href="#">Merge Cell Below</a></li>
133 134 <li class="divider"></li>
134 135 <li id="move_cell_up"><a href="#">Move Cell Up</a></li>
135 136 <li id="move_cell_down"><a href="#">Move Cell Down</a></li>
136 137 <li class="divider"></li>
137 138 <li id="edit_nb_metadata"><a href="#">Edit Notebook Metadata</a></li>
138 139 </ul>
139 140 </li>
140 141 <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">View</a>
141 142 <ul id="view_menu" class="dropdown-menu">
142 143 <li id="toggle_header"
143 144 title="Show/Hide the IPython Notebook logo and notebook title (above menu bar)">
144 145 <a href="#">Toggle Header</a></li>
145 146 <li id="toggle_toolbar"
146 147 title="Show/Hide the action icons (below menu bar)">
147 148 <a href="#">Toggle Toolbar</a></li>
148 149 </ul>
149 150 </li>
150 151 <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Insert</a>
151 152 <ul id="insert_menu" class="dropdown-menu">
152 153 <li id="insert_cell_above"
153 154 title="Insert an empty Code cell above the currently active cell">
154 155 <a href="#">Insert Cell Above</a></li>
155 156 <li id="insert_cell_below"
156 157 title="Insert an empty Code cell below the currently active cell">
157 158 <a href="#">Insert Cell Below</a></li>
158 159 </ul>
159 160 </li>
160 161 <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Cell</a>
161 162 <ul id="cell_menu" class="dropdown-menu">
162 163 <li id="run_cell" title="Run this cell, and move cursor to the next one">
163 164 <a href="#">Run</a></li>
164 165 <li id="run_cell_select_below" title="Run this cell, select below">
165 166 <a href="#">Run and Select Below</a></li>
166 167 <li id="run_cell_insert_below" title="Run this cell, insert below">
167 168 <a href="#">Run and Insert Below</a></li>
168 169 <li id="run_all_cells" title="Run all cells in the notebook">
169 170 <a href="#">Run All</a></li>
170 171 <li id="run_all_cells_above" title="Run all cells above (but not including) this cell">
171 172 <a href="#">Run All Above</a></li>
172 173 <li id="run_all_cells_below" title="Run this cell and all cells below it">
173 174 <a href="#">Run All Below</a></li>
174 175 <li class="divider"></li>
175 176 <li id="change_cell_type" class="dropdown-submenu"
176 177 title="All cells in the notebook have a cell type. By default, new cells are created as 'Code' cells">
177 178 <a href="#">Cell Type</a>
178 179 <ul class="dropdown-menu">
179 180 <li id="to_code"
180 181 title="Contents will be sent to the kernel for execution, and output will display in the footer of cell">
181 182 <a href="#">Code</a></li>
182 183 <li id="to_markdown"
183 184 title="Contents will be rendered as HTML and serve as explanatory text">
184 185 <a href="#">Markdown</a></li>
185 186 <li id="to_raw"
186 187 title="Contents will pass through nbconvert unmodified">
187 188 <a href="#">Raw NBConvert</a></li>
188 189 </ul>
189 190 </li>
190 191 <li class="divider"></li>
191 192 <li id="current_outputs" class="dropdown-submenu"><a href="#">Current Output</a>
192 193 <ul class="dropdown-menu">
193 194 <li id="toggle_current_output"
194 195 title="Hide/Show the output of the current cell">
195 196 <a href="#">Toggle</a>
196 197 </li>
197 198 <li id="toggle_current_output_scroll"
198 199 title="Scroll the output of the current cell">
199 200 <a href="#">Toggle Scrolling</a>
200 201 </li>
201 202 <li id="clear_current_output"
202 203 title="Clear the output of the current cell">
203 204 <a href="#">Clear</a>
204 205 </li>
205 206 </ul>
206 207 </li>
207 208 <li id="all_outputs" class="dropdown-submenu"><a href="#">All Output</a>
208 209 <ul class="dropdown-menu">
209 210 <li id="toggle_all_output"
210 211 title="Hide/Show the output of all cells">
211 212 <a href="#">Toggle</a>
212 213 </li>
213 214 <li id="toggle_all_output_scroll"
214 215 title="Scroll the output of all cells">
215 216 <a href="#">Toggle Scrolling</a>
216 217 </li>
217 218 <li id="clear_all_output"
218 219 title="Clear the output of all cells">
219 220 <a href="#">Clear</a>
220 221 </li>
221 222 </ul>
222 223 </li>
223 224 </ul>
224 225 </li>
225 226 <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Kernel</a>
226 227 <ul id="kernel_menu" class="dropdown-menu">
227 228 <li id="int_kernel"
228 229 title="Send KeyboardInterrupt (CTRL-C) to the Kernel">
229 230 <a href="#">Interrupt</a>
230 231 </li>
231 232 <li id="restart_kernel"
232 233 title="Restart the Kernel">
233 234 <a href="#">Restart</a>
234 235 </li>
235 236 <li id="reconnect_kernel"
236 237 title="Reconnect to the Kernel">
237 238 <a href="#">Reconnect</a>
238 239 </li>
239 240 <li class="divider"></li>
240 241 <li id="menu-change-kernel" class="dropdown-submenu">
241 242 <a href="#">Change kernel</a>
242 243 <ul class="dropdown-menu" id="menu-change-kernel-submenu"></ul>
243 244 </li>
244 245 </ul>
245 246 </li>
246 247 <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Help</a>
247 248 <ul id="help_menu" class="dropdown-menu">
248 249 <li id="notebook_tour" title="A quick tour of the notebook user interface"><a href="#">User Interface Tour</a></li>
249 250 <li id="keyboard_shortcuts" title="Opens a tooltip with all keyboard shortcuts"><a href="#">Keyboard Shortcuts</a></li>
250 251 <li class="divider"></li>
251 252 {% set
252 253 sections = (
253 254 (
254 255 ("http://ipython.org/documentation.html","IPython Help",True),
255 256 ("http://nbviewer.ipython.org/github/ipython/ipython/tree/2.x/examples/Index.ipynb", "Notebook Help", True),
256 257 ),(
257 258 ("http://docs.python.org","Python",True),
258 259 ("http://help.github.com/articles/github-flavored-markdown","Markdown",True),
259 260 ("http://docs.scipy.org/doc/numpy/reference/","NumPy",True),
260 261 ("http://docs.scipy.org/doc/scipy/reference/","SciPy",True),
261 262 ("http://matplotlib.org/contents.html","Matplotlib",True),
262 263 ("http://docs.sympy.org/latest/index.html","SymPy",True),
263 264 ("http://pandas.pydata.org/pandas-docs/stable/","pandas", True)
264 265 )
265 266 )
266 267 %}
267 268
268 269 {% for helplinks in sections %}
269 270 {% for link in helplinks %}
270 271 <li><a href="{{link[0]}}" {{'target="_blank" title="Opens in a new window"' if link[2]}}>
271 272 {{'<i class="fa fa-external-link menu-icon pull-right"></i>' if link[2]}}
272 273 {{link[1]}}
273 274 </a></li>
274 275 {% endfor %}
275 276 {% if not loop.last %}
276 277 <li class="divider"></li>
277 278 {% endif %}
278 279 {% endfor %}
279 280 <li class="divider"></li>
280 281 <li title="About IPython Notebook"><a id="notebook_about" href="#">About</a></li>
281 282 </ul>
282 283 </li>
283 284 </ul>
284 285 </div>
285 286 </div>
286 287 </div>
287 288 </div>
288 289
289 290 <div id="maintoolbar" class="navbar">
290 291 <div class="toolbar-inner navbar-inner navbar-nobg">
291 292 <div id="maintoolbar-container" class="container"></div>
292 293 </div>
293 294 </div>
294 295 </div>
295 296
296 297 <div class="lower-header-bar"></div>
297 298 {% endblock header %}
298 299
299 300 {% block site %}
300 301
301 302
302 303 <div id="ipython-main-app">
303 304 <div id="notebook_panel">
304 305 <div id="notebook"></div>
305 306 </div>
306 307 </div>
307 308
308 309 <div id="pager">
309 310 <div id="pager-contents">
310 311 <div id="pager-container" class="container"></div>
311 312 </div>
312 313 <div id='pager-button-area'></div>
313 314 </div>
314 315
315 316 <div id='tooltip' class='ipython_tooltip' style='display:none'></div>
316 317
317 318
318 319 {% endblock %}
319 320
320 321
321 322 {% block script %}
322 323 {{super()}}
323 324 <script type="text/javascript">
324 325 sys_info = {{sys_info}};
325 326 </script>
326 327
327 328 <script src="{{ static_url("components/text-encoding/lib/encoding.js") }}" charset="utf-8"></script>
328 329
329 330 <script src="{{ static_url("notebook/js/main.js") }}" charset="utf-8"></script>
330 331
331 332 {% endblock %}
@@ -1,213 +1,215 b''
1 1 import io
2 2 import json
3 3 import os
4 4 import shutil
5 5 import sys
6 6
7 7 pjoin = os.path.join
8 8
9 9 from IPython.utils.path import get_ipython_dir
10 10 from IPython.utils.py3compat import PY3
11 11 from IPython.utils.traitlets import HasTraits, List, Unicode, Dict, Any
12 12 from .launcher import make_ipkernel_cmd
13 13
14 14 if os.name == 'nt':
15 15 programdata = os.environ.get('PROGRAMDATA', None)
16 16 if programdata:
17 17 SYSTEM_KERNEL_DIRS = [pjoin(programdata, 'ipython', 'kernels')]
18 18 else: # PROGRAMDATA is not defined by default on XP.
19 19 SYSTEM_KERNEL_DIRS = []
20 20 else:
21 21 SYSTEM_KERNEL_DIRS = ["/usr/share/ipython/kernels",
22 22 "/usr/local/share/ipython/kernels",
23 23 ]
24 24
25 25 NATIVE_KERNEL_NAME = 'python3' if PY3 else 'python2'
26 26
27 27 def _pythonfirst(s):
28 28 "Sort key function that will put strings starting with 'python' first."
29 29 if s == NATIVE_KERNEL_NAME:
30 30 return ' ' + s # Two spaces to sort this first of all
31 31 elif s.startswith('python'):
32 32 # Space is not valid in kernel names, so this should sort first
33 33 return ' ' + s
34 34 return s
35 35
36 36 class KernelSpec(HasTraits):
37 37 argv = List()
38 38 display_name = Unicode()
39 39 env = Dict()
40 40 resource_dir = Unicode()
41 41
42 42 @classmethod
43 43 def from_resource_dir(cls, resource_dir):
44 44 """Create a KernelSpec object by reading kernel.json
45 45
46 46 Pass the path to the *directory* containing kernel.json.
47 47 """
48 48 kernel_file = pjoin(resource_dir, 'kernel.json')
49 49 with io.open(kernel_file, 'r', encoding='utf-8') as f:
50 50 kernel_dict = json.load(f)
51 51 return cls(resource_dir=resource_dir, **kernel_dict)
52 52
53 53 def to_dict(self):
54 54 d = dict(argv=self.argv,
55 55 env=self.env,
56 56 display_name=self.display_name,
57 57 )
58 58
59 59 return d
60 60
61 61 def to_json(self):
62 62 return json.dumps(self.to_dict())
63 63
64 64 def _is_kernel_dir(path):
65 65 """Is ``path`` a kernel directory?"""
66 66 return os.path.isdir(path) and os.path.isfile(pjoin(path, 'kernel.json'))
67 67
68 68 def _list_kernels_in(dir):
69 69 """Return a mapping of kernel names to resource directories from dir.
70 70
71 71 If dir is None or does not exist, returns an empty dict.
72 72 """
73 73 if dir is None or not os.path.isdir(dir):
74 74 return {}
75 75 return {f.lower(): pjoin(dir, f) for f in os.listdir(dir)
76 76 if _is_kernel_dir(pjoin(dir, f))}
77 77
78 78 class NoSuchKernel(KeyError):
79 79 def __init__(self, name):
80 80 self.name = name
81 81
82 82 class KernelSpecManager(HasTraits):
83 83 ipython_dir = Unicode()
84 84 def _ipython_dir_default(self):
85 85 return get_ipython_dir()
86 86
87 87 user_kernel_dir = Unicode()
88 88 def _user_kernel_dir_default(self):
89 89 return pjoin(self.ipython_dir, 'kernels')
90 90
91 91 kernel_dirs = List(
92 92 help="List of kernel directories to search. Later ones take priority over earlier."
93 93 )
94 94 def _kernel_dirs_default(self):
95 95 return SYSTEM_KERNEL_DIRS + [
96 96 self.user_kernel_dir,
97 97 ]
98 98
99 99 @property
100 100 def _native_kernel_dict(self):
101 101 """Makes a kernel directory for the native kernel.
102 102
103 103 The native kernel is the kernel using the same Python runtime as this
104 104 process. This will put its informatino in the user kernels directory.
105 105 """
106 106 return {'argv': make_ipkernel_cmd(),
107 107 'display_name': 'IPython (Python %d)' % (3 if PY3 else 2),
108 108 }
109 109
110 110 @property
111 111 def _native_kernel_resource_dir(self):
112 # TODO: This may be different when we actually have any resources
113 return os.path.dirname(__file__)
112 return pjoin(os.path.dirname(__file__), 'resources')
114 113
115 114 def find_kernel_specs(self):
116 115 """Returns a dict mapping kernel names to resource directories."""
117 116 d = {}
118 117 for kernel_dir in self.kernel_dirs:
119 118 d.update(_list_kernels_in(kernel_dir))
120 119
121 120 d[NATIVE_KERNEL_NAME] = self._native_kernel_resource_dir
122 121 return d
123 122 # TODO: Caching?
124 123
125 124 def get_kernel_spec(self, kernel_name):
126 125 """Returns a :class:`KernelSpec` instance for the given kernel_name.
127 126
128 127 Raises :exc:`NoSuchKernel` if the given kernel name is not found.
129 128 """
130 129 if kernel_name in {'python', NATIVE_KERNEL_NAME}:
131 return KernelSpec(self._native_kernel_resource_dir, **self._native_kernel_dict)
130 return KernelSpec(resource_dir=self._native_kernel_resource_dir,
131 **self._native_kernel_dict)
132 132
133 133 d = self.find_kernel_specs()
134 134 try:
135 135 resource_dir = d[kernel_name.lower()]
136 136 except KeyError:
137 137 raise NoSuchKernel(kernel_name)
138 138 return KernelSpec.from_resource_dir(resource_dir)
139 139
140 140 def _get_destination_dir(self, kernel_name, system=False):
141 141 if system:
142 142 if SYSTEM_KERNEL_DIRS:
143 143 return os.path.join(SYSTEM_KERNEL_DIRS[-1], kernel_name)
144 144 else:
145 145 raise EnvironmentError("No system kernel directory is available")
146 146 else:
147 147 return os.path.join(self.user_kernel_dir, kernel_name)
148 148
149 149 def install_kernel_spec(self, source_dir, kernel_name=None, system=False,
150 150 replace=False):
151 151 """Install a kernel spec by copying its directory.
152 152
153 153 If ``kernel_name`` is not given, the basename of ``source_dir`` will
154 154 be used.
155 155
156 156 If ``system`` is True, it will attempt to install into the systemwide
157 157 kernel registry. If the process does not have appropriate permissions,
158 158 an :exc:`OSError` will be raised.
159 159
160 160 If ``replace`` is True, this will replace an existing kernel of the same
161 161 name. Otherwise, if the destination already exists, an :exc:`OSError`
162 162 will be raised.
163 163 """
164 164 if not kernel_name:
165 165 kernel_name = os.path.basename(source_dir)
166 166 kernel_name = kernel_name.lower()
167 167
168 168 destination = self._get_destination_dir(kernel_name, system=system)
169 169
170 170 if replace and os.path.isdir(destination):
171 171 shutil.rmtree(destination)
172 172
173 173 shutil.copytree(source_dir, destination)
174 174
175 175 def install_native_kernel_spec(self, system=False):
176 176 """Install the native kernel spec to the filesystem
177 177
178 178 This allows a Python 3 frontend to use a Python 2 kernel, or vice versa.
179 179 The kernelspec will be written pointing to the Python executable on
180 180 which this is run.
181 181
182 182 If ``system`` is True, it will attempt to install into the systemwide
183 183 kernel registry. If the process does not have appropriate permissions,
184 184 an :exc:`OSError` will be raised.
185 185 """
186 186 path = self._get_destination_dir(NATIVE_KERNEL_NAME, system=system)
187 187 os.makedirs(path, mode=0o755)
188 188 with open(pjoin(path, 'kernel.json'), 'w') as f:
189 189 json.dump(self._native_kernel_dict, f, indent=1)
190 # TODO: Copy icons into directory
190 copy_from = self._native_kernel_resource_dir
191 for file in os.listdir(copy_from):
192 shutil.copy(pjoin(copy_from, file), path)
191 193 return path
192 194
193 195 def find_kernel_specs():
194 196 """Returns a dict mapping kernel names to resource directories."""
195 197 return KernelSpecManager().find_kernel_specs()
196 198
197 199 def get_kernel_spec(kernel_name):
198 200 """Returns a :class:`KernelSpec` instance for the given kernel_name.
199 201
200 202 Raises KeyError if the given kernel name is not found.
201 203 """
202 204 return KernelSpecManager().get_kernel_spec(kernel_name)
203 205
204 206 def install_kernel_spec(source_dir, kernel_name=None, system=False, replace=False):
205 207 return KernelSpecManager().install_kernel_spec(source_dir, kernel_name,
206 208 system, replace)
207 209
208 210 install_kernel_spec.__doc__ = KernelSpecManager.install_kernel_spec.__doc__
209 211
210 212 def install_native_kernel_spec(self, system=False):
211 213 return KernelSpecManager().install_native_kernel_spec(system=system)
212 214
213 215 install_native_kernel_spec.__doc__ = KernelSpecManager.install_native_kernel_spec.__doc__
General Comments 0
You need to be logged in to leave comments. Login now