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