##// END OF EJS Templates
use argparse to make most of the parameters configurable
Matthias BUSSONNIER -
Show More
@@ -1,271 +1,304 b''
1 #!/usr/bin/python
1 """Utility function for installing MathJax javascript library into
2 """Utility function for installing MathJax javascript library into
2 the notebook's 'static' directory, for offline use.
3 the notebook's 'static' directory, for offline use.
3
4
4 Authors:
5 Authors:
5
6
6 * Min RK
7 * Min RK
7 * Mark Sienkiewicz
8 * Mark Sienkiewicz
8 * Matthias Bussonnier
9 * Matthias Bussonnier
9
10
10 To download and install MathJax:
11 To download and install MathJax:
11
12
12 From Python:
13 From Python:
13
14
14 >>> from IPython.external.mathjax import install_mathjax
15 >>> from IPython.external.mathjax import install_mathjax
15 >>> install_mathjax()
16 >>> install_mathjax()
16
17
17 From the command line:
18 From the command line:
18
19
19 $ python -m IPython.external.mathjax
20 $ python -m IPython.external.mathjax
20
21
21 To install MathJax from a file you have already downloaded:
22 To install MathJax from a file you have already downloaded:
22
23
23 $ python -m IPython.external.mathjax mathjax-xxx.tar.gz
24 $ python -m IPython.external.mathjax mathjax-xxx.tar.gz
24 $ python -m IPython.external.mathjax mathjax-xxx.zip
25 $ python -m IPython.external.mathjax mathjax-xxx.zip
25
26
26 It will not install MathJax if it is already there. Use -r to
27 It will not install MathJax if it is already there. Use -r to
27 replace the existing copy of MathJax.
28 replace the existing copy of MathJax.
28
29
29 To find the directory where IPython would like MathJax installed:
30 To find the directory where IPython would like MathJax installed:
30
31
31 $ python -m IPython.external.mathjax -d
32 $ python -m IPython.external.mathjax -d
32
33
33 """
34 """
34
35
36
35 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
36 # Copyright (C) 2008-2011 The IPython Development Team
38 # Copyright (C) 2008-2011 The IPython Development Team
37 #
39 #
38 # Distributed under the terms of the BSD License. The full license is in
40 # Distributed under the terms of the BSD License. The full license is in
39 # the file COPYING, distributed as part of this software.
41 # the file COPYING, distributed as part of this software.
40 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
41
43
42
44
43 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
44 # Imports
46 # Imports
45 #-----------------------------------------------------------------------------
47 #-----------------------------------------------------------------------------
46
48
47 import os
49 import os
48 import shutil
50 import shutil
49 import sys
51 import sys
50 import tarfile
52 import tarfile
51 import urllib2
53 import urllib2
52 import zipfile
54 import zipfile
53
55
56
54 from IPython.utils.path import locate_profile
57 from IPython.utils.path import locate_profile
58 from IPython.external import argparse
55 #-----------------------------------------------------------------------------
59 #-----------------------------------------------------------------------------
56 #
60 #
57 #-----------------------------------------------------------------------------
61 #-----------------------------------------------------------------------------
58
62
59 # Where mathjax will be installed.
63 # Where mathjax will be installed.
60
64
61 default_dest = os.path.join(locate_profile('default'), 'static')
65 static = os.path.join(locate_profile('default'), 'static')
66 default_dest = os.path.join(static, 'mathjax')
62
67
63 ##
68 ##
64
69
65 # Test for access to install mathjax.
70 # Test for access to install mathjax.
66
71
67 def check_perms(replace=False, dest=default_dest):
72 def check_perms(dest, replace=False):
68 if not os.access(static, os.W_OK):
73 parent = os.path.abspath(os.path.join(dest, os.path.pardir))
69 raise IOError("Need have write access to %s" % static)
74 if not os.access(parent, os.W_OK):
75 raise IOError("Need have write access to %s" % parent)
70 if os.path.exists(dest):
76 if os.path.exists(dest):
71 if replace:
77 if replace:
72 if not os.access(dest, os.W_OK):
78 if not os.access(dest, os.W_OK):
73 raise IOError("Need have write access to %s" % dest)
79 raise IOError("Need have write access to %s" % dest)
74 print "removing previous MathJax install"
80 print "removing previous MathJax install"
75 shutil.rmtree(dest)
81 shutil.rmtree(dest)
76 return True
82 return True
77 else:
83 else:
78 print "offline MathJax apparently already installed"
84 print "offline MathJax apparently already installed"
79 return False
85 return False
80 else :
86 else :
81 return True
87 return True
82
88
83 ##
89 ##
84
90
85 def extract_tar( fd, dest ) :
91 def extract_tar( fd, dest ) :
86 # use 'r|gz' stream mode, because socket file-like objects can't seek:
92 # use 'r|gz' stream mode, because socket file-like objects can't seek:
87 tar = tarfile.open(fileobj=fd, mode='r|gz')
93 tar = tarfile.open(fileobj=fd, mode='r|gz')
88
94
89 # we just happen to know that the first entry in the mathjax
95 # we just happen to know that the first entry in the mathjax
90 # archive is the directory that the remaining members are in.
96 # archive is the directory that the remaining members are in.
91 topdir = tar.firstmember.path
97 topdir = tar.firstmember.path
92
98
93 # extract the archive (contains a single directory) to the static/ directory
99 # extract the archive (contains a single directory) to the static/ directory
94 tar.extractall(static)
100 parent = os.path.abspath(os.path.join(dest, os.path.pardir))
101 tar.extractall(parent)
95
102
96 # it will be mathjax-MathJax-<sha>, rename to just mathjax
103 # it will be mathjax-MathJax-<sha>, rename to just mathjax
97 os.rename(os.path.join(static, topdir), dest)
104 os.rename(os.path.join(parent, topdir), dest)
98
105
99 ##
106 ##
100
107
101 def extract_zip( fd, dest ) :
108 def extract_zip( fd, dest ) :
102 z = zipfile.ZipFile( fd, 'r' )
109 z = zipfile.ZipFile( fd, 'r' )
103
110
104 # we just happen to know that the first entry in the mathjax
111 # we just happen to know that the first entry in the mathjax
105 # archive is the directory that the remaining members are in.
112 # archive is the directory that the remaining members are in.
106 topdir = z.namelist()[0]
113 topdir = z.namelist()[0]
107
114
108 # extract the archive (contains a single directory) to the static/ directory
115 # extract the archive (contains a single directory) to the static/ directory
109 z.extractall( static )
116 parent = os.path.abspath(os.path.join(dest, os.path.pardir))
117 z.extractall( parent )
110
118
111 # it will be mathjax-MathJax-<sha>, rename to just mathjax
119 # it will be mathjax-MathJax-<sha>, rename to just mathjax
112 d = os.path.join(static, topdir)
120 d = os.path.join(parent, topdir)
113 print d
121 print d
114 os.rename(os.path.join(static, topdir), dest)
122 os.rename(os.path.join(parent, topdir), dest)
115
123
116 ##
124 ##
117
125
118 def install_mathjax(tag='v2.0', dest=default_dest, replace=False, file=None, extractor=extract_tar ):
126 def install_mathjax(tag='v2.0', dest=default_dest, replace=False, file=None, extractor=extract_tar ):
119 """Download and/or install MathJax for offline use.
127 """Download and/or install MathJax for offline use.
120
128
121 This will install mathjax to the 'static' dir in the IPython notebook
129 This will install mathjax to the 'static' dir in the IPython notebook
122 package, so it will fail if the caller does not have write access
130 package, so it will fail if the caller does not have write access
123 to that location.
131 to that location.
124
132
125 MathJax is a ~15MB download, and ~150MB installed.
133 MathJax is a ~15MB download, and ~150MB installed.
126
134
127 Parameters
135 Parameters
128 ----------
136 ----------
129
137
130 replace : bool [False]
138 replace : bool [False]
131 Whether to remove and replace an existing install.
139 Whether to remove and replace an existing install.
132 dest : str [path to default profile]
140 dest : str [path to default profile]
133 Where to locally install mathjax
141 Where to locally install mathjax
134 tag : str ['v2.0']
142 tag : str ['v2.0']
135 Which tag to download. Default is 'v2.0', the current stable release,
143 Which tag to download. Default is 'v2.0', the current stable release,
136 but alternatives include 'v1.1a' and 'master'.
144 but alternatives include 'v1.1a' and 'master'.
137 file : file like object [ defualt to content of https://github.com/mathjax/MathJax/tarball/#{tag}]
145 file : file like object [ defualt to content of https://github.com/mathjax/MathJax/tarball/#{tag}]
138 File handle from which to untar/unzip/... mathjax
146 File handle from which to untar/unzip/... mathjax
139 extractor : function
147 extractor : function
140 Method tu use to untar/unzip/... `file`
148 Method tu use to untar/unzip/... `file`
141 """
149 """
142
150 if not check_perms(dest, replace) :
143 if not check_perms(replace, dest=dest) :
144 return
151 return
145
152
146 if file is None :
153 if file is None :
147 # download mathjax
154 # download mathjax
148 mathjax_url = "https://github.com/mathjax/MathJax/tarball/%s"%tag
155 mathjax_url = "https://github.com/mathjax/MathJax/tarball/%s" % tag
149 print "Downloading mathjax source from %s"%mathjax_url
156 print "Downloading mathjax source from %s" % mathjax_url
150 response = urllib2.urlopen(mathjax_url)
157 response = urllib2.urlopen(mathjax_url)
151 file = response.fp
158 file = response.fp
152
159
153 print "Extracting to %s"%dest
160 print "Extracting to %s" % dest
154 extractor( fd, dest )
161 extractor( file, dest )
155
162
156 ##
163 ##
157
164
158 def test_func( remove, dest=default_dest) :
165 def test_func( remove, dest) :
159 """See if mathjax appears to be installed correctly"""
166 """See if mathjax appears to be installed correctly"""
167 status = 0
160 if not os.path.isdir( dest ) :
168 if not os.path.isdir( dest ) :
161 print "%s directory not found"%dest
169 print "%s directory not found" % dest
162 status=1
170 status = 1
163 if not os.path.exists( dest + "/MathJax.js" ) :
171 if not os.path.exists( dest + "/MathJax.js" ) :
164 print "MathJax.js not present in %s"%dest
172 print "MathJax.js not present in %s" % dest
165 status=1
173 status = 1
166 print "ok"
174 print "ok"
167 if remove :
175 if remove and os.path.exists(dest):
168 shutil.rmtree( dest )
176 shutil.rmtree( dest )
169 return status
177 return status
170
178
171 ##
179 ##
172
180
173 def main( args ) :
181 def main() :
174 # This main is just simple enough that it is not worth the
182 # This main is just simple enough that it is not worth the
175 # complexity of argparse
183 # complexity of argparse
176
184
177 # What directory is mathjax in?
185 # What directory is mathjax in?
178 if '-d' in args :
186 parser = argparse.ArgumentParser(
187 description="""Install mathjax from internet or local archive""",
188 )
189
190 parser.add_argument(
191 '-i',
192 '--install-dir',
193 default=default_dest,
194 help='installation directory (by default : %s)' % (default_dest))
195 parser.add_argument(
196 '-d',
197 '--dest',
198 action='store_true',
199 help='print where is current mathjax would be installed and exit')
200 parser.add_argument(
201 '-r',
202 '--replace',
203 action='store_true',
204 help='Wether to replace current mathjax if already exist')
205 parser.add_argument(
206 '-t',
207 '--test',
208 action='store_true')
209 parser.add_argument('tarball',
210 type=int,
211 help="the local tar/zip-ball containing mathjax",
212 nargs='?',
213 metavar='tarball')
214
215 pargs = parser.parse_args()
216
217 dest = pargs.install_dir
218 if pargs.dest :
179 print dest
219 print dest
180 return
220 return
181
221
182 # help
183 if '-h' in args or '--help' in args :
184 print __doc__
185 return
186
187 # remove/replace existing mathjax?
222 # remove/replace existing mathjax?
188 if '-r' in args :
223 if pargs.replace :
189 replace = True
224 replace = True
190 args.remove('-r')
191 else :
225 else :
192 replace = False
226 replace = False
193
227
194 # undocumented test interface
228 # undocumented test interface
195 if '-test' in args :
229 if pargs.test :
196 return test_func( replace, dest=dest)
230 return test_func( replace, dest)
197
231
198 # do it
232 # do it
199 if len(args) == 0 :
233 if pargs.tarball :
200 # This is compatible with the interface documented in ipython 0.13
234 fname = pargs.tarball
201 install_mathjax( replace=replace )
202 else :
203 fname = args[0]
204
235
205 # automatically detect zip/tar - could do something based
236 # automatically detect zip/tar - could do something based
206 # on file content, but really not cost-effective here.
237 # on file content, but really not cost-effective here.
207 if fname.endswith('.zip') :
238 if fname.endswith('.zip') :
208 extractor = extract_zip
239 extractor = extract_zip
209 else :
240 else :
210 extractor = extract_tar
241 extractor = extract_tar
211
212 # do it
242 # do it
213 install_mathjax(fd=open(args[0],"r"), replace=replace, extractor=extractor )
243 install_mathjax(file=open(fname, "r"), replace=replace, extractor=extractor, dest=dest )
244 else:
245 install_mathjax(replace=replace, dest=dest)
246
214
247
215 if __name__ == '__main__' :
248 if __name__ == '__main__' :
216 sys.exit(main( sys.argv[1:] ))
249 sys.exit(main())
217
250
218 __all__ = ['install_mathjax','main','dest']
251 __all__ = ['install_mathjax', 'main', 'dest']
219
252
220 """
253 """
221 Test notes:
254 Test notes:
222
255
223 IPython uses IPython.testing.iptest as a custom test controller
256 IPython uses IPython.testing.iptest as a custom test controller
224 (though it is based on nose). It might be possible to fit automatic
257 (though it is based on nose). It might be possible to fit automatic
225 tests of installation into that framework, but it looks awkward to me.
258 tests of installation into that framework, but it looks awkward to me.
226 So, here is a manual procedure for testing this automatic installer.
259 So, here is a manual procedure for testing this automatic installer.
227
260
228 Mark Sienkiewicz, 2012-08-06
261 Mark Sienkiewicz, 2012-08-06
229 first 8 letters of my last name @ stsci.edu
262 first 8 letters of my last name @ stsci.edu
230
263
231 # remove mathjax from the installed ipython instance
264 # remove mathjax from the installed ipython instance
232 # IOError ok if mathjax was never installed yet.
265 # IOError ok if mathjax was never installed yet.
233
266
234 python -m IPython.external.mathjax -test -r
267 python -m IPython.external.mathjax --test -r
235
268
236 # download and install mathjax from command line:
269 # download and install mathjax from command line:
237
270
238 python -m IPython.external.mathjax
271 python -m IPython.external.mathjax
239 python -m IPython.external.mathjax -test -r
272 python -m IPython.external.mathjax --test -r
240
273
241 # download and install from within python
274 # download and install from within python
242
275
243 python -c "from IPython.external.mathjax import install_mathjax; install_mathjax()"
276 python -c "from IPython.external.mathjax import install_mathjax; install_mathjax()"
244 python -m IPython.external.mathjax -test -r
277 python -m IPython.external.mathjax --test -r
245
278
246 # view http://www.mathjax.org/download/ in your browser
279 # view http://www.mathjax.org/download/ in your browser
247 # save-as the link for MathJax-2.0 near the bottom of the page.
280 # save-as the link for MathJax-2.0 near the bottom of the page.
248 # The file it offers is mathjax-MathJax-v2.0-20-g07669ac.zip
281 # The file it offers is mathjax-MathJax-v2.0-20-g07669ac.zip
249
282
250 python -m IPython.external.mathjax mathjax-MathJax-v2.0-20-g07669ac.zip
283 python -m IPython.external.mathjax mathjax-MathJax-v2.0-20-g07669ac.zip
251 python -m IPython.external.mathjax -test -r
284 python -m IPython.external.mathjax --test -r
252
285
253 # download https://github.com/mathjax/MathJax/tarball/v2.0 in your browser
286 # download https://github.com/mathjax/MathJax/tarball/v2.0 in your browser
254 # (this is the url used internally by install_mathjax)
287 # (this is the url used internally by install_mathjax)
255 # The file it offers is mathjax-MathJax-v2.0-20-g07669ac.tar.gz
288 # The file it offers is mathjax-MathJax-v2.0-20-g07669ac.tar.gz
256
289
257 python -m IPython.external.mathjax mathjax-MathJax-v2.0-20-g07669ac.tar.gz
290 python -m IPython.external.mathjax mathjax-MathJax-v2.0-20-g07669ac.tar.gz
258
291
259 python -m IPython.external.mathjax -test
292 python -m IPython.external.mathjax --test
260 # note no -r
293 # note no -r
261
294
262 # install it again while it is already there
295 # install it again while it is already there
263
296
264 python -m IPython.external.mathjax mathjax-MathJax-v2.0-20-g07669ac.tar.gz
297 python -m IPython.external.mathjax mathjax-MathJax-v2.0-20-g07669ac.tar.gz
265 # says "offline MathJax apparently already installed"
298 # says "offline MathJax apparently already installed"
266
299
267 python -m IPython.external.mathjax ~/mathjax-MathJax-v2.0-20-g07669ac.tar.gz
300 python -m IPython.external.mathjax ~/mathjax-MathJax-v2.0-20-g07669ac.tar.gz
268 python -m IPython.external.mathjax -test
301 python -m IPython.external.mathjax --test
269
302
270
303
271 """
304 """
General Comments 0
You need to be logged in to leave comments. Login now