##// END OF EJS Templates
Add documentation to check_nbextension, and switch order of parameters to be consistent with install_nbextension.
Jason Grout -
Show More
@@ -1,349 +1,361 b''
1 # coding: utf-8
1 # coding: utf-8
2 """Utilities for installing Javascript extensions for the notebook"""
2 """Utilities for installing Javascript extensions for the notebook"""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 from __future__ import print_function
7 from __future__ import print_function
8
8
9 import os
9 import os
10 import shutil
10 import shutil
11 import sys
11 import sys
12 import tarfile
12 import tarfile
13 import zipfile
13 import zipfile
14 import uuid
14 import uuid
15 from os.path import basename, join as pjoin
15 from os.path import basename, join as pjoin
16
16
17 # Deferred imports
17 # Deferred imports
18 try:
18 try:
19 from urllib.parse import urlparse # Py3
19 from urllib.parse import urlparse # Py3
20 from urllib.request import urlretrieve
20 from urllib.request import urlretrieve
21 except ImportError:
21 except ImportError:
22 from urlparse import urlparse
22 from urlparse import urlparse
23 from urllib import urlretrieve
23 from urllib import urlretrieve
24
24
25 from IPython.utils.path import get_ipython_dir, ensure_dir_exists
25 from IPython.utils.path import get_ipython_dir, ensure_dir_exists
26 from IPython.utils.py3compat import string_types, cast_unicode_py2
26 from IPython.utils.py3compat import string_types, cast_unicode_py2
27 from IPython.utils.tempdir import TemporaryDirectory
27 from IPython.utils.tempdir import TemporaryDirectory
28
28
29 class ArgumentConflict(ValueError):
29 class ArgumentConflict(ValueError):
30 pass
30 pass
31
31
32 # Packagers: modify the next block if you store system-installed nbextensions elsewhere (unlikely)
32 # Packagers: modify the next block if you store system-installed nbextensions elsewhere (unlikely)
33 SYSTEM_NBEXTENSIONS_DIRS = []
33 SYSTEM_NBEXTENSIONS_DIRS = []
34
34
35 if os.name == 'nt':
35 if os.name == 'nt':
36 programdata = os.environ.get('PROGRAMDATA', None)
36 programdata = os.environ.get('PROGRAMDATA', None)
37 if programdata: # PROGRAMDATA is not defined by default on XP.
37 if programdata: # PROGRAMDATA is not defined by default on XP.
38 SYSTEM_NBEXTENSIONS_DIRS = [pjoin(programdata, 'jupyter', 'nbextensions')]
38 SYSTEM_NBEXTENSIONS_DIRS = [pjoin(programdata, 'jupyter', 'nbextensions')]
39 prefixes = []
39 prefixes = []
40 else:
40 else:
41 prefixes = [os.path.sep + pjoin('usr', 'local'), os.path.sep + 'usr']
41 prefixes = [os.path.sep + pjoin('usr', 'local'), os.path.sep + 'usr']
42
42
43 # add sys.prefix at the front
43 # add sys.prefix at the front
44 if sys.prefix not in prefixes:
44 if sys.prefix not in prefixes:
45 prefixes.insert(0, sys.prefix)
45 prefixes.insert(0, sys.prefix)
46
46
47 for prefix in prefixes:
47 for prefix in prefixes:
48 nbext = pjoin(prefix, 'share', 'jupyter', 'nbextensions')
48 nbext = pjoin(prefix, 'share', 'jupyter', 'nbextensions')
49 if nbext not in SYSTEM_NBEXTENSIONS_DIRS:
49 if nbext not in SYSTEM_NBEXTENSIONS_DIRS:
50 SYSTEM_NBEXTENSIONS_DIRS.append(nbext)
50 SYSTEM_NBEXTENSIONS_DIRS.append(nbext)
51
51
52 if os.name == 'nt':
52 if os.name == 'nt':
53 # PROGRAMDATA
53 # PROGRAMDATA
54 SYSTEM_NBEXTENSIONS_INSTALL_DIR = SYSTEM_NBEXTENSIONS_DIRS[-1]
54 SYSTEM_NBEXTENSIONS_INSTALL_DIR = SYSTEM_NBEXTENSIONS_DIRS[-1]
55 else:
55 else:
56 # /usr/local
56 # /usr/local
57 SYSTEM_NBEXTENSIONS_INSTALL_DIR = SYSTEM_NBEXTENSIONS_DIRS[-2]
57 SYSTEM_NBEXTENSIONS_INSTALL_DIR = SYSTEM_NBEXTENSIONS_DIRS[-2]
58
58
59
59
60 def _should_copy(src, dest, verbose=1):
60 def _should_copy(src, dest, verbose=1):
61 """should a file be copied?"""
61 """should a file be copied?"""
62 if not os.path.exists(dest):
62 if not os.path.exists(dest):
63 return True
63 return True
64 if os.stat(src).st_mtime - os.stat(dest).st_mtime > 1e-6:
64 if os.stat(src).st_mtime - os.stat(dest).st_mtime > 1e-6:
65 # we add a fudge factor to work around a bug in python 2.x
65 # we add a fudge factor to work around a bug in python 2.x
66 # that was fixed in python 3.x: http://bugs.python.org/issue12904
66 # that was fixed in python 3.x: http://bugs.python.org/issue12904
67 if verbose >= 2:
67 if verbose >= 2:
68 print("%s is out of date" % dest)
68 print("%s is out of date" % dest)
69 return True
69 return True
70 if verbose >= 2:
70 if verbose >= 2:
71 print("%s is up to date" % dest)
71 print("%s is up to date" % dest)
72 return False
72 return False
73
73
74
74
75 def _maybe_copy(src, dest, verbose=1):
75 def _maybe_copy(src, dest, verbose=1):
76 """copy a file if it needs updating"""
76 """copy a file if it needs updating"""
77 if _should_copy(src, dest, verbose):
77 if _should_copy(src, dest, verbose):
78 if verbose >= 1:
78 if verbose >= 1:
79 print("copying %s -> %s" % (src, dest))
79 print("copying %s -> %s" % (src, dest))
80 try:
80 try:
81 shutil.copy2(src, dest)
81 shutil.copy2(src, dest)
82 except IOError as e:
82 except IOError as e:
83 print(str(e), file=sys.stderr)
83 print(str(e), file=sys.stderr)
84
84
85 def _safe_is_tarfile(path):
85 def _safe_is_tarfile(path):
86 """safe version of is_tarfile, return False on IOError"""
86 """safe version of is_tarfile, return False on IOError"""
87 try:
87 try:
88 return tarfile.is_tarfile(path)
88 return tarfile.is_tarfile(path)
89 except IOError:
89 except IOError:
90 return False
90 return False
91
91
92
92
93 def _get_nbext_dir(nbextensions_dir=None, user=False, prefix=None):
93 def _get_nbext_dir(nbextensions_dir=None, user=False, prefix=None):
94 """Return the nbextension directory specified"""
94 """Return the nbextension directory specified"""
95 if sum(map(bool, [user, prefix, nbextensions_dir])) > 1:
95 if sum(map(bool, [user, prefix, nbextensions_dir])) > 1:
96 raise ArgumentConflict("Cannot specify more than one of user, prefix, or nbextensions_dir.")
96 raise ArgumentConflict("Cannot specify more than one of user, prefix, or nbextensions_dir.")
97 if user:
97 if user:
98 nbext = pjoin(get_ipython_dir(), u'nbextensions')
98 nbext = pjoin(get_ipython_dir(), u'nbextensions')
99 else:
99 else:
100 if prefix:
100 if prefix:
101 nbext = pjoin(prefix, 'share', 'jupyter', 'nbextensions')
101 nbext = pjoin(prefix, 'share', 'jupyter', 'nbextensions')
102 elif nbextensions_dir:
102 elif nbextensions_dir:
103 nbext = nbextensions_dir
103 nbext = nbextensions_dir
104 else:
104 else:
105 nbext = SYSTEM_NBEXTENSIONS_INSTALL_DIR
105 nbext = SYSTEM_NBEXTENSIONS_INSTALL_DIR
106 return nbext
106 return nbext
107
107
108
108
109 def check_nbextension(files, nbextensions_dir=None, user=False, prefix=None):
109 def check_nbextension(files, user=False, prefix=None, nbextensions_dir=None):
110 """Check whether nbextension files have been installed
110 """Check whether nbextension files have been installed
111
111
112 files should be a list of relative paths within nbextensions.
113
114 Returns True if all files are found, False if any are missing.
112 Returns True if all files are found, False if any are missing.
113
114 Parameters
115 ----------
116
117 files : list(paths)
118 a list of relative paths within nbextensions.
119 user : bool [default: False]
120 Whether to check the user's .ipython/nbextensions directory.
121 Otherwise check a system-wide install (e.g. /usr/local/share/jupyter/nbextensions).
122 prefix : str [optional]
123 Specify install prefix, if it should differ from default (e.g. /usr/local).
124 Will check prefix/share/jupyter/nbextensions
125 nbextensions_dir : str [optional]
126 Specify absolute path of nbextensions directory explicitly.
115 """
127 """
116 nbext = _get_nbext_dir(nbextensions_dir, user, prefix)
128 nbext = _get_nbext_dir(nbextensions_dir, user, prefix)
117 # make sure nbextensions dir exists
129 # make sure nbextensions dir exists
118 if not os.path.exists(nbext):
130 if not os.path.exists(nbext):
119 return False
131 return False
120
132
121 if isinstance(files, string_types):
133 if isinstance(files, string_types):
122 # one file given, turn it into a list
134 # one file given, turn it into a list
123 files = [files]
135 files = [files]
124
136
125 return all(os.path.exists(pjoin(nbext, f)) for f in files)
137 return all(os.path.exists(pjoin(nbext, f)) for f in files)
126
138
127
139
128 def install_nbextension(files, overwrite=False, symlink=False, user=False, prefix=None, nbextensions_dir=None, verbose=1):
140 def install_nbextension(files, overwrite=False, symlink=False, user=False, prefix=None, nbextensions_dir=None, verbose=1):
129 """Install a Javascript extension for the notebook
141 """Install a Javascript extension for the notebook
130
142
131 Stages files and/or directories into the nbextensions directory.
143 Stages files and/or directories into the nbextensions directory.
132 By default, this compares modification time, and only stages files that need updating.
144 By default, this compares modification time, and only stages files that need updating.
133 If `overwrite` is specified, matching files are purged before proceeding.
145 If `overwrite` is specified, matching files are purged before proceeding.
134
146
135 Parameters
147 Parameters
136 ----------
148 ----------
137
149
138 files : list(paths or URLs) or dict(install_name: path or URL)
150 files : list(paths or URLs) or dict(install_name: path or URL)
139 One or more paths or URLs to existing files directories to install.
151 One or more paths or URLs to existing files directories to install.
140 If given as a list, these will be installed with their base name, so '/path/to/foo'
152 If given as a list, these will be installed with their base name, so '/path/to/foo'
141 will install to 'nbextensions/foo'. If given as a dict, such as {'bar': '/path/to/foo'},
153 will install to 'nbextensions/foo'. If given as a dict, such as {'bar': '/path/to/foo'},
142 then '/path/to/foo' will install to 'nbextensions/bar'.
154 then '/path/to/foo' will install to 'nbextensions/bar'.
143 Archives (zip or tarballs) will be extracted into the nbextensions directory.
155 Archives (zip or tarballs) will be extracted into the nbextensions directory.
144 overwrite : bool [default: False]
156 overwrite : bool [default: False]
145 If True, always install the files, regardless of what may already be installed.
157 If True, always install the files, regardless of what may already be installed.
146 symlink : bool [default: False]
158 symlink : bool [default: False]
147 If True, create a symlink in nbextensions, rather than copying files.
159 If True, create a symlink in nbextensions, rather than copying files.
148 Not allowed with URLs or archives. Windows support for symlinks requires
160 Not allowed with URLs or archives. Windows support for symlinks requires
149 Vista or above, Python 3, and a permission bit which only admin users
161 Vista or above, Python 3, and a permission bit which only admin users
150 have by default, so don't rely on it.
162 have by default, so don't rely on it.
151 user : bool [default: False]
163 user : bool [default: False]
152 Whether to install to the user's .ipython/nbextensions directory.
164 Whether to install to the user's .ipython/nbextensions directory.
153 Otherwise do a system-wide install (e.g. /usr/local/share/jupyter/nbextensions).
165 Otherwise do a system-wide install (e.g. /usr/local/share/jupyter/nbextensions).
154 prefix : str [optional]
166 prefix : str [optional]
155 Specify install prefix, if it should differ from default (e.g. /usr/local).
167 Specify install prefix, if it should differ from default (e.g. /usr/local).
156 Will install to prefix/share/jupyter/nbextensions
168 Will install to prefix/share/jupyter/nbextensions
157 nbextensions_dir : str [optional]
169 nbextensions_dir : str [optional]
158 Specify absolute path of nbextensions directory explicitly.
170 Specify absolute path of nbextensions directory explicitly.
159 verbose : int [default: 1]
171 verbose : int [default: 1]
160 Set verbosity level. The default is 1, where file actions are printed.
172 Set verbosity level. The default is 1, where file actions are printed.
161 set verbose=2 for more output, or verbose=0 for silence.
173 set verbose=2 for more output, or verbose=0 for silence.
162 """
174 """
163 nbext = _get_nbext_dir(nbextensions_dir, user, prefix)
175 nbext = _get_nbext_dir(nbextensions_dir, user, prefix)
164 # make sure nbextensions dir exists
176 # make sure nbextensions dir exists
165 ensure_dir_exists(nbext)
177 ensure_dir_exists(nbext)
166
178
167 if isinstance(files, string_types):
179 if isinstance(files, string_types):
168 # one file given, turn it into a list
180 # one file given, turn it into a list
169 files = [files]
181 files = [files]
170 if isinstance(files, (list,tuple)):
182 if isinstance(files, (list,tuple)):
171 # list given, turn into dict
183 # list given, turn into dict
172 _files = {}
184 _files = {}
173 for path in map(cast_unicode_py2, files):
185 for path in map(cast_unicode_py2, files):
174 if path.startswith(('https://', 'http://')):
186 if path.startswith(('https://', 'http://')):
175 destination = urlparse(path).path.split('/')[-1]
187 destination = urlparse(path).path.split('/')[-1]
176 elif path.endswith('.zip') or _safe_is_tarfile(path):
188 elif path.endswith('.zip') or _safe_is_tarfile(path):
177 destination = str(uuid.uuid4()) # ignored for archives
189 destination = str(uuid.uuid4()) # ignored for archives
178 else:
190 else:
179 destination = basename(path)
191 destination = basename(path)
180 _files[destination] = path
192 _files[destination] = path
181 files = _files
193 files = _files
182
194
183 for dest_basename,path in (map(cast_unicode_py2, item) for item in files.items()):
195 for dest_basename,path in (map(cast_unicode_py2, item) for item in files.items()):
184
196
185 if path.startswith(('https://', 'http://')):
197 if path.startswith(('https://', 'http://')):
186 if symlink:
198 if symlink:
187 raise ValueError("Cannot symlink from URLs")
199 raise ValueError("Cannot symlink from URLs")
188 # Given a URL, download it
200 # Given a URL, download it
189 with TemporaryDirectory() as td:
201 with TemporaryDirectory() as td:
190 filename = urlparse(path).path.split('/')[-1]
202 filename = urlparse(path).path.split('/')[-1]
191 local_path = os.path.join(td, filename)
203 local_path = os.path.join(td, filename)
192 if verbose >= 1:
204 if verbose >= 1:
193 print("downloading %s to %s" % (path, local_path))
205 print("downloading %s to %s" % (path, local_path))
194 urlretrieve(path, local_path)
206 urlretrieve(path, local_path)
195 # now install from the local copy
207 # now install from the local copy
196 install_nbextension({dest_basename: local_path}, overwrite=overwrite, symlink=symlink, nbextensions_dir=nbext, verbose=verbose)
208 install_nbextension({dest_basename: local_path}, overwrite=overwrite, symlink=symlink, nbextensions_dir=nbext, verbose=verbose)
197 continue
209 continue
198
210
199 # handle archives
211 # handle archives
200 archive = None
212 archive = None
201 if path.endswith('.zip'):
213 if path.endswith('.zip'):
202 archive = zipfile.ZipFile(path)
214 archive = zipfile.ZipFile(path)
203 elif _safe_is_tarfile(path):
215 elif _safe_is_tarfile(path):
204 archive = tarfile.open(path)
216 archive = tarfile.open(path)
205
217
206 if archive:
218 if archive:
207 if symlink:
219 if symlink:
208 raise ValueError("Cannot symlink from archives")
220 raise ValueError("Cannot symlink from archives")
209 if verbose >= 1:
221 if verbose >= 1:
210 print("extracting %s to %s" % (path, nbext))
222 print("extracting %s to %s" % (path, nbext))
211 archive.extractall(nbext)
223 archive.extractall(nbext)
212 archive.close()
224 archive.close()
213 continue
225 continue
214
226
215 dest = pjoin(nbext, dest_basename)
227 dest = pjoin(nbext, dest_basename)
216 if overwrite and os.path.exists(dest):
228 if overwrite and os.path.exists(dest):
217 if verbose >= 1:
229 if verbose >= 1:
218 print("removing %s" % dest)
230 print("removing %s" % dest)
219 if os.path.isdir(dest) and not os.path.islink(dest):
231 if os.path.isdir(dest) and not os.path.islink(dest):
220 shutil.rmtree(dest)
232 shutil.rmtree(dest)
221 else:
233 else:
222 os.remove(dest)
234 os.remove(dest)
223
235
224 if symlink:
236 if symlink:
225 path = os.path.abspath(path)
237 path = os.path.abspath(path)
226 if not os.path.exists(dest):
238 if not os.path.exists(dest):
227 if verbose >= 1:
239 if verbose >= 1:
228 print("symlink %s -> %s" % (dest, path))
240 print("symlink %s -> %s" % (dest, path))
229 os.symlink(path, dest)
241 os.symlink(path, dest)
230 continue
242 continue
231
243
232 if os.path.isdir(path):
244 if os.path.isdir(path):
233 path = pjoin(os.path.abspath(path), '') # end in path separator
245 path = pjoin(os.path.abspath(path), '') # end in path separator
234 for parent, dirs, files in os.walk(path):
246 for parent, dirs, files in os.walk(path):
235 dest_dir = pjoin(dest, parent[len(path):])
247 dest_dir = pjoin(dest, parent[len(path):])
236 if not os.path.exists(dest_dir):
248 if not os.path.exists(dest_dir):
237 if verbose >= 2:
249 if verbose >= 2:
238 print("making directory %s" % dest_dir)
250 print("making directory %s" % dest_dir)
239 os.makedirs(dest_dir)
251 os.makedirs(dest_dir)
240 for file in files:
252 for file in files:
241 src = pjoin(parent, file)
253 src = pjoin(parent, file)
242 # print("%r, %r" % (dest_dir, file))
254 # print("%r, %r" % (dest_dir, file))
243 dest_file = pjoin(dest_dir, file)
255 dest_file = pjoin(dest_dir, file)
244 _maybe_copy(src, dest_file, verbose)
256 _maybe_copy(src, dest_file, verbose)
245 else:
257 else:
246 src = path
258 src = path
247 _maybe_copy(src, dest, verbose)
259 _maybe_copy(src, dest, verbose)
248
260
249 #----------------------------------------------------------------------
261 #----------------------------------------------------------------------
250 # install nbextension app
262 # install nbextension app
251 #----------------------------------------------------------------------
263 #----------------------------------------------------------------------
252
264
253 from IPython.utils.traitlets import Bool, Enum, Unicode, TraitError
265 from IPython.utils.traitlets import Bool, Enum, Unicode, TraitError
254 from IPython.core.application import BaseIPythonApplication
266 from IPython.core.application import BaseIPythonApplication
255
267
256 flags = {
268 flags = {
257 "overwrite" : ({
269 "overwrite" : ({
258 "NBExtensionApp" : {
270 "NBExtensionApp" : {
259 "overwrite" : True,
271 "overwrite" : True,
260 }}, "Force overwrite of existing files"
272 }}, "Force overwrite of existing files"
261 ),
273 ),
262 "debug" : ({
274 "debug" : ({
263 "NBExtensionApp" : {
275 "NBExtensionApp" : {
264 "verbose" : 2,
276 "verbose" : 2,
265 }}, "Extra output"
277 }}, "Extra output"
266 ),
278 ),
267 "quiet" : ({
279 "quiet" : ({
268 "NBExtensionApp" : {
280 "NBExtensionApp" : {
269 "verbose" : 0,
281 "verbose" : 0,
270 }}, "Minimal output"
282 }}, "Minimal output"
271 ),
283 ),
272 "symlink" : ({
284 "symlink" : ({
273 "NBExtensionApp" : {
285 "NBExtensionApp" : {
274 "symlink" : True,
286 "symlink" : True,
275 }}, "Create symlinks instead of copying files"
287 }}, "Create symlinks instead of copying files"
276 ),
288 ),
277 "user" : ({
289 "user" : ({
278 "NBExtensionApp" : {
290 "NBExtensionApp" : {
279 "user" : True,
291 "user" : True,
280 }}, "Install to the user's IPython directory"
292 }}, "Install to the user's IPython directory"
281 ),
293 ),
282 }
294 }
283 flags['s'] = flags['symlink']
295 flags['s'] = flags['symlink']
284
296
285 aliases = {
297 aliases = {
286 "ipython-dir" : "NBExtensionApp.ipython_dir",
298 "ipython-dir" : "NBExtensionApp.ipython_dir",
287 "prefix" : "NBExtensionApp.prefix",
299 "prefix" : "NBExtensionApp.prefix",
288 "nbextensions" : "NBExtensionApp.nbextensions_dir",
300 "nbextensions" : "NBExtensionApp.nbextensions_dir",
289 }
301 }
290
302
291 class NBExtensionApp(BaseIPythonApplication):
303 class NBExtensionApp(BaseIPythonApplication):
292 """Entry point for installing notebook extensions"""
304 """Entry point for installing notebook extensions"""
293
305
294 description = """Install IPython notebook extensions
306 description = """Install IPython notebook extensions
295
307
296 Usage
308 Usage
297
309
298 ipython install-nbextension file [more files, folders, archives or urls]
310 ipython install-nbextension file [more files, folders, archives or urls]
299
311
300 This copies files and/or folders into the IPython nbextensions directory.
312 This copies files and/or folders into the IPython nbextensions directory.
301 If a URL is given, it will be downloaded.
313 If a URL is given, it will be downloaded.
302 If an archive is given, it will be extracted into nbextensions.
314 If an archive is given, it will be extracted into nbextensions.
303 If the requested files are already up to date, no action is taken
315 If the requested files are already up to date, no action is taken
304 unless --overwrite is specified.
316 unless --overwrite is specified.
305 """
317 """
306
318
307 examples = """
319 examples = """
308 ipython install-nbextension /path/to/d3.js /path/to/myextension
320 ipython install-nbextension /path/to/d3.js /path/to/myextension
309 """
321 """
310 aliases = aliases
322 aliases = aliases
311 flags = flags
323 flags = flags
312
324
313 overwrite = Bool(False, config=True, help="Force overwrite of existing files")
325 overwrite = Bool(False, config=True, help="Force overwrite of existing files")
314 symlink = Bool(False, config=True, help="Create symlinks instead of copying files")
326 symlink = Bool(False, config=True, help="Create symlinks instead of copying files")
315 user = Bool(False, config=True, help="Whether to do a user install")
327 user = Bool(False, config=True, help="Whether to do a user install")
316 prefix = Unicode('', config=True, help="Installation prefix")
328 prefix = Unicode('', config=True, help="Installation prefix")
317 nbextensions_dir = Unicode('', config=True, help="Full path to nbextensions dir (probably use prefix or user)")
329 nbextensions_dir = Unicode('', config=True, help="Full path to nbextensions dir (probably use prefix or user)")
318 verbose = Enum((0,1,2), default_value=1, config=True,
330 verbose = Enum((0,1,2), default_value=1, config=True,
319 help="Verbosity level"
331 help="Verbosity level"
320 )
332 )
321
333
322 def install_extensions(self):
334 def install_extensions(self):
323 install_nbextension(self.extra_args,
335 install_nbextension(self.extra_args,
324 overwrite=self.overwrite,
336 overwrite=self.overwrite,
325 symlink=self.symlink,
337 symlink=self.symlink,
326 verbose=self.verbose,
338 verbose=self.verbose,
327 user=self.user,
339 user=self.user,
328 prefix=self.prefix,
340 prefix=self.prefix,
329 nbextensions_dir=self.nbextensions_dir,
341 nbextensions_dir=self.nbextensions_dir,
330 )
342 )
331
343
332 def start(self):
344 def start(self):
333 if not self.extra_args:
345 if not self.extra_args:
334 for nbext in [pjoin(self.ipython_dir, u'nbextensions')] + SYSTEM_NBEXTENSIONS_DIRS:
346 for nbext in [pjoin(self.ipython_dir, u'nbextensions')] + SYSTEM_NBEXTENSIONS_DIRS:
335 if os.path.exists(nbext):
347 if os.path.exists(nbext):
336 print("Notebook extensions in %s:" % nbext)
348 print("Notebook extensions in %s:" % nbext)
337 for ext in os.listdir(nbext):
349 for ext in os.listdir(nbext):
338 print(u" %s" % ext)
350 print(u" %s" % ext)
339 else:
351 else:
340 try:
352 try:
341 self.install_extensions()
353 self.install_extensions()
342 except ArgumentConflict as e:
354 except ArgumentConflict as e:
343 print(str(e), file=sys.stderr)
355 print(str(e), file=sys.stderr)
344 self.exit(1)
356 self.exit(1)
345
357
346
358
347 if __name__ == '__main__':
359 if __name__ == '__main__':
348 NBExtensionApp.launch_instance()
360 NBExtensionApp.launch_instance()
349
361
General Comments 0
You need to be logged in to leave comments. Login now