|
|
#!/usr/bin/python
|
|
|
"""Utility function for installing MathJax javascript library into
|
|
|
your IPython nbextensions directory, for offline use.
|
|
|
|
|
|
Authors:
|
|
|
|
|
|
* Min RK
|
|
|
* Mark Sienkiewicz
|
|
|
* Matthias Bussonnier
|
|
|
|
|
|
To download and install MathJax:
|
|
|
|
|
|
From Python:
|
|
|
|
|
|
>>> from IPython.external.mathjax import install_mathjax
|
|
|
>>> install_mathjax()
|
|
|
|
|
|
From the command line:
|
|
|
|
|
|
$ python -m IPython.external.mathjax
|
|
|
|
|
|
To a specific location:
|
|
|
|
|
|
$ python -m IPython.external.mathjax -i /usr/share/
|
|
|
|
|
|
will install mathjax to /usr/share/mathjax
|
|
|
|
|
|
To install MathJax from a file you have already downloaded:
|
|
|
|
|
|
$ python -m IPython.external.mathjax mathjax-xxx.tar.gz
|
|
|
$ python -m IPython.external.mathjax mathjax-xxx.zip
|
|
|
|
|
|
It will not install MathJax if it is already there. Use -r to
|
|
|
replace the existing copy of MathJax.
|
|
|
|
|
|
To find the directory where IPython would like MathJax installed:
|
|
|
|
|
|
$ python -m IPython.external.mathjax -d
|
|
|
|
|
|
"""
|
|
|
from __future__ import print_function
|
|
|
|
|
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
# Copyright (C) 2011 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.
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
# Imports
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
|
|
import argparse
|
|
|
import os
|
|
|
import shutil
|
|
|
import sys
|
|
|
import tarfile
|
|
|
import zipfile
|
|
|
|
|
|
from IPython.utils.path import get_ipython_dir
|
|
|
|
|
|
try:
|
|
|
from urllib.request import urlopen # Py 3
|
|
|
except ImportError:
|
|
|
from urllib2 import urlopen
|
|
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
#
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
|
|
# Where mathjax will be installed
|
|
|
|
|
|
nbextensions = os.path.join(get_ipython_dir(), 'nbextensions')
|
|
|
default_dest = os.path.join(nbextensions, 'mathjax')
|
|
|
|
|
|
# Test for access to install mathjax
|
|
|
|
|
|
def prepare_dest(dest, replace=False):
|
|
|
"""prepare the destination folder for mathjax install
|
|
|
|
|
|
Returns False if mathjax appears to already be installed and there is nothing to do,
|
|
|
True otherwise.
|
|
|
"""
|
|
|
|
|
|
parent = os.path.abspath(os.path.join(dest, os.path.pardir))
|
|
|
if not os.path.exists(parent):
|
|
|
os.makedirs(parent)
|
|
|
|
|
|
if os.path.exists(dest):
|
|
|
if replace:
|
|
|
print("removing existing MathJax at %s" % dest)
|
|
|
shutil.rmtree(dest)
|
|
|
return True
|
|
|
else:
|
|
|
mathjax_js = os.path.join(dest, 'MathJax.js')
|
|
|
if not os.path.exists(mathjax_js):
|
|
|
raise IOError("%s exists, but does not contain MathJax.js" % dest)
|
|
|
print("%s already exists" % mathjax_js)
|
|
|
return False
|
|
|
else:
|
|
|
return True
|
|
|
|
|
|
|
|
|
def extract_tar(fd, dest):
|
|
|
"""extract a tarball from filelike `fd` to destination `dest`"""
|
|
|
# use 'r|gz' stream mode, because socket file-like objects can't seek:
|
|
|
tar = tarfile.open(fileobj=fd, mode='r|gz')
|
|
|
|
|
|
# The first entry in the archive is the top-level dir
|
|
|
topdir = tar.firstmember.path
|
|
|
|
|
|
# extract the archive (contains a single directory) to the destination directory
|
|
|
parent = os.path.abspath(os.path.join(dest, os.path.pardir))
|
|
|
tar.extractall(parent)
|
|
|
|
|
|
# it will be mathjax-MathJax-<sha>, rename to just mathjax
|
|
|
os.rename(os.path.join(parent, topdir), dest)
|
|
|
|
|
|
|
|
|
def extract_zip(fd, dest):
|
|
|
"""extract a zip file from filelike `fd` to destination `dest`"""
|
|
|
z = zipfile.ZipFile(fd, 'r')
|
|
|
|
|
|
# The first entry in the archive is the top-level dir
|
|
|
topdir = z.namelist()[0]
|
|
|
|
|
|
# extract the archive (contains a single directory) to the static/ directory
|
|
|
parent = os.path.abspath(os.path.join(dest, os.path.pardir))
|
|
|
z.extractall(parent)
|
|
|
|
|
|
# it will be mathjax-MathJax-<sha>, rename to just mathjax
|
|
|
os.rename(os.path.join(parent, topdir), dest)
|
|
|
|
|
|
|
|
|
def install_mathjax(tag='2.4.0', dest=default_dest, replace=False, file=None, extractor=extract_tar):
|
|
|
"""Download and/or install MathJax for offline use.
|
|
|
|
|
|
This will install mathjax to the nbextensions dir in your IPYTHONDIR.
|
|
|
|
|
|
MathJax is a ~15MB download, and ~150MB installed.
|
|
|
|
|
|
Parameters
|
|
|
----------
|
|
|
|
|
|
replace : bool [False]
|
|
|
Whether to remove and replace an existing install.
|
|
|
dest : str [IPYTHONDIR/nbextensions/mathjax]
|
|
|
Where to install mathjax
|
|
|
tag : str ['2.4.0']
|
|
|
Which tag to download. Default is '2.4.0', the current stable release,
|
|
|
but alternatives include 'v1.1a' and 'master'.
|
|
|
file : file like object [ defualt to content of https://github.com/mathjax/MathJax/tarball/#{tag}]
|
|
|
File handle from which to untar/unzip/... mathjax
|
|
|
extractor : function
|
|
|
Method to use to untar/unzip/... `file`
|
|
|
"""
|
|
|
try:
|
|
|
anything_to_do = prepare_dest(dest, replace)
|
|
|
except OSError as e:
|
|
|
print("ERROR %s, require write access to %s" % (e, dest))
|
|
|
return 1
|
|
|
else:
|
|
|
if not anything_to_do:
|
|
|
return 0
|
|
|
|
|
|
if file is None:
|
|
|
# download mathjax
|
|
|
mathjax_url = "https://github.com/mathjax/MathJax/archive/%s.tar.gz" %tag
|
|
|
print("Downloading mathjax source from %s" % mathjax_url)
|
|
|
response = urlopen(mathjax_url)
|
|
|
file = response.fp
|
|
|
|
|
|
print("Extracting to %s" % dest)
|
|
|
extractor(file, dest)
|
|
|
return 0
|
|
|
|
|
|
|
|
|
def main():
|
|
|
parser = argparse.ArgumentParser(
|
|
|
description="""Install mathjax from internet or local archive""",
|
|
|
)
|
|
|
|
|
|
parser.add_argument(
|
|
|
'-i',
|
|
|
'--install-dir',
|
|
|
default=nbextensions,
|
|
|
help='custom installation directory. Mathjax will be installed in here/mathjax')
|
|
|
|
|
|
parser.add_argument(
|
|
|
'-d',
|
|
|
'--print-dest',
|
|
|
action='store_true',
|
|
|
help='print where mathjax would be installed and exit')
|
|
|
parser.add_argument(
|
|
|
'-r',
|
|
|
'--replace',
|
|
|
action='store_true',
|
|
|
help='Whether to replace current mathjax if it already exists')
|
|
|
parser.add_argument('filename',
|
|
|
help="the local tar/zip-ball filename containing mathjax",
|
|
|
nargs='?',
|
|
|
metavar='filename')
|
|
|
|
|
|
pargs = parser.parse_args()
|
|
|
|
|
|
dest = os.path.join(pargs.install_dir, 'mathjax')
|
|
|
|
|
|
if pargs.print_dest:
|
|
|
print(dest)
|
|
|
return
|
|
|
|
|
|
# remove/replace existing mathjax?
|
|
|
replace = pargs.replace
|
|
|
|
|
|
# do it
|
|
|
if pargs.filename:
|
|
|
fname = pargs.filename
|
|
|
|
|
|
# automatically detect zip/tar - could do something based
|
|
|
# on file content, but really not cost-effective here.
|
|
|
if fname.endswith('.zip'):
|
|
|
extractor = extract_zip
|
|
|
else :
|
|
|
extractor = extract_tar
|
|
|
# do it
|
|
|
return install_mathjax(file=open(fname, "rb"), replace=replace, extractor=extractor, dest=dest)
|
|
|
else:
|
|
|
return install_mathjax(replace=replace, dest=dest)
|
|
|
|
|
|
|
|
|
if __name__ == '__main__' :
|
|
|
sys.exit(main())
|
|
|
|
|
|
__all__ = ['install_mathjax', 'main', 'default_dest']
|
|
|
|