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