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