##// END OF EJS Templates
Merge pull request #8238 from ipython/revert-8235-testpath...
Merge pull request #8238 from ipython/revert-8235-testpath Revert "use testpath.tempdir for utils.tempdir"

File last commit:

r20403:37db54fb
r21110:ce85574b merge
Show More
nbextensions.py
350 lines | 12.9 KiB | text/x-python | PythonLexer
MinRK
add IPython.html.nbextensions.install_nbextension...
r15220 # coding: utf-8
"""Utilities for installing Javascript extensions for the notebook"""
MinRK
add utils.path.ensure_dir_exists...
r16486 # Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
MinRK
add IPython.html.nbextensions.install_nbextension...
r15220
from __future__ import print_function
import os
import shutil
Min RK
allow system-wide paths for nbextensions...
r19854 import sys
MinRK
support URLs and zip/tarballs in install_extension
r15223 import tarfile
import zipfile
Jason Grout
Initial take on implementing configurable destinations for nbextensions....
r20071 import uuid
MinRK
add IPython.html.nbextensions.install_nbextension...
r15220 from os.path import basename, join as pjoin
MinRK
support URLs and zip/tarballs in install_extension
r15223 # Deferred imports
try:
from urllib.parse import urlparse # Py3
from urllib.request import urlretrieve
except ImportError:
from urlparse import urlparse
from urllib import urlretrieve
MinRK
add utils.path.ensure_dir_exists...
r16486 from IPython.utils.path import get_ipython_dir, ensure_dir_exists
MinRK
add IPython.html.nbextensions.install_nbextension...
r15220 from IPython.utils.py3compat import string_types, cast_unicode_py2
MinRK
support URLs and zip/tarballs in install_extension
r15223 from IPython.utils.tempdir import TemporaryDirectory
MinRK
add IPython.html.nbextensions.install_nbextension...
r15220
Min RK
remove duplicate arg conflict check
r19856 class ArgumentConflict(ValueError):
pass
MinRK
add IPython.html.nbextensions.install_nbextension...
r15220
Min RK
allow system-wide paths for nbextensions...
r19854 # Packagers: modify the next block if you store system-installed nbextensions elsewhere (unlikely)
SYSTEM_NBEXTENSIONS_DIRS = []
if os.name == 'nt':
programdata = os.environ.get('PROGRAMDATA', None)
if programdata: # PROGRAMDATA is not defined by default on XP.
SYSTEM_NBEXTENSIONS_DIRS = [pjoin(programdata, 'jupyter', 'nbextensions')]
prefixes = []
else:
Min RK
path.sep
r19857 prefixes = [os.path.sep + pjoin('usr', 'local'), os.path.sep + 'usr']
Min RK
allow system-wide paths for nbextensions...
r19854
# add sys.prefix at the front
if sys.prefix not in prefixes:
prefixes.insert(0, sys.prefix)
for prefix in prefixes:
Min RK
path.sep
r19857 nbext = pjoin(prefix, 'share', 'jupyter', 'nbextensions')
Min RK
allow system-wide paths for nbextensions...
r19854 if nbext not in SYSTEM_NBEXTENSIONS_DIRS:
SYSTEM_NBEXTENSIONS_DIRS.append(nbext)
if os.name == 'nt':
# PROGRAMDATA
SYSTEM_NBEXTENSIONS_INSTALL_DIR = SYSTEM_NBEXTENSIONS_DIRS[-1]
else:
# /usr/local
SYSTEM_NBEXTENSIONS_INSTALL_DIR = SYSTEM_NBEXTENSIONS_DIRS[-2]
MinRK
add IPython.html.nbextensions.install_nbextension...
r15220 def _should_copy(src, dest, verbose=1):
"""should a file be copied?"""
if not os.path.exists(dest):
return True
Jason Grout
Work around a bug in setting and getting the mtime in python 2...
r20080 if os.stat(src).st_mtime - os.stat(dest).st_mtime > 1e-6:
# we add a fudge factor to work around a bug in python 2.x
# that was fixed in python 3.x: http://bugs.python.org/issue12904
MinRK
add IPython.html.nbextensions.install_nbextension...
r15220 if verbose >= 2:
print("%s is out of date" % dest)
return True
if verbose >= 2:
print("%s is up to date" % dest)
return False
def _maybe_copy(src, dest, verbose=1):
"""copy a file if it needs updating"""
if _should_copy(src, dest, verbose):
if verbose >= 1:
print("copying %s -> %s" % (src, dest))
Jason Grout
Don't trap any copying errors - allow them to bubble up.
r20171 shutil.copy2(src, dest)
MinRK
add IPython.html.nbextensions.install_nbextension...
r15220
MinRK
support URLs and zip/tarballs in install_extension
r15223 def _safe_is_tarfile(path):
"""safe version of is_tarfile, return False on IOError"""
try:
return tarfile.is_tarfile(path)
except IOError:
return False
Jason Grout
Refactor the logic to get the nbextension directory...
r20083 def _get_nbext_dir(nbextensions_dir=None, user=False, prefix=None):
"""Return the nbextension directory specified"""
if sum(map(bool, [user, prefix, nbextensions_dir])) > 1:
raise ArgumentConflict("Cannot specify more than one of user, prefix, or nbextensions_dir.")
if user:
nbext = pjoin(get_ipython_dir(), u'nbextensions')
else:
if prefix:
nbext = pjoin(prefix, 'share', 'jupyter', 'nbextensions')
elif nbextensions_dir:
nbext = nbextensions_dir
else:
nbext = SYSTEM_NBEXTENSIONS_INSTALL_DIR
return nbext
Jason Grout
Add documentation to check_nbextension, and switch order of parameters to be consistent with install_nbextension.
r20085 def check_nbextension(files, user=False, prefix=None, nbextensions_dir=None):
MinRK
add check_nbextension
r15227 """Check whether nbextension files have been installed
Returns True if all files are found, False if any are missing.
Jason Grout
Add documentation to check_nbextension, and switch order of parameters to be consistent with install_nbextension.
r20085
Parameters
----------
files : list(paths)
a list of relative paths within nbextensions.
user : bool [default: False]
Whether to check the user's .ipython/nbextensions directory.
Otherwise check a system-wide install (e.g. /usr/local/share/jupyter/nbextensions).
prefix : str [optional]
Specify install prefix, if it should differ from default (e.g. /usr/local).
Will check prefix/share/jupyter/nbextensions
nbextensions_dir : str [optional]
Specify absolute path of nbextensions directory explicitly.
MinRK
add check_nbextension
r15227 """
Jason Grout
Refactor the logic to get the nbextension directory...
r20083 nbext = _get_nbext_dir(nbextensions_dir, user, prefix)
MinRK
add check_nbextension
r15227 # make sure nbextensions dir exists
if not os.path.exists(nbext):
return False
if isinstance(files, string_types):
# one file given, turn it into a list
files = [files]
MinRK
clarify with all in check_nbextension
r15340 return all(os.path.exists(pjoin(nbext, f)) for f in files)
MinRK
add check_nbextension
r15227
Jason Grout
Change install_nbextension to take install only a single nbextension (file, folder, archive, url), with an optional destination argument
r20217 def install_nbextension(path, overwrite=False, symlink=False, user=False, prefix=None, nbextensions_dir=None, destination=None, verbose=1):
MinRK
add IPython.html.nbextensions.install_nbextension...
r15220 """Install a Javascript extension for the notebook
Min RK
s/nbextensions/nbextensions_dir...
r19855 Stages files and/or directories into the nbextensions directory.
MinRK
support URLs and zip/tarballs in install_extension
r15223 By default, this compares modification time, and only stages files that need updating.
MinRK
add IPython.html.nbextensions.install_nbextension...
r15220 If `overwrite` is specified, matching files are purged before proceeding.
Parameters
----------
Jason Grout
Change install_nbextension to take install only a single nbextension (file, folder, archive, url), with an optional destination argument
r20217 path : path to file, directory, zip or tarball archive, or URL to install
By default, the file will be installed with its base name, so '/path/to/foo'
will install to 'nbextensions/foo'. See the destination argument below to change this.
MinRK
support URLs and zip/tarballs in install_extension
r15223 Archives (zip or tarballs) will be extracted into the nbextensions directory.
MinRK
add IPython.html.nbextensions.install_nbextension...
r15220 overwrite : bool [default: False]
If True, always install the files, regardless of what may already be installed.
MinRK
allow installing nbextensions with symlinks
r15226 symlink : bool [default: False]
If True, create a symlink in nbextensions, rather than copying files.
Thomas Kluyver
Document limitations of symlink parameter to install_nbextension...
r18725 Not allowed with URLs or archives. Windows support for symlinks requires
Vista or above, Python 3, and a permission bit which only admin users
have by default, so don't rely on it.
Min RK
allow system-wide paths for nbextensions...
r19854 user : bool [default: False]
Whether to install to the user's .ipython/nbextensions directory.
Otherwise do a system-wide install (e.g. /usr/local/share/jupyter/nbextensions).
prefix : str [optional]
Specify install prefix, if it should differ from default (e.g. /usr/local).
Matthias Bussonnier
minor doc improvement on nbextension
r20403 Will install to ``<prefix>/share/jupyter/nbextensions``
Min RK
s/nbextensions/nbextensions_dir...
r19855 nbextensions_dir : str [optional]
Min RK
allow system-wide paths for nbextensions...
r19854 Specify absolute path of nbextensions directory explicitly.
Jason Grout
Change install_nbextension to take install only a single nbextension (file, folder, archive, url), with an optional destination argument
r20217 destination : str [optional]
name the nbextension is installed to. For example, if destination is 'foo', then
the source file will be installed to 'nbextensions/foo', regardless of the source name.
This cannot be specified if an archive is given as the source.
MinRK
add IPython.html.nbextensions.install_nbextension...
r15220 verbose : int [default: 1]
Set verbosity level. The default is 1, where file actions are printed.
set verbose=2 for more output, or verbose=0 for silence.
"""
Jason Grout
Refactor the logic to get the nbextension directory...
r20083 nbext = _get_nbext_dir(nbextensions_dir, user, prefix)
MinRK
add IPython.html.nbextensions.install_nbextension...
r15220 # make sure nbextensions dir exists
MinRK
add utils.path.ensure_dir_exists...
r16486 ensure_dir_exists(nbext)
MinRK
add IPython.html.nbextensions.install_nbextension...
r15220
Jason Grout
Change install_nbextension to take install only a single nbextension (file, folder, archive, url), with an optional destination argument
r20217 if isinstance(path, (list, tuple)):
raise TypeError("path must be a string pointing to a single extension to install; call this function multiple times to install multiple extensions")
MinRK
add IPython.html.nbextensions.install_nbextension...
r15220
Jason Grout
Change install_nbextension to take install only a single nbextension (file, folder, archive, url), with an optional destination argument
r20217 path = cast_unicode_py2(path)
if path.startswith(('https://', 'http://')):
if symlink:
raise ValueError("Cannot symlink from URLs")
# Given a URL, download it
with TemporaryDirectory() as td:
filename = urlparse(path).path.split('/')[-1]
local_path = os.path.join(td, filename)
if verbose >= 1:
print("downloading %s to %s" % (path, local_path))
urlretrieve(path, local_path)
# now install from the local copy
install_nbextension(local_path, overwrite=overwrite, symlink=symlink, nbextensions_dir=nbext, destination=destination, verbose=verbose)
elif path.endswith('.zip') or _safe_is_tarfile(path):
if symlink:
raise ValueError("Cannot symlink from archives")
if destination:
raise ValueError("Cannot give destination for archives")
if verbose >= 1:
print("extracting %s to %s" % (path, nbext))
MinRK
support URLs and zip/tarballs in install_extension
r15223 if path.endswith('.zip'):
archive = zipfile.ZipFile(path)
elif _safe_is_tarfile(path):
archive = tarfile.open(path)
Jason Grout
Change install_nbextension to take install only a single nbextension (file, folder, archive, url), with an optional destination argument
r20217 archive.extractall(nbext)
archive.close()
else:
if not destination:
destination = basename(path)
Jason Grout
Cast the destination url to unicode in python2...
r20228 destination = cast_unicode_py2(destination)
Jason Grout
Change install_nbextension to take install only a single nbextension (file, folder, archive, url), with an optional destination argument
r20217 full_dest = pjoin(nbext, destination)
Jason Grout
Fix error when overwriting a bad symbolic link installing an nbextension...
r20245 if overwrite and os.path.lexists(full_dest):
MinRK
add IPython.html.nbextensions.install_nbextension...
r15220 if verbose >= 1:
Jason Grout
Change install_nbextension to take install only a single nbextension (file, folder, archive, url), with an optional destination argument
r20217 print("removing %s" % full_dest)
if os.path.isdir(full_dest) and not os.path.islink(full_dest):
shutil.rmtree(full_dest)
MinRK
add IPython.html.nbextensions.install_nbextension...
r15220 else:
Jason Grout
Change install_nbextension to take install only a single nbextension (file, folder, archive, url), with an optional destination argument
r20217 os.remove(full_dest)
MinRK
allow installing nbextensions with symlinks
r15226 if symlink:
path = os.path.abspath(path)
Jason Grout
Change install_nbextension to take install only a single nbextension (file, folder, archive, url), with an optional destination argument
r20217 if not os.path.exists(full_dest):
MinRK
allow installing nbextensions with symlinks
r15226 if verbose >= 1:
Jason Grout
Change install_nbextension to take install only a single nbextension (file, folder, archive, url), with an optional destination argument
r20217 print("symlink %s -> %s" % (full_dest, path))
os.symlink(path, full_dest)
elif os.path.isdir(path):
Jason Grout
Fix the path we use when walking to include the path separator...
r20078 path = pjoin(os.path.abspath(path), '') # end in path separator
MinRK
add IPython.html.nbextensions.install_nbextension...
r15220 for parent, dirs, files in os.walk(path):
Jason Grout
Change install_nbextension to take install only a single nbextension (file, folder, archive, url), with an optional destination argument
r20217 dest_dir = pjoin(full_dest, parent[len(path):])
MinRK
add IPython.html.nbextensions.install_nbextension...
r15220 if not os.path.exists(dest_dir):
if verbose >= 2:
print("making directory %s" % dest_dir)
os.makedirs(dest_dir)
for file in files:
src = pjoin(parent, file)
# print("%r, %r" % (dest_dir, file))
Jason Grout
Don't overwrite the dest variable
r20077 dest_file = pjoin(dest_dir, file)
_maybe_copy(src, dest_file, verbose)
MinRK
add IPython.html.nbextensions.install_nbextension...
r15220 else:
src = path
Jason Grout
Fix variable name typo
r20218 _maybe_copy(src, full_dest, verbose)
MinRK
add `ipython install-nbextension` entrypoint
r15221
#----------------------------------------------------------------------
# install nbextension app
#----------------------------------------------------------------------
Min RK
allow system-wide paths for nbextensions...
r19854 from IPython.utils.traitlets import Bool, Enum, Unicode, TraitError
MinRK
add `ipython install-nbextension` entrypoint
r15221 from IPython.core.application import BaseIPythonApplication
flags = {
"overwrite" : ({
"NBExtensionApp" : {
"overwrite" : True,
}}, "Force overwrite of existing files"
),
"debug" : ({
"NBExtensionApp" : {
"verbose" : 2,
}}, "Extra output"
),
"quiet" : ({
"NBExtensionApp" : {
"verbose" : 0,
}}, "Minimal output"
),
MinRK
allow installing nbextensions with symlinks
r15226 "symlink" : ({
"NBExtensionApp" : {
"symlink" : True,
Jason Grout
Change install_nbextension to take install only a single nbextension (file, folder, archive, url), with an optional destination argument
r20217 }}, "Create symlink instead of copying files"
MinRK
allow installing nbextensions with symlinks
r15226 ),
Min RK
allow system-wide paths for nbextensions...
r19854 "user" : ({
"NBExtensionApp" : {
"user" : True,
}}, "Install to the user's IPython directory"
),
MinRK
add `ipython install-nbextension` entrypoint
r15221 }
MinRK
allow installing nbextensions with symlinks
r15226 flags['s'] = flags['symlink']
MinRK
add `ipython install-nbextension` entrypoint
r15221 aliases = {
Min RK
allow system-wide paths for nbextensions...
r19854 "ipython-dir" : "NBExtensionApp.ipython_dir",
"prefix" : "NBExtensionApp.prefix",
Min RK
s/nbextensions/nbextensions_dir...
r19855 "nbextensions" : "NBExtensionApp.nbextensions_dir",
Jason Grout
Change install_nbextension to take install only a single nbextension (file, folder, archive, url), with an optional destination argument
r20217 "destination" : "NBExtensionApp.destination",
MinRK
add `ipython install-nbextension` entrypoint
r15221 }
class NBExtensionApp(BaseIPythonApplication):
"""Entry point for installing notebook extensions"""
description = """Install IPython notebook extensions
Usage
Jason Grout
Fix wording of install-nbextension command help...
r20220 ipython install-nbextension path/url
MinRK
add `ipython install-nbextension` entrypoint
r15221
Jason Grout
Fix wording of install-nbextension command help...
r20220 This copies a file or a folder into the IPython nbextensions directory.
MinRK
support URLs and zip/tarballs in install_extension
r15223 If a URL is given, it will be downloaded.
If an archive is given, it will be extracted into nbextensions.
MinRK
add `ipython install-nbextension` entrypoint
r15221 If the requested files are already up to date, no action is taken
unless --overwrite is specified.
"""
examples = """
Jason Grout
Change install_nbextension to take install only a single nbextension (file, folder, archive, url), with an optional destination argument
r20217 ipython install-nbextension /path/to/myextension
MinRK
add `ipython install-nbextension` entrypoint
r15221 """
aliases = aliases
flags = flags
overwrite = Bool(False, config=True, help="Force overwrite of existing files")
MinRK
allow installing nbextensions with symlinks
r15226 symlink = Bool(False, config=True, help="Create symlinks instead of copying files")
Min RK
allow system-wide paths for nbextensions...
r19854 user = Bool(False, config=True, help="Whether to do a user install")
prefix = Unicode('', config=True, help="Installation prefix")
Min RK
s/nbextensions/nbextensions_dir...
r19855 nbextensions_dir = Unicode('', config=True, help="Full path to nbextensions dir (probably use prefix or user)")
Jason Grout
Change install_nbextension to take install only a single nbextension (file, folder, archive, url), with an optional destination argument
r20217 destination = Unicode('', config=True, help="Destination for the copy or symlink")
MinRK
add `ipython install-nbextension` entrypoint
r15221 verbose = Enum((0,1,2), default_value=1, config=True,
help="Verbosity level"
)
def install_extensions(self):
Jason Grout
Give sensible error message if using the install-nbextension command to try to install multiple extensions.
r20219 if len(self.extra_args)>1:
raise ValueError("only one nbextension allowed at a time. Call multiple times to install multiple extensions.")
install_nbextension(self.extra_args[0],
MinRK
add `ipython install-nbextension` entrypoint
r15221 overwrite=self.overwrite,
MinRK
allow installing nbextensions with symlinks
r15226 symlink=self.symlink,
MinRK
add `ipython install-nbextension` entrypoint
r15221 verbose=self.verbose,
Min RK
allow system-wide paths for nbextensions...
r19854 user=self.user,
prefix=self.prefix,
Jason Grout
Change install_nbextension to take install only a single nbextension (file, folder, archive, url), with an optional destination argument
r20217 destination=self.destination,
Min RK
s/nbextensions/nbextensions_dir...
r19855 nbextensions_dir=self.nbextensions_dir,
MinRK
add `ipython install-nbextension` entrypoint
r15221 )
def start(self):
if not self.extra_args:
Min RK
allow system-wide paths for nbextensions...
r19854 for nbext in [pjoin(self.ipython_dir, u'nbextensions')] + SYSTEM_NBEXTENSIONS_DIRS:
if os.path.exists(nbext):
print("Notebook extensions in %s:" % nbext)
for ext in os.listdir(nbext):
print(u" %s" % ext)
MinRK
add `ipython install-nbextension` entrypoint
r15221 else:
Min RK
remove duplicate arg conflict check
r19856 try:
self.install_extensions()
except ArgumentConflict as e:
print(str(e), file=sys.stderr)
self.exit(1)
MinRK
add `ipython install-nbextension` entrypoint
r15221
if __name__ == '__main__':
NBExtensionApp.launch_instance()
Jason Grout
Add documentation to check_nbextension, and switch order of parameters to be consistent with install_nbextension.
r20085