IPython in a standalone, executable zip file
[Contributed by Lisandro Dalcin of MPI4Py and Cython fame, thanks!].
With the code below, you can make a standalone executable zip file that contains all of IPython. The code as written is made for 0.10, but it's easy enough to adapt (we'll likely include it in IPython proper as a utility). If you update the library layout for the post-0.10 refactoring, please post an updated version below.
1 ## Author: Lisandro Dalcin
2 ## Contact: dalcinl@gmail.com
3
4 import sys, os
5 import glob
6 from zipfile import ZipFile
7 from zipfile import ZIP_STORED
8 from zipfile import ZIP_DEFLATED
9 try:
10 import zlib
11 except ImportError:
12 zlib = None
13
14 origin = 'IPython'
15
16 includes = [
17 'IPython/*.py',
18 'IPython/config/*.py',
19 'IPython/Extensions/*.py',
20 'IPython/external/*.py',
21 'IPython/frontend/*.py',
22 'IPython/frontend/*/*.py',
23 'IPython/gui/*.py',
24 'IPython/gui/*/*.py',
25 'IPython/kernel/*.py',
26 'IPython/kernel/*/*.py',
27 'IPython/testing/*.py',
28 'IPython/testing/*/*.py',
29 'IPython/tools/*.py',
30 'IPython/UserConfig/*.py',
31 ]
32
33 target = 'ipython.zip'
34
35 header = """\
36 #!/bin/sh
37 exec python -c "
38 import sys, os
39 sys.path.insert(0, os.path.abspath('$0'))
40 import IPython.Shell
41 IPython.Shell.start().mainloop()
42 " $@
43 """
44
45 header_win = '\r\n'.join("""\
46 @echo off
47 setlocal
48 set _cmd=%_cmd%import sys, os;
49 set _cmd=%_cmd%sys.path.insert(0,os.path.abspath('%0'));
50 set _cmd=%_cmd%import IPython.Shell;
51 set _cmd=%_cmd%IPython.Shell.start().mainloop();
52 python.exe -c "%_cmd%" %*
53 goto :eof
54 """.split('\n'))
55
56 if 'win' in sys.platform:
57 target = os.path.splitext(target)[0]+'.bat'
58 header = header_win
59
60 script = ("ipython.py", """\
61 #!/usr/bin/env python
62 import IPython.Shell
63 IPython.Shell.start().mainloop()
64 """)
65
66 try:
67 prefix = sys.argv[1]
68 prefix = os.path.expanduser(prefix)
69 prefix = os.path.normpath(prefix)
70 except IndexError:
71 package = __import__(origin)
72 pkgroot = os.path.dirname(package.__file__)
73 prefix = os.path.dirname(pkgroot)
74 assert os.path.isdir(prefix)
75
76 filelist = []
77 for pattern in includes:
78 files = glob.glob(os.path.join(prefix, pattern))
79 filelist += sorted(files, key=str.lower)
80 assert filelist
81
82 # white shell-script header
83 fobj = open(target, 'wb')
84 fobj.write(header.encode('ascii'))
85 fobj.close()
86
87 # add files to the ZIP archive
88 if zlib is not None:
89 compression = ZIP_DEFLATED
90 else:
91 compression = ZIP_STORED
92 fobj = ZipFile(target, 'a', compression)
93 fobj.writestr(script[0], script[1])
94 for filename in filelist:
95 arcname = filename[len(prefix)+1:]
96 fobj.write(filename, arcname)
97 fobj.close()
98
99 # make the ZIP file executable
100 try:
101 try:
102 mode = eval('0o755')
103 except SyntaxError:
104 mode = eval('0755')
105 os.chmod(target, mode)
106 except:
107 pass