mathjax.py
234 lines
| 6.9 KiB
| text/x-python
|
PythonLexer
Matthias BUSSONNIER
|
r8682 | #!/usr/bin/python | ||
MinRK
|
r4652 | """Utility function for installing MathJax javascript library into | ||
MinRK
|
r12811 | your IPython nbextensions directory, for offline use. | ||
MinRK
|
r4652 | |||
Matthias BUSSONNIER
|
r8507 | Authors: | ||
* Min RK | ||||
* Mark Sienkiewicz | ||||
* Matthias Bussonnier | ||||
Mark Sienkiewicz at STScI
|
r8154 | 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 | ||||
MinRK
|
r12809 | To a specific location: | ||
Kyle Kelley
|
r12292 | |||
MinRK
|
r12812 | $ python -m IPython.external.mathjax -i /usr/share/ | ||
will install mathjax to /usr/share/mathjax | ||||
Kyle Kelley
|
r12292 | |||
Mark Sienkiewicz at STScI
|
r8154 | 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 | ||||
MinRK
|
r4652 | |||
""" | ||||
Thomas Kluyver
|
r13348 | from __future__ import print_function | ||
MinRK
|
r4652 | |||
Matthias BUSSONNIER
|
r8682 | |||
MinRK
|
r4652 | #----------------------------------------------------------------------------- | ||
MinRK
|
r12812 | # Copyright (C) 2011 The IPython Development Team | ||
MinRK
|
r4652 | # | ||
# Distributed under the terms of the BSD License. The full license is in | ||||
# the file COPYING, distributed as part of this software. | ||||
#----------------------------------------------------------------------------- | ||||
Mark Sienkiewicz at STScI
|
r8154 | |||
MinRK
|
r4652 | #----------------------------------------------------------------------------- | ||
# Imports | ||||
#----------------------------------------------------------------------------- | ||||
Thomas Kluyver
|
r12547 | import argparse | ||
MinRK
|
r4652 | import os | ||
import shutil | ||||
Mark Sienkiewicz at STScI
|
r8154 | import sys | ||
MinRK
|
r4652 | import tarfile | ||
Mark Sienkiewicz at STScI
|
r8154 | import urllib2 | ||
import zipfile | ||||
MinRK
|
r4652 | |||
MinRK
|
r12809 | from IPython.utils.path import get_ipython_dir | ||
Matthias BUSSONNIER
|
r8682 | |||
MinRK
|
r4652 | #----------------------------------------------------------------------------- | ||
Mark Sienkiewicz at STScI
|
r8154 | # | ||
MinRK
|
r4652 | #----------------------------------------------------------------------------- | ||
MinRK
|
r12809 | # Where mathjax will be installed | ||
Mark Sienkiewicz at STScI
|
r8154 | |||
MinRK
|
r12812 | nbextensions = os.path.join(get_ipython_dir(), 'nbextensions') | ||
default_dest = os.path.join(nbextensions, 'mathjax') | ||||
Mark Sienkiewicz at STScI
|
r8154 | |||
MinRK
|
r12809 | # Test for access to install mathjax | ||
Mark Sienkiewicz at STScI
|
r8154 | |||
MinRK
|
r12809 | 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. | ||||
""" | ||||
Matthias BUSSONNIER
|
r8682 | parent = os.path.abspath(os.path.join(dest, os.path.pardir)) | ||
MinRK
|
r12809 | if not os.path.exists(parent): | ||
os.makedirs(parent) | ||||
MinRK
|
r12812 | |||
MinRK
|
r4652 | if os.path.exists(dest): | ||
if replace: | ||||
Thomas Kluyver
|
r13348 | print("removing existing MathJax at %s" % dest) | ||
MinRK
|
r4652 | shutil.rmtree(dest) | ||
Mark Sienkiewicz at STScI
|
r8154 | return True | ||
MinRK
|
r4652 | else: | ||
MinRK
|
r12812 | 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) | ||||
Thomas Kluyver
|
r13348 | print("%s already exists" % mathjax_js) | ||
Mark Sienkiewicz at STScI
|
r8154 | return False | ||
MinRK
|
r12809 | else: | ||
Mark Sienkiewicz at STScI
|
r8154 | return True | ||
MinRK
|
r12809 | def extract_tar(fd, dest): | ||
"""extract a tarball from filelike `fd` to destination `dest`""" | ||||
MinRK
|
r4652 | # use 'r|gz' stream mode, because socket file-like objects can't seek: | ||
Mark Sienkiewicz at STScI
|
r8154 | tar = tarfile.open(fileobj=fd, mode='r|gz') | ||
MinRK
|
r12809 | # The first entry in the archive is the top-level dir | ||
MinRK
|
r4652 | topdir = tar.firstmember.path | ||
Mark Sienkiewicz at STScI
|
r8154 | |||
MinRK
|
r12809 | # extract the archive (contains a single directory) to the destination directory | ||
Matthias BUSSONNIER
|
r8682 | parent = os.path.abspath(os.path.join(dest, os.path.pardir)) | ||
tar.extractall(parent) | ||||
Mark Sienkiewicz at STScI
|
r8154 | |||
MinRK
|
r4652 | # it will be mathjax-MathJax-<sha>, rename to just mathjax | ||
Matthias BUSSONNIER
|
r8682 | os.rename(os.path.join(parent, topdir), dest) | ||
MinRK
|
r4652 | |||
Mark Sienkiewicz at STScI
|
r8154 | |||
MinRK
|
r12809 | def extract_zip(fd, dest): | ||
"""extract a zip file from filelike `fd` to destination `dest`""" | ||||
z = zipfile.ZipFile(fd, 'r') | ||||
Mark Sienkiewicz at STScI
|
r8154 | |||
MinRK
|
r12809 | # The first entry in the archive is the top-level dir | ||
Mark Sienkiewicz at STScI
|
r8154 | topdir = z.namelist()[0] | ||
# extract the archive (contains a single directory) to the static/ directory | ||||
Matthias BUSSONNIER
|
r8682 | parent = os.path.abspath(os.path.join(dest, os.path.pardir)) | ||
MinRK
|
r12809 | z.extractall(parent) | ||
Mark Sienkiewicz at STScI
|
r8154 | |||
# it will be mathjax-MathJax-<sha>, rename to just mathjax | ||||
Matthias BUSSONNIER
|
r8682 | d = os.path.join(parent, topdir) | ||
os.rename(os.path.join(parent, topdir), dest) | ||||
Mark Sienkiewicz at STScI
|
r8154 | |||
MinRK
|
r12809 | def install_mathjax(tag='v2.2', dest=default_dest, replace=False, file=None, extractor=extract_tar): | ||
Matthias BUSSONNIER
|
r8507 | """Download and/or install MathJax for offline use. | ||
Mark Sienkiewicz at STScI
|
r8154 | |||
MinRK
|
r12811 | This will install mathjax to the nbextensions dir in your IPYTHONDIR. | ||
Mark Sienkiewicz at STScI
|
r8154 | |||
MathJax is a ~15MB download, and ~150MB installed. | ||||
Parameters | ||||
---------- | ||||
replace : bool [False] | ||||
Whether to remove and replace an existing install. | ||||
MinRK
|
r12812 | dest : str [IPYTHONDIR/nbextensions/mathjax] | ||
Where to install mathjax | ||||
MinRK
|
r12809 | tag : str ['v2.2'] | ||
Which tag to download. Default is 'v2.2', the current stable release, | ||||
Mark Sienkiewicz at STScI
|
r8154 | but alternatives include 'v1.1a' and 'master'. | ||
Matthias BUSSONNIER
|
r8507 | 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 | ||||
MinRK
|
r12809 | Method to use to untar/unzip/... `file` | ||
Mark Sienkiewicz at STScI
|
r8154 | """ | ||
MinRK
|
r12809 | try: | ||
anything_to_do = prepare_dest(dest, replace) | ||||
except OSError as e: | ||||
Thomas Kluyver
|
r13348 | print(("ERROR %s, require write access to %s" % (e, dest))) | ||
MinRK
|
r12809 | return 1 | ||
else: | ||||
if not anything_to_do: | ||||
return 0 | ||||
Mark Sienkiewicz at STScI
|
r8154 | |||
MinRK
|
r12809 | if file is None: | ||
Mark Sienkiewicz at STScI
|
r8154 | # download mathjax | ||
ahmadia
|
r12875 | mathjax_url = "https://github.com/mathjax/MathJax/archive/%s.tar.gz" %tag | ||
Thomas Kluyver
|
r13348 | print("Downloading mathjax source from %s" % mathjax_url) | ||
Mark Sienkiewicz at STScI
|
r8154 | response = urllib2.urlopen(mathjax_url) | ||
Matthias BUSSONNIER
|
r8507 | file = response.fp | ||
Mark Sienkiewicz at STScI
|
r8154 | |||
Thomas Kluyver
|
r13348 | print("Extracting to %s" % dest) | ||
MinRK
|
r12809 | extractor(file, dest) | ||
return 0 | ||||
def main(): | ||||
Matthias BUSSONNIER
|
r8682 | parser = argparse.ArgumentParser( | ||
description="""Install mathjax from internet or local archive""", | ||||
MinRK
|
r12809 | ) | ||
Kyle Kelley
|
r12287 | |||
parser.add_argument( | ||||
Matthias BUSSONNIER
|
r8682 | '-i', | ||
'--install-dir', | ||||
MinRK
|
r12812 | default=nbextensions, | ||
help='custom installation directory. Mathjax will be installed in here/mathjax') | ||||
Kyle Kelley
|
r12291 | |||
Matthias BUSSONNIER
|
r8682 | parser.add_argument( | ||
'-d', | ||||
MinRK
|
r12809 | '--print-dest', | ||
Matthias BUSSONNIER
|
r8682 | action='store_true', | ||
MinRK
|
r12809 | help='print where mathjax would be installed and exit') | ||
Matthias BUSSONNIER
|
r8682 | parser.add_argument( | ||
'-r', | ||||
'--replace', | ||||
action='store_true', | ||||
Kyle Kelley
|
r12287 | help='Whether to replace current mathjax if it already exists') | ||
MinRK
|
r12809 | parser.add_argument('filename', | ||
help="the local tar/zip-ball filename containing mathjax", | ||||
Matthias BUSSONNIER
|
r8682 | nargs='?', | ||
MinRK
|
r12809 | metavar='filename') | ||
Matthias BUSSONNIER
|
r8682 | |||
pargs = parser.parse_args() | ||||
MinRK
|
r12812 | dest = os.path.join(pargs.install_dir, 'mathjax') | ||
Kyle Kelley
|
r12287 | |||
MinRK
|
r12809 | if pargs.print_dest: | ||
Thomas Kluyver
|
r13348 | print(dest) | ||
Mark Sienkiewicz at STScI
|
r8154 | return | ||
# remove/replace existing mathjax? | ||||
MinRK
|
r12809 | replace = pargs.replace | ||
Mark Sienkiewicz at STScI
|
r8154 | |||
Matthias BUSSONNIER
|
r8507 | # do it | ||
MinRK
|
r12809 | if pargs.filename: | ||
fname = pargs.filename | ||||
Mark Sienkiewicz at STScI
|
r8154 | |||
# automatically detect zip/tar - could do something based | ||||
Matthias BUSSONNIER
|
r8682 | # on file content, but really not cost-effective here. | ||
MinRK
|
r12809 | if fname.endswith('.zip'): | ||
Mark Sienkiewicz at STScI
|
r8154 | extractor = extract_zip | ||
else : | ||||
extractor = extract_tar | ||||
# do it | ||||
MinRK
|
r12809 | return install_mathjax(file=open(fname, "rb"), replace=replace, extractor=extractor, dest=dest) | ||
Matthias BUSSONNIER
|
r8682 | else: | ||
MinRK
|
r12809 | return install_mathjax(replace=replace, dest=dest) | ||
Matthias BUSSONNIER
|
r8682 | |||
Mark Sienkiewicz at STScI
|
r8154 | |||
if __name__ == '__main__' : | ||||
Matthias BUSSONNIER
|
r8682 | sys.exit(main()) | ||
MinRK
|
r4652 | |||
Paul Ivanov
|
r12401 | __all__ = ['install_mathjax', 'main', 'default_dest'] | ||