|
|
# coding: utf-8
|
|
|
"""Utilities for installing Javascript extensions for the notebook"""
|
|
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
# Copyright (C) 2014 The IPython Development Team
|
|
|
#
|
|
|
# Distributed under the terms of the BSD License. The full license is in
|
|
|
# the file COPYING, distributed as part of this software.
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
|
|
from __future__ import print_function
|
|
|
|
|
|
import os
|
|
|
import shutil
|
|
|
from os.path import basename, join as pjoin
|
|
|
|
|
|
from IPython.utils.path import get_ipython_dir
|
|
|
from IPython.utils.py3compat import string_types, cast_unicode_py2
|
|
|
|
|
|
|
|
|
def _should_copy(src, dest, verbose=1):
|
|
|
"""should a file be copied?"""
|
|
|
if not os.path.exists(dest):
|
|
|
return True
|
|
|
if os.stat(dest).st_mtime < os.stat(src).st_mtime:
|
|
|
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))
|
|
|
shutil.copy2(src, dest)
|
|
|
|
|
|
|
|
|
def install_nbextension(files, overwrite=False, ipython_dir=None, verbose=1):
|
|
|
"""Install a Javascript extension for the notebook
|
|
|
|
|
|
Stages files and/or directories into IPYTHONDIR/nbextensions.
|
|
|
By default, this comparse modification time, and only stages files that need updating.
|
|
|
If `overwrite` is specified, matching files are purged before proceeding.
|
|
|
|
|
|
Parameters
|
|
|
----------
|
|
|
|
|
|
files : list(paths)
|
|
|
One or more paths to existing files or directories to install.
|
|
|
These will be installed with their base name, so '/path/to/foo'
|
|
|
will install to 'nbextensions/foo'.
|
|
|
overwrite : bool [default: False]
|
|
|
If True, always install the files, regardless of what may already be installed.
|
|
|
ipython_dir : str [optional]
|
|
|
The path to an IPython directory, if the default value is not desired.
|
|
|
get_ipython_dir() is used by default.
|
|
|
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.
|
|
|
"""
|
|
|
|
|
|
ipython_dir = ipython_dir or get_ipython_dir()
|
|
|
nbext = pjoin(ipython_dir, u'nbextensions')
|
|
|
# make sure nbextensions dir exists
|
|
|
if not os.path.exists(nbext):
|
|
|
os.makedirs(nbext)
|
|
|
|
|
|
if isinstance(files, string_types):
|
|
|
# one file given, turn it into a list
|
|
|
files = [files]
|
|
|
|
|
|
for path in map(cast_unicode_py2, files):
|
|
|
dest = pjoin(nbext, basename(path))
|
|
|
if overwrite and os.path.exists(dest):
|
|
|
if verbose >= 1:
|
|
|
print("removing %s" % dest)
|
|
|
if os.path.isdir(dest):
|
|
|
shutil.rmtree(dest)
|
|
|
else:
|
|
|
os.remove(dest)
|
|
|
|
|
|
if os.path.isdir(path):
|
|
|
strip_prefix_len = len(path) - len(basename(path))
|
|
|
for parent, dirs, files in os.walk(path):
|
|
|
dest_dir = pjoin(nbext, parent[strip_prefix_len:])
|
|
|
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))
|
|
|
dest = pjoin(dest_dir, file)
|
|
|
_maybe_copy(src, dest, verbose)
|
|
|
else:
|
|
|
src = path
|
|
|
_maybe_copy(src, dest, verbose)
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
# install nbextension app
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
|
import logging
|
|
|
from IPython.utils.traitlets import Bool, Enum
|
|
|
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"
|
|
|
),
|
|
|
}
|
|
|
aliases = {
|
|
|
"ipython-dir" : "NBExtensionApp.ipython_dir"
|
|
|
}
|
|
|
|
|
|
class NBExtensionApp(BaseIPythonApplication):
|
|
|
"""Entry point for installing notebook extensions"""
|
|
|
|
|
|
description = """Install IPython notebook extensions
|
|
|
|
|
|
Usage
|
|
|
|
|
|
ipython install-nbextension file [more files or folders]
|
|
|
|
|
|
This copies files and/or folders into the IPython nbextensions directory.
|
|
|
If the requested files are already up to date, no action is taken
|
|
|
unless --overwrite is specified.
|
|
|
"""
|
|
|
|
|
|
examples = """
|
|
|
ipython install-nbextension /path/to/d3.js /path/to/myextension
|
|
|
"""
|
|
|
aliases = aliases
|
|
|
flags = flags
|
|
|
|
|
|
overwrite = Bool(False, config=True, help="Force overwrite of existing files")
|
|
|
verbose = Enum((0,1,2), default_value=1, config=True,
|
|
|
help="Verbosity level"
|
|
|
)
|
|
|
|
|
|
def install_extensions(self):
|
|
|
install_nbextension(self.extra_args,
|
|
|
overwrite=self.overwrite,
|
|
|
verbose=self.verbose,
|
|
|
ipython_dir=self.ipython_dir,
|
|
|
)
|
|
|
|
|
|
def start(self):
|
|
|
if not self.extra_args:
|
|
|
nbext = pjoin(self.ipython_dir, u'nbextensions')
|
|
|
print("Notebook extensions in %s:" % nbext)
|
|
|
for ext in os.listdir(nbext):
|
|
|
print(u" %s" % ext)
|
|
|
else:
|
|
|
self.install_extensions()
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
NBExtensionApp.launch_instance()
|
|
|
|