##// END OF EJS Templates
Merge pull request #4104 from rgbkrk/mathjax_profile...
Min RK -
r12384:972ed784 merge
parent child Browse files
Show More
@@ -1,315 +1,331
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(
207 '-p',
208 '--profile',
209 default='default',
210 help='profile to install MathJax to (default is default)')
211
212 parser.add_argument(
203 213 '-i',
204 214 '--install-dir',
205 default=default_dest,
206 help='installation directory (by default : %s)' % (default_dest))
215 help='custom installation directory')
216
207 217 parser.add_argument(
208 218 '-d',
209 219 '--dest',
210 220 action='store_true',
211 help='print where is current mathjax would be installed and exit')
221 help='print where current mathjax would be installed and exit')
212 222 parser.add_argument(
213 223 '-r',
214 224 '--replace',
215 225 action='store_true',
216 help='Wether to replace current mathjax if already exist')
226 help='Whether to replace current mathjax if it already exists')
217 227 parser.add_argument(
218 228 '-t',
219 229 '--test',
220 230 action='store_true')
221 231 parser.add_argument('tarball',
222 232 help="the local tar/zip-ball containing mathjax",
223 233 nargs='?',
224 234 metavar='tarball')
225 235
226 236 pargs = parser.parse_args()
227 237
238 if pargs.install_dir:
239 # Explicit install_dir overrides profile
228 240 dest = pargs.install_dir
241 else:
242 profile = pargs.profile
243 dest = os.path.join(locate_profile(profile), 'static', 'mathjax')
244
229 245 if pargs.dest :
230 246 print dest
231 247 return
232 248
233 249 # remove/replace existing mathjax?
234 250 if pargs.replace :
235 251 replace = True
236 252 else :
237 253 replace = False
238 254
239 255 # undocumented test interface
240 256 if pargs.test :
241 257 return test_func( replace, dest)
242 258
243 259 # do it
244 260 if pargs.tarball :
245 261 fname = pargs.tarball
246 262
247 263 # automatically detect zip/tar - could do something based
248 264 # on file content, but really not cost-effective here.
249 265 if fname.endswith('.zip') :
250 266 extractor = extract_zip
251 267 else :
252 268 extractor = extract_tar
253 269 # do it
254 270 install_mathjax(file=open(fname, "r"), replace=replace, extractor=extractor, dest=dest )
255 271 else:
256 272 install_mathjax(replace=replace, dest=dest)
257 273
258 274
259 275 if __name__ == '__main__' :
260 276 sys.exit(main())
261 277
262 278 __all__ = ['install_mathjax', 'main', 'dest']
263 279
264 280 """
265 281 Test notes:
266 282
267 283 IPython uses IPython.testing.iptest as a custom test controller
268 284 (though it is based on nose). It might be possible to fit automatic
269 285 tests of installation into that framework, but it looks awkward to me.
270 286 So, here is a manual procedure for testing this automatic installer.
271 287
272 288 Mark Sienkiewicz, 2012-08-06
273 289 first 8 letters of my last name @ stsci.edu
274 290
275 291 # remove mathjax from the installed ipython instance
276 292 # IOError ok if mathjax was never installed yet.
277 293
278 294 python -m IPython.external.mathjax --test -r
279 295
280 296 # download and install mathjax from command line:
281 297
282 298 python -m IPython.external.mathjax
283 299 python -m IPython.external.mathjax --test -r
284 300
285 301 # download and install from within python
286 302
287 303 python -c "from IPython.external.mathjax import install_mathjax; install_mathjax()"
288 304 python -m IPython.external.mathjax --test -r
289 305
290 306 # view http://www.mathjax.org/download/ in your browser
291 307 # save-as the link for MathJax-2.0 near the bottom of the page.
292 308 # The file it offers is mathjax-MathJax-v2.0-20-g07669ac.zip
293 309
294 310 python -m IPython.external.mathjax mathjax-MathJax-v2.0-20-g07669ac.zip
295 311 python -m IPython.external.mathjax --test -r
296 312
297 313 # download https://github.com/mathjax/MathJax/tarball/v2.0 in your browser
298 314 # (this is the url used internally by install_mathjax)
299 315 # The file it offers is mathjax-MathJax-v2.0-20-g07669ac.tar.gz
300 316
301 317 python -m IPython.external.mathjax mathjax-MathJax-v2.0-20-g07669ac.tar.gz
302 318
303 319 python -m IPython.external.mathjax --test
304 320 # note no -r
305 321
306 322 # install it again while it is already there
307 323
308 324 python -m IPython.external.mathjax mathjax-MathJax-v2.0-20-g07669ac.tar.gz
309 325 # says "offline MathJax apparently already installed"
310 326
311 327 python -m IPython.external.mathjax ~/mathjax-MathJax-v2.0-20-g07669ac.tar.gz
312 328 python -m IPython.external.mathjax --test
313 329
314 330
315 331 """
General Comments 0
You need to be logged in to leave comments. Login now