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