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