##// END OF EJS Templates
fix windows post-installation routines with setuptools installed
Darren Dale -
Show More
@@ -1,97 +1,100 b''
1 #!python
1 #!python
2 """Windows-specific part of the installation"""
2 """Windows-specific part of the installation"""
3
3
4 import os, sys, shutil
4 import os, sys, shutil
5 pjoin = os.path.join
5 pjoin = os.path.join
6
6
7 def mkshortcut(target,description,link_file,*args,**kw):
7 def mkshortcut(target,description,link_file,*args,**kw):
8 """make a shortcut if it doesn't exist, and register its creation"""
8 """make a shortcut if it doesn't exist, and register its creation"""
9
9
10 create_shortcut(target, description, link_file,*args,**kw)
10 create_shortcut(target, description, link_file,*args,**kw)
11 file_created(link_file)
11 file_created(link_file)
12
12
13 def install():
13 def install():
14 """Routine to be run by the win32 installer with the -install switch."""
14 """Routine to be run by the win32 installer with the -install switch."""
15
15
16 from IPython.core.release import version
16 from IPython.core.release import version
17
17
18 # Get some system constants
18 # Get some system constants
19 prefix = sys.prefix
19 prefix = sys.prefix
20 python = pjoin(prefix, 'python.exe')
20 python = pjoin(prefix, 'python.exe')
21
21
22 # Lookup path to common startmenu ...
22 # Lookup path to common startmenu ...
23 ip_start_menu = pjoin(get_special_folder_path('CSIDL_COMMON_PROGRAMS'), 'IPython')
23 ip_start_menu = pjoin(get_special_folder_path('CSIDL_COMMON_PROGRAMS'), 'IPython')
24 # Create IPython entry ...
24 # Create IPython entry ...
25 if not os.path.isdir(ip_start_menu):
25 if not os.path.isdir(ip_start_menu):
26 os.mkdir(ip_start_menu)
26 os.mkdir(ip_start_menu)
27 directory_created(ip_start_menu)
27 directory_created(ip_start_menu)
28
28
29 # Create .py and .bat files to make things available from
29 # Create .py and .bat files to make things available from
30 # the Windows command line. Thanks to the Twisted project
30 # the Windows command line. Thanks to the Twisted project
31 # for this logic!
31 # for this logic!
32 programs = [
32 programs = [
33 'ipython',
33 'ipython',
34 'iptest',
34 'iptest',
35 'ipcontroller',
35 'ipcontroller',
36 'ipengine',
36 'ipengine',
37 'ipcluster',
37 'ipcluster',
38 'irunner'
38 'irunner'
39 ]
39 ]
40 scripts = pjoin(prefix,'scripts')
40 scripts = pjoin(prefix,'scripts')
41 for program in programs:
41 for program in programs:
42 raw = pjoin(scripts, program)
42 raw = pjoin(scripts, program)
43 bat = raw + '.bat'
43 bat = raw + '.bat'
44 py = raw + '.py'
44 py = raw + '.py'
45 # Create .py versions of the scripts
45 # Create .py versions of the scripts
46 shutil.copy(raw, py)
46 shutil.copy(raw, py)
47 # Create .bat files for each of the scripts
47 # Create .bat files for each of the scripts
48 bat_file = file(bat,'w')
48 bat_file = file(bat,'w')
49 bat_file.write("@%s %s %%*" % (python, py))
49 bat_file.write("@%s %s %%*" % (python, py))
50 bat_file.close()
50 bat_file.close()
51
51
52 # Now move onto setting the Start Menu up
52 # Now move onto setting the Start Menu up
53 ipybase = pjoin(scripts, 'ipython')
53 ipybase = pjoin(scripts, 'ipython')
54 if 'setuptools' in sys.modules:
55 # let setuptools take care of the scripts:
56 ipybase = ipybase + '-script.py'
54 workdir = "%HOMEDRIVE%%HOMEPATH%"
57 workdir = "%HOMEDRIVE%%HOMEPATH%"
55
58
56 link = pjoin(ip_start_menu, 'IPython.lnk')
59 link = pjoin(ip_start_menu, 'IPython.lnk')
57 cmd = '"%s"' % ipybase
60 cmd = '"%s"' % ipybase
58 mkshortcut(python, 'IPython', link, cmd, workdir)
61 mkshortcut(python, 'IPython', link, cmd, workdir)
59
62
60 link = pjoin(ip_start_menu, 'pysh.lnk')
63 link = pjoin(ip_start_menu, 'pysh.lnk')
61 cmd = '"%s" -p sh' % ipybase
64 cmd = '"%s" -p sh' % ipybase
62 mkshortcut(python, 'IPython (command prompt mode)', link, cmd, workdir)
65 mkshortcut(python, 'IPython (command prompt mode)', link, cmd, workdir)
63
66
64 link = pjoin(ip_start_menu, 'scipy.lnk')
67 link = pjoin(ip_start_menu, 'scipy.lnk')
65 cmd = '"%s" -p scipy' % ipybase
68 cmd = '"%s" -p scipy' % ipybase
66 mkshortcut(python, 'IPython (scipy profile)', link, cmd, workdir)
69 mkshortcut(python, 'IPython (scipy profile)', link, cmd, workdir)
67
70
68 link = pjoin(ip_start_menu, 'ipcontroller.lnk')
71 link = pjoin(ip_start_menu, 'ipcontroller.lnk')
69 cmd = '"%s" -xy' % pjoin(scripts, 'ipcontroller')
72 cmd = '"%s" -xy' % pjoin(scripts, 'ipcontroller')
70 mkshortcut(python, 'IPython controller', link, cmd, workdir)
73 mkshortcut(python, 'IPython controller', link, cmd, workdir)
71
74
72 link = pjoin(ip_start_menu, 'ipengine.lnk')
75 link = pjoin(ip_start_menu, 'ipengine.lnk')
73 cmd = '"%s"' % pjoin(scripts, 'ipengine')
76 cmd = '"%s"' % pjoin(scripts, 'ipengine')
74 mkshortcut(python, 'IPython engine', link, cmd, workdir)
77 mkshortcut(python, 'IPython engine', link, cmd, workdir)
75
78
76 # Create documentation shortcuts ...
79 # Create documentation shortcuts ...
77 t = prefix + r'\share\doc\ipython\manual\ipython.pdf'
80 t = prefix + r'\share\doc\ipython\manual\ipython.pdf'
78 f = ip_start_menu + r'\Manual in PDF.lnk'
81 f = ip_start_menu + r'\Manual in PDF.lnk'
79 mkshortcut(t,r'IPython Manual - PDF-Format',f)
82 mkshortcut(t,r'IPython Manual - PDF-Format',f)
80
83
81 t = prefix + r'\share\doc\ipython\manual\html\index.html'
84 t = prefix + r'\share\doc\ipython\manual\html\index.html'
82 f = ip_start_menu + r'\Manual in HTML.lnk'
85 f = ip_start_menu + r'\Manual in HTML.lnk'
83 mkshortcut(t,'IPython Manual - HTML-Format',f)
86 mkshortcut(t,'IPython Manual - HTML-Format',f)
84
87
85
88
86 def remove():
89 def remove():
87 """Routine to be run by the win32 installer with the -remove switch."""
90 """Routine to be run by the win32 installer with the -remove switch."""
88 pass
91 pass
89
92
90 # main()
93 # main()
91 if len(sys.argv) > 1:
94 if len(sys.argv) > 1:
92 if sys.argv[1] == '-install':
95 if sys.argv[1] == '-install':
93 install()
96 install()
94 elif sys.argv[1] == '-remove':
97 elif sys.argv[1] == '-remove':
95 remove()
98 remove()
96 else:
99 else:
97 print "Script was called with option %s" % sys.argv[1]
100 print "Script was called with option %s" % sys.argv[1]
@@ -1,257 +1,255 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
2 # -*- coding: utf-8 -*-
3 """Setup script for IPython.
3 """Setup script for IPython.
4
4
5 Under Posix environments it works like a typical setup.py script.
5 Under Posix environments it works like a typical setup.py script.
6 Under Windows, the command sdist is not supported, since IPython
6 Under Windows, the command sdist is not supported, since IPython
7 requires utilities which are not available under Windows."""
7 requires utilities which are not available under Windows."""
8
8
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10 # Copyright (c) 2008-2010, IPython Development Team.
10 # Copyright (c) 2008-2010, IPython Development Team.
11 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
11 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
12 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
12 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
13 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
13 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
14 #
14 #
15 # Distributed under the terms of the Modified BSD License.
15 # Distributed under the terms of the Modified BSD License.
16 #
16 #
17 # The full license is in the file COPYING.txt, distributed with this software.
17 # The full license is in the file COPYING.txt, distributed with this software.
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 # Minimal Python version sanity check
21 # Minimal Python version sanity check
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23
23
24 import sys
24 import sys
25
25
26 # This check is also made in IPython/__init__, don't forget to update both when
26 # This check is also made in IPython/__init__, don't forget to update both when
27 # changing Python version requirements.
27 # changing Python version requirements.
28 if sys.version[0:3] < '2.6':
28 if sys.version[0:3] < '2.6':
29 error = """\
29 error = """\
30 ERROR: 'IPython requires Python Version 2.6 or above.'
30 ERROR: 'IPython requires Python Version 2.6 or above.'
31 Exiting."""
31 Exiting."""
32 print >> sys.stderr, error
32 print >> sys.stderr, error
33 sys.exit(1)
33 sys.exit(1)
34
34
35 # At least we're on the python version we need, move on.
35 # At least we're on the python version we need, move on.
36
36
37 #-------------------------------------------------------------------------------
37 #-------------------------------------------------------------------------------
38 # Imports
38 # Imports
39 #-------------------------------------------------------------------------------
39 #-------------------------------------------------------------------------------
40
40
41 # Stdlib imports
41 # Stdlib imports
42 import os
42 import os
43 import shutil
43 import shutil
44
44
45 from glob import glob
45 from glob import glob
46
46
47 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
47 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
48 # update it when the contents of directories change.
48 # update it when the contents of directories change.
49 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
49 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
50
50
51 from distutils.core import setup
51 from distutils.core import setup
52
52
53 # Our own imports
53 # Our own imports
54 from IPython.utils.path import target_update
54 from IPython.utils.path import target_update
55
55
56 from setupbase import (
56 from setupbase import (
57 setup_args,
57 setup_args,
58 find_packages,
58 find_packages,
59 find_package_data,
59 find_package_data,
60 find_scripts,
60 find_scripts,
61 find_data_files,
61 find_data_files,
62 check_for_dependencies,
62 check_for_dependencies,
63 record_commit_info,
63 record_commit_info,
64 )
64 )
65
65
66 isfile = os.path.isfile
66 isfile = os.path.isfile
67 pjoin = os.path.join
67 pjoin = os.path.join
68
68
69 #-----------------------------------------------------------------------------
69 #-----------------------------------------------------------------------------
70 # Function definitions
70 # Function definitions
71 #-----------------------------------------------------------------------------
71 #-----------------------------------------------------------------------------
72
72
73 def cleanup():
73 def cleanup():
74 """Clean up the junk left around by the build process"""
74 """Clean up the junk left around by the build process"""
75 if "develop" not in sys.argv:
75 if "develop" not in sys.argv:
76 try:
76 try:
77 shutil.rmtree('ipython.egg-info')
77 shutil.rmtree('ipython.egg-info')
78 except:
78 except:
79 try:
79 try:
80 os.unlink('ipython.egg-info')
80 os.unlink('ipython.egg-info')
81 except:
81 except:
82 pass
82 pass
83
83
84 #-------------------------------------------------------------------------------
84 #-------------------------------------------------------------------------------
85 # Handle OS specific things
85 # Handle OS specific things
86 #-------------------------------------------------------------------------------
86 #-------------------------------------------------------------------------------
87
87
88 if os.name == 'posix':
88 if os.name == 'posix':
89 os_name = 'posix'
89 os_name = 'posix'
90 elif os.name in ['nt','dos']:
90 elif os.name in ['nt','dos']:
91 os_name = 'windows'
91 os_name = 'windows'
92 else:
92 else:
93 print 'Unsupported operating system:',os.name
93 print 'Unsupported operating system:',os.name
94 sys.exit(1)
94 sys.exit(1)
95
95
96 # Under Windows, 'sdist' has not been supported. Now that the docs build with
96 # Under Windows, 'sdist' has not been supported. Now that the docs build with
97 # Sphinx it might work, but let's not turn it on until someone confirms that it
97 # Sphinx it might work, but let's not turn it on until someone confirms that it
98 # actually works.
98 # actually works.
99 if os_name == 'windows' and 'sdist' in sys.argv:
99 if os_name == 'windows' and 'sdist' in sys.argv:
100 print 'The sdist command is not available under Windows. Exiting.'
100 print 'The sdist command is not available under Windows. Exiting.'
101 sys.exit(1)
101 sys.exit(1)
102
102
103 #-------------------------------------------------------------------------------
103 #-------------------------------------------------------------------------------
104 # Things related to the IPython documentation
104 # Things related to the IPython documentation
105 #-------------------------------------------------------------------------------
105 #-------------------------------------------------------------------------------
106
106
107 # update the manuals when building a source dist
107 # update the manuals when building a source dist
108 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
108 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
109 import textwrap
109 import textwrap
110
110
111 # List of things to be updated. Each entry is a triplet of args for
111 # List of things to be updated. Each entry is a triplet of args for
112 # target_update()
112 # target_update()
113 to_update = [
113 to_update = [
114 # FIXME - Disabled for now: we need to redo an automatic way
114 # FIXME - Disabled for now: we need to redo an automatic way
115 # of generating the magic info inside the rst.
115 # of generating the magic info inside the rst.
116 #('docs/magic.tex',
116 #('docs/magic.tex',
117 #['IPython/Magic.py'],
117 #['IPython/Magic.py'],
118 #"cd doc && ./update_magic.sh" ),
118 #"cd doc && ./update_magic.sh" ),
119
119
120 ('docs/man/ipcluster.1.gz',
120 ('docs/man/ipcluster.1.gz',
121 ['docs/man/ipcluster.1'],
121 ['docs/man/ipcluster.1'],
122 'cd docs/man && gzip -9c ipcluster.1 > ipcluster.1.gz'),
122 'cd docs/man && gzip -9c ipcluster.1 > ipcluster.1.gz'),
123
123
124 ('docs/man/ipcontroller.1.gz',
124 ('docs/man/ipcontroller.1.gz',
125 ['docs/man/ipcontroller.1'],
125 ['docs/man/ipcontroller.1'],
126 'cd docs/man && gzip -9c ipcontroller.1 > ipcontroller.1.gz'),
126 'cd docs/man && gzip -9c ipcontroller.1 > ipcontroller.1.gz'),
127
127
128 ('docs/man/ipengine.1.gz',
128 ('docs/man/ipengine.1.gz',
129 ['docs/man/ipengine.1'],
129 ['docs/man/ipengine.1'],
130 'cd docs/man && gzip -9c ipengine.1 > ipengine.1.gz'),
130 'cd docs/man && gzip -9c ipengine.1 > ipengine.1.gz'),
131
131
132 ('docs/man/ipython.1.gz',
132 ('docs/man/ipython.1.gz',
133 ['docs/man/ipython.1'],
133 ['docs/man/ipython.1'],
134 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
134 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
135
135
136 ('docs/man/ipython-wx.1.gz',
136 ('docs/man/ipython-wx.1.gz',
137 ['docs/man/ipython-wx.1'],
137 ['docs/man/ipython-wx.1'],
138 'cd docs/man && gzip -9c ipython-wx.1 > ipython-wx.1.gz'),
138 'cd docs/man && gzip -9c ipython-wx.1 > ipython-wx.1.gz'),
139
139
140 ('docs/man/ipythonx.1.gz',
140 ('docs/man/ipythonx.1.gz',
141 ['docs/man/ipythonx.1'],
141 ['docs/man/ipythonx.1'],
142 'cd docs/man && gzip -9c ipythonx.1 > ipythonx.1.gz'),
142 'cd docs/man && gzip -9c ipythonx.1 > ipythonx.1.gz'),
143
143
144 ('docs/man/irunner.1.gz',
144 ('docs/man/irunner.1.gz',
145 ['docs/man/irunner.1'],
145 ['docs/man/irunner.1'],
146 'cd docs/man && gzip -9c irunner.1 > irunner.1.gz'),
146 'cd docs/man && gzip -9c irunner.1 > irunner.1.gz'),
147
147
148 ('docs/man/pycolor.1.gz',
148 ('docs/man/pycolor.1.gz',
149 ['docs/man/pycolor.1'],
149 ['docs/man/pycolor.1'],
150 'cd docs/man && gzip -9c pycolor.1 > pycolor.1.gz'),
150 'cd docs/man && gzip -9c pycolor.1 > pycolor.1.gz'),
151 ]
151 ]
152
152
153 # Only build the docs if sphinx is present
153 # Only build the docs if sphinx is present
154 try:
154 try:
155 import sphinx
155 import sphinx
156 except ImportError:
156 except ImportError:
157 pass
157 pass
158 else:
158 else:
159 # The Makefile calls the do_sphinx scripts to build html and pdf, so
159 # The Makefile calls the do_sphinx scripts to build html and pdf, so
160 # just one target is enough to cover all manual generation
160 # just one target is enough to cover all manual generation
161
161
162 # First, compute all the dependencies that can force us to rebuild the
162 # First, compute all the dependencies that can force us to rebuild the
163 # docs. Start with the main release file that contains metadata
163 # docs. Start with the main release file that contains metadata
164 docdeps = ['IPython/core/release.py']
164 docdeps = ['IPython/core/release.py']
165 # Inculde all the reST sources
165 # Inculde all the reST sources
166 pjoin = os.path.join
166 pjoin = os.path.join
167 for dirpath,dirnames,filenames in os.walk('docs/source'):
167 for dirpath,dirnames,filenames in os.walk('docs/source'):
168 if dirpath in ['_static','_templates']:
168 if dirpath in ['_static','_templates']:
169 continue
169 continue
170 docdeps += [ pjoin(dirpath,f) for f in filenames
170 docdeps += [ pjoin(dirpath,f) for f in filenames
171 if f.endswith('.txt') ]
171 if f.endswith('.txt') ]
172 # and the examples
172 # and the examples
173 for dirpath,dirnames,filenames in os.walk('docs/example'):
173 for dirpath,dirnames,filenames in os.walk('docs/example'):
174 docdeps += [ pjoin(dirpath,f) for f in filenames
174 docdeps += [ pjoin(dirpath,f) for f in filenames
175 if not f.endswith('~') ]
175 if not f.endswith('~') ]
176 # then, make them all dependencies for the main PDF (the html will get
176 # then, make them all dependencies for the main PDF (the html will get
177 # auto-generated as well).
177 # auto-generated as well).
178 to_update.append(
178 to_update.append(
179 ('docs/dist/ipython.pdf',
179 ('docs/dist/ipython.pdf',
180 docdeps,
180 docdeps,
181 "cd docs && make dist")
181 "cd docs && make dist")
182 )
182 )
183
183
184 [ target_update(*t) for t in to_update ]
184 [ target_update(*t) for t in to_update ]
185
185
186 #---------------------------------------------------------------------------
186 #---------------------------------------------------------------------------
187 # Find all the packages, package data, scripts and data_files
187 # Find all the packages, package data, scripts and data_files
188 #---------------------------------------------------------------------------
188 #---------------------------------------------------------------------------
189
189
190 packages = find_packages()
190 packages = find_packages()
191 package_data = find_package_data()
191 package_data = find_package_data()
192 scripts = find_scripts()
192 scripts = find_scripts()
193 data_files = find_data_files()
193 data_files = find_data_files()
194
194
195 #---------------------------------------------------------------------------
195 #---------------------------------------------------------------------------
196 # Handle dependencies and setuptools specific things
196 # Handle dependencies and setuptools specific things
197 #---------------------------------------------------------------------------
197 #---------------------------------------------------------------------------
198
198
199 # For some commands, use setuptools. Note that we do NOT list install here!
199 # For some commands, use setuptools. Note that we do NOT list install here!
200 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
200 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
201 if len(set(('develop', 'sdist', 'release', 'bdist_egg', 'bdist_rpm',
201 if len(set(('develop', 'sdist', 'release', 'bdist_egg', 'bdist_rpm',
202 'bdist', 'bdist_dumb', 'bdist_wininst', 'install_egg_info',
202 'bdist', 'bdist_dumb', 'bdist_wininst', 'install_egg_info',
203 'build_sphinx', 'egg_info', 'easy_install', 'upload',
203 'build_sphinx', 'egg_info', 'easy_install', 'upload',
204 )).intersection(sys.argv)) > 0:
204 )).intersection(sys.argv)) > 0:
205 import setuptools
205 import setuptools
206
206
207 # This dict is used for passing extra arguments that are setuptools
207 # This dict is used for passing extra arguments that are setuptools
208 # specific to setup
208 # specific to setup
209 setuptools_extra_args = {}
209 setuptools_extra_args = {}
210
210
211 if 'setuptools' in sys.modules:
211 if 'setuptools' in sys.modules:
212 setuptools_extra_args['zip_safe'] = False
212 setuptools_extra_args['zip_safe'] = False
213 setuptools_extra_args['entry_points'] = {
213 setuptools_extra_args['entry_points'] = {
214 'console_scripts': [
214 'console_scripts': [
215 'ipython = IPython.frontend.terminal.ipapp:launch_new_instance',
215 'ipython = IPython.frontend.terminal.ipapp:launch_new_instance',
216 'ipython-qtconsole = IPython.frontend.qt.console.ipythonqt:main',
216 'ipython-qtconsole = IPython.frontend.qt.console.ipythonqt:main',
217 'pycolor = IPython.utils.PyColorize:main',
217 'pycolor = IPython.utils.PyColorize:main',
218 'ipcontroller = IPython.kernel.ipcontrollerapp:launch_new_instance',
218 'ipcontroller = IPython.kernel.ipcontrollerapp:launch_new_instance',
219 'ipengine = IPython.kernel.ipengineapp:launch_new_instance',
219 'ipengine = IPython.kernel.ipengineapp:launch_new_instance',
220 'ipcluster = IPython.kernel.ipclusterapp:launch_new_instance',
220 'ipcluster = IPython.kernel.ipclusterapp:launch_new_instance',
221 'iptest = IPython.testing.iptest:main',
221 'iptest = IPython.testing.iptest:main',
222 'irunner = IPython.lib.irunner:main'
222 'irunner = IPython.lib.irunner:main'
223 ]
223 ]
224 }
224 }
225 setup_args['extras_require'] = dict(
225 setup_args['extras_require'] = dict(
226 kernel = [
226 kernel = [
227 'zope.interface>=3.4.1',
227 'zope.interface>=3.4.1',
228 'Twisted>=8.0.1',
228 'Twisted>=8.0.1',
229 'foolscap>=0.2.6'
229 'foolscap>=0.2.6'
230 ],
230 ],
231 doc='Sphinx>=0.3',
231 doc='Sphinx>=0.3',
232 test='nose>=0.10.1',
232 test='nose>=0.10.1',
233 security='pyOpenSSL>=0.6'
233 security='pyOpenSSL>=0.6'
234 )
234 )
235 # Allow setuptools to handle the scripts
236 scripts = []
237 else:
235 else:
238 # If we are running without setuptools, call this function which will
236 # If we are running without setuptools, call this function which will
239 # check for dependencies an inform the user what is needed. This is
237 # check for dependencies an inform the user what is needed. This is
240 # just to make life easy for users.
238 # just to make life easy for users.
241 check_for_dependencies()
239 check_for_dependencies()
242
240
243 #---------------------------------------------------------------------------
241 #---------------------------------------------------------------------------
244 # Do the actual setup now
242 # Do the actual setup now
245 #---------------------------------------------------------------------------
243 #---------------------------------------------------------------------------
246
244
247 setup_args['cmdclass'] = {'build_py': record_commit_info('IPython')}
245 setup_args['cmdclass'] = {'build_py': record_commit_info('IPython')}
248 setup_args['packages'] = packages
246 setup_args['packages'] = packages
249 setup_args['package_data'] = package_data
247 setup_args['package_data'] = package_data
250 setup_args['scripts'] = scripts
248 setup_args['scripts'] = scripts
251 setup_args['data_files'] = data_files
249 setup_args['data_files'] = data_files
252 setup_args.update(setuptools_extra_args)
250 setup_args.update(setuptools_extra_args)
253
251
254
252
255 if __name__ == '__main__':
253 if __name__ == '__main__':
256 setup(**setup_args)
254 setup(**setup_args)
257 cleanup()
255 cleanup()
@@ -1,375 +1,375 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 This module defines the things that are used in setup.py for building IPython
3 This module defines the things that are used in setup.py for building IPython
4
4
5 This includes:
5 This includes:
6
6
7 * The basic arguments to setup
7 * The basic arguments to setup
8 * Functions for finding things like packages, package data, etc.
8 * Functions for finding things like packages, package data, etc.
9 * A function for checking dependencies.
9 * A function for checking dependencies.
10 """
10 """
11 from __future__ import print_function
11 from __future__ import print_function
12
12
13 #-------------------------------------------------------------------------------
13 #-------------------------------------------------------------------------------
14 # Copyright (C) 2008 The IPython Development Team
14 # Copyright (C) 2008 The IPython Development Team
15 #
15 #
16 # Distributed under the terms of the BSD License. The full license is in
16 # Distributed under the terms of the BSD License. The full license is in
17 # the file COPYING, distributed as part of this software.
17 # the file COPYING, distributed as part of this software.
18 #-------------------------------------------------------------------------------
18 #-------------------------------------------------------------------------------
19
19
20 #-------------------------------------------------------------------------------
20 #-------------------------------------------------------------------------------
21 # Imports
21 # Imports
22 #-------------------------------------------------------------------------------
22 #-------------------------------------------------------------------------------
23 import os
23 import os
24 import sys
24 import sys
25
25
26 from ConfigParser import ConfigParser
26 from ConfigParser import ConfigParser
27 from distutils.command.build_py import build_py
27 from distutils.command.build_py import build_py
28 from glob import glob
28 from glob import glob
29
29
30 from setupext import install_data_ext
30 from setupext import install_data_ext
31
31
32 #-------------------------------------------------------------------------------
32 #-------------------------------------------------------------------------------
33 # Useful globals and utility functions
33 # Useful globals and utility functions
34 #-------------------------------------------------------------------------------
34 #-------------------------------------------------------------------------------
35
35
36 # A few handy globals
36 # A few handy globals
37 isfile = os.path.isfile
37 isfile = os.path.isfile
38 pjoin = os.path.join
38 pjoin = os.path.join
39
39
40 def oscmd(s):
40 def oscmd(s):
41 print(">", s)
41 print(">", s)
42 os.system(s)
42 os.system(s)
43
43
44 # A little utility we'll need below, since glob() does NOT allow you to do
44 # A little utility we'll need below, since glob() does NOT allow you to do
45 # exclusion on multiple endings!
45 # exclusion on multiple endings!
46 def file_doesnt_endwith(test,endings):
46 def file_doesnt_endwith(test,endings):
47 """Return true if test is a file and its name does NOT end with any
47 """Return true if test is a file and its name does NOT end with any
48 of the strings listed in endings."""
48 of the strings listed in endings."""
49 if not isfile(test):
49 if not isfile(test):
50 return False
50 return False
51 for e in endings:
51 for e in endings:
52 if test.endswith(e):
52 if test.endswith(e):
53 return False
53 return False
54 return True
54 return True
55
55
56 #---------------------------------------------------------------------------
56 #---------------------------------------------------------------------------
57 # Basic project information
57 # Basic project information
58 #---------------------------------------------------------------------------
58 #---------------------------------------------------------------------------
59
59
60 # release.py contains version, authors, license, url, keywords, etc.
60 # release.py contains version, authors, license, url, keywords, etc.
61 execfile(pjoin('IPython','core','release.py'))
61 execfile(pjoin('IPython','core','release.py'))
62
62
63 # Create a dict with the basic information
63 # Create a dict with the basic information
64 # This dict is eventually passed to setup after additional keys are added.
64 # This dict is eventually passed to setup after additional keys are added.
65 setup_args = dict(
65 setup_args = dict(
66 name = name,
66 name = name,
67 version = version,
67 version = version,
68 description = description,
68 description = description,
69 long_description = long_description,
69 long_description = long_description,
70 author = author,
70 author = author,
71 author_email = author_email,
71 author_email = author_email,
72 url = url,
72 url = url,
73 download_url = download_url,
73 download_url = download_url,
74 license = license,
74 license = license,
75 platforms = platforms,
75 platforms = platforms,
76 keywords = keywords,
76 keywords = keywords,
77 cmdclass = {'install_data': install_data_ext},
77 cmdclass = {'install_data': install_data_ext},
78 )
78 )
79
79
80
80
81 #---------------------------------------------------------------------------
81 #---------------------------------------------------------------------------
82 # Find packages
82 # Find packages
83 #---------------------------------------------------------------------------
83 #---------------------------------------------------------------------------
84
84
85 def add_package(packages,pname,config=False,tests=False,scripts=False,
85 def add_package(packages,pname,config=False,tests=False,scripts=False,
86 others=None):
86 others=None):
87 """
87 """
88 Add a package to the list of packages, including certain subpackages.
88 Add a package to the list of packages, including certain subpackages.
89 """
89 """
90 packages.append('.'.join(['IPython',pname]))
90 packages.append('.'.join(['IPython',pname]))
91 if config:
91 if config:
92 packages.append('.'.join(['IPython',pname,'config']))
92 packages.append('.'.join(['IPython',pname,'config']))
93 if tests:
93 if tests:
94 packages.append('.'.join(['IPython',pname,'tests']))
94 packages.append('.'.join(['IPython',pname,'tests']))
95 if scripts:
95 if scripts:
96 packages.append('.'.join(['IPython',pname,'scripts']))
96 packages.append('.'.join(['IPython',pname,'scripts']))
97 if others is not None:
97 if others is not None:
98 for o in others:
98 for o in others:
99 packages.append('.'.join(['IPython',pname,o]))
99 packages.append('.'.join(['IPython',pname,o]))
100
100
101 def find_packages():
101 def find_packages():
102 """
102 """
103 Find all of IPython's packages.
103 Find all of IPython's packages.
104 """
104 """
105 packages = ['IPython']
105 packages = ['IPython']
106 add_package(packages, 'config', tests=True, others=['default','profile'])
106 add_package(packages, 'config', tests=True, others=['default','profile'])
107 add_package(packages, 'core', tests=True)
107 add_package(packages, 'core', tests=True)
108 add_package(packages, 'deathrow', tests=True)
108 add_package(packages, 'deathrow', tests=True)
109 add_package(packages, 'extensions')
109 add_package(packages, 'extensions')
110 add_package(packages, 'external')
110 add_package(packages, 'external')
111 add_package(packages, 'frontend')
111 add_package(packages, 'frontend')
112 add_package(packages, 'frontend.qt')
112 add_package(packages, 'frontend.qt')
113 add_package(packages, 'frontend.qt.console', tests=True)
113 add_package(packages, 'frontend.qt.console', tests=True)
114 add_package(packages, 'frontend.terminal', tests=True)
114 add_package(packages, 'frontend.terminal', tests=True)
115 add_package(packages, 'kernel', config=False, tests=True, scripts=True)
115 add_package(packages, 'kernel', config=False, tests=True, scripts=True)
116 add_package(packages, 'kernel.core', config=False, tests=True)
116 add_package(packages, 'kernel.core', config=False, tests=True)
117 add_package(packages, 'lib', tests=True)
117 add_package(packages, 'lib', tests=True)
118 add_package(packages, 'quarantine', tests=True)
118 add_package(packages, 'quarantine', tests=True)
119 add_package(packages, 'scripts')
119 add_package(packages, 'scripts')
120 add_package(packages, 'testing', tests=True)
120 add_package(packages, 'testing', tests=True)
121 add_package(packages, 'testing.plugin', tests=False)
121 add_package(packages, 'testing.plugin', tests=False)
122 add_package(packages, 'utils', tests=True)
122 add_package(packages, 'utils', tests=True)
123 add_package(packages, 'zmq')
123 add_package(packages, 'zmq')
124 add_package(packages, 'zmq.pylab')
124 add_package(packages, 'zmq.pylab')
125 return packages
125 return packages
126
126
127 #---------------------------------------------------------------------------
127 #---------------------------------------------------------------------------
128 # Find package data
128 # Find package data
129 #---------------------------------------------------------------------------
129 #---------------------------------------------------------------------------
130
130
131 def find_package_data():
131 def find_package_data():
132 """
132 """
133 Find IPython's package_data.
133 Find IPython's package_data.
134 """
134 """
135 # This is not enough for these things to appear in an sdist.
135 # This is not enough for these things to appear in an sdist.
136 # We need to muck with the MANIFEST to get this to work
136 # We need to muck with the MANIFEST to get this to work
137 package_data = {
137 package_data = {
138 'IPython.config.userconfig' : ['*'],
138 'IPython.config.userconfig' : ['*'],
139 'IPython.testing' : ['*.txt']
139 'IPython.testing' : ['*.txt']
140 }
140 }
141 return package_data
141 return package_data
142
142
143
143
144 #---------------------------------------------------------------------------
144 #---------------------------------------------------------------------------
145 # Find data files
145 # Find data files
146 #---------------------------------------------------------------------------
146 #---------------------------------------------------------------------------
147
147
148 def make_dir_struct(tag,base,out_base):
148 def make_dir_struct(tag,base,out_base):
149 """Make the directory structure of all files below a starting dir.
149 """Make the directory structure of all files below a starting dir.
150
150
151 This is just a convenience routine to help build a nested directory
151 This is just a convenience routine to help build a nested directory
152 hierarchy because distutils is too stupid to do this by itself.
152 hierarchy because distutils is too stupid to do this by itself.
153
153
154 XXX - this needs a proper docstring!
154 XXX - this needs a proper docstring!
155 """
155 """
156
156
157 # we'll use these a lot below
157 # we'll use these a lot below
158 lbase = len(base)
158 lbase = len(base)
159 pathsep = os.path.sep
159 pathsep = os.path.sep
160 lpathsep = len(pathsep)
160 lpathsep = len(pathsep)
161
161
162 out = []
162 out = []
163 for (dirpath,dirnames,filenames) in os.walk(base):
163 for (dirpath,dirnames,filenames) in os.walk(base):
164 # we need to strip out the dirpath from the base to map it to the
164 # we need to strip out the dirpath from the base to map it to the
165 # output (installation) path. This requires possibly stripping the
165 # output (installation) path. This requires possibly stripping the
166 # path separator, because otherwise pjoin will not work correctly
166 # path separator, because otherwise pjoin will not work correctly
167 # (pjoin('foo/','/bar') returns '/bar').
167 # (pjoin('foo/','/bar') returns '/bar').
168
168
169 dp_eff = dirpath[lbase:]
169 dp_eff = dirpath[lbase:]
170 if dp_eff.startswith(pathsep):
170 if dp_eff.startswith(pathsep):
171 dp_eff = dp_eff[lpathsep:]
171 dp_eff = dp_eff[lpathsep:]
172 # The output path must be anchored at the out_base marker
172 # The output path must be anchored at the out_base marker
173 out_path = pjoin(out_base,dp_eff)
173 out_path = pjoin(out_base,dp_eff)
174 # Now we can generate the final filenames. Since os.walk only produces
174 # Now we can generate the final filenames. Since os.walk only produces
175 # filenames, we must join back with the dirpath to get full valid file
175 # filenames, we must join back with the dirpath to get full valid file
176 # paths:
176 # paths:
177 pfiles = [pjoin(dirpath,f) for f in filenames]
177 pfiles = [pjoin(dirpath,f) for f in filenames]
178 # Finally, generate the entry we need, which is a pari of (output
178 # Finally, generate the entry we need, which is a pari of (output
179 # path, files) for use as a data_files parameter in install_data.
179 # path, files) for use as a data_files parameter in install_data.
180 out.append((out_path, pfiles))
180 out.append((out_path, pfiles))
181
181
182 return out
182 return out
183
183
184
184
185 def find_data_files():
185 def find_data_files():
186 """
186 """
187 Find IPython's data_files.
187 Find IPython's data_files.
188
188
189 Most of these are docs.
189 Most of these are docs.
190 """
190 """
191
191
192 docdirbase = pjoin('share', 'doc', 'ipython')
192 docdirbase = pjoin('share', 'doc', 'ipython')
193 manpagebase = pjoin('share', 'man', 'man1')
193 manpagebase = pjoin('share', 'man', 'man1')
194
194
195 # Simple file lists can be made by hand
195 # Simple file lists can be made by hand
196 manpages = filter(isfile, glob(pjoin('docs','man','*.1.gz')))
196 manpages = filter(isfile, glob(pjoin('docs','man','*.1.gz')))
197 igridhelpfiles = filter(isfile,
197 igridhelpfiles = filter(isfile,
198 glob(pjoin('IPython','extensions','igrid_help.*')))
198 glob(pjoin('IPython','extensions','igrid_help.*')))
199
199
200 # For nested structures, use the utility above
200 # For nested structures, use the utility above
201 example_files = make_dir_struct(
201 example_files = make_dir_struct(
202 'data',
202 'data',
203 pjoin('docs','examples'),
203 pjoin('docs','examples'),
204 pjoin(docdirbase,'examples')
204 pjoin(docdirbase,'examples')
205 )
205 )
206 manual_files = make_dir_struct(
206 manual_files = make_dir_struct(
207 'data',
207 'data',
208 pjoin('docs','dist'),
208 pjoin('docs','dist'),
209 pjoin(docdirbase,'manual')
209 pjoin(docdirbase,'manual')
210 )
210 )
211
211
212 # And assemble the entire output list
212 # And assemble the entire output list
213 data_files = [ (manpagebase, manpages),
213 data_files = [ (manpagebase, manpages),
214 (pjoin(docdirbase, 'extensions'), igridhelpfiles),
214 (pjoin(docdirbase, 'extensions'), igridhelpfiles),
215 ] + manual_files + example_files
215 ] + manual_files + example_files
216
216
217 ## import pprint # dbg
217 ## import pprint # dbg
218 ## print('*'*80)
218 ## print('*'*80)
219 ## print('data files')
219 ## print('data files')
220 ## pprint.pprint(data_files)
220 ## pprint.pprint(data_files)
221 ## print('*'*80)
221 ## print('*'*80)
222
222
223 return data_files
223 return data_files
224
224
225
225
226 def make_man_update_target(manpage):
226 def make_man_update_target(manpage):
227 """Return a target_update-compliant tuple for the given manpage.
227 """Return a target_update-compliant tuple for the given manpage.
228
228
229 Parameters
229 Parameters
230 ----------
230 ----------
231 manpage : string
231 manpage : string
232 Name of the manpage, must include the section number (trailing number).
232 Name of the manpage, must include the section number (trailing number).
233
233
234 Example
234 Example
235 -------
235 -------
236
236
237 >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE
237 >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE
238 ('docs/man/ipython.1.gz',
238 ('docs/man/ipython.1.gz',
239 ['docs/man/ipython.1'],
239 ['docs/man/ipython.1'],
240 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz')
240 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz')
241 """
241 """
242 man_dir = pjoin('docs', 'man')
242 man_dir = pjoin('docs', 'man')
243 manpage_gz = manpage + '.gz'
243 manpage_gz = manpage + '.gz'
244 manpath = pjoin(man_dir, manpage)
244 manpath = pjoin(man_dir, manpage)
245 manpath_gz = pjoin(man_dir, manpage_gz)
245 manpath_gz = pjoin(man_dir, manpage_gz)
246 gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" %
246 gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" %
247 locals() )
247 locals() )
248 return (manpath_gz, [manpath], gz_cmd)
248 return (manpath_gz, [manpath], gz_cmd)
249
249
250 #---------------------------------------------------------------------------
250 #---------------------------------------------------------------------------
251 # Find scripts
251 # Find scripts
252 #---------------------------------------------------------------------------
252 #---------------------------------------------------------------------------
253
253
254 def find_scripts():
254 def find_scripts():
255 """
255 """
256 Find IPython's scripts.
256 Find IPython's scripts.
257 """
257 """
258 kernel_scripts = pjoin('IPython','kernel','scripts')
258 kernel_scripts = pjoin('IPython','kernel','scripts')
259 main_scripts = pjoin('IPython','scripts')
259 main_scripts = pjoin('IPython','scripts')
260 scripts = [pjoin(kernel_scripts, 'ipengine'),
260 scripts = [pjoin(kernel_scripts, 'ipengine'),
261 pjoin(kernel_scripts, 'ipcontroller'),
261 pjoin(kernel_scripts, 'ipcontroller'),
262 pjoin(kernel_scripts, 'ipcluster'),
262 pjoin(kernel_scripts, 'ipcluster'),
263 pjoin(main_scripts, 'ipython'),
263 pjoin(main_scripts, 'ipython'),
264 pjoin(main_scripts, 'ipython-qtconsole'),
264 pjoin(main_scripts, 'ipython-qtconsole'),
265 pjoin(main_scripts, 'pycolor'),
265 pjoin(main_scripts, 'pycolor'),
266 pjoin(main_scripts, 'irunner'),
266 pjoin(main_scripts, 'irunner'),
267 pjoin(main_scripts, 'iptest')
267 pjoin(main_scripts, 'iptest')
268 ]
268 ]
269
269
270 # Script to be run by the windows binary installer after the default setup
270 # Script to be run by the windows binary installer after the default setup
271 # routine, to add shortcuts and similar windows-only things. Windows
271 # routine, to add shortcuts and similar windows-only things. Windows
272 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
272 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
273 # doesn't find them.
273 # doesn't find them.
274 if 'bdist_wininst' in sys.argv:
274 if 'bdist_wininst' in sys.argv:
275 if len(sys.argv) > 2 and \
275 if len(sys.argv) > 2 and \
276 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
276 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
277 print("ERROR: bdist_wininst must be run alone. Exiting.",
277 print("ERROR: bdist_wininst must be run alone. Exiting.",
278 file=sys.stderr)
278 file=sys.stderr)
279 sys.exit(1)
279 sys.exit(1)
280 scripts.append(pjoin('scripts','ipython_win_post_install.py'))
280 scripts.append(pjoin('scripts','ipython_win_post_install.py'))
281
281
282 return scripts
282 return scripts
283
283
284 #---------------------------------------------------------------------------
284 #---------------------------------------------------------------------------
285 # Verify all dependencies
285 # Verify all dependencies
286 #---------------------------------------------------------------------------
286 #---------------------------------------------------------------------------
287
287
288 def check_for_dependencies():
288 def check_for_dependencies():
289 """Check for IPython's dependencies.
289 """Check for IPython's dependencies.
290
290
291 This function should NOT be called if running under setuptools!
291 This function should NOT be called if running under setuptools!
292 """
292 """
293 from setupext.setupext import (
293 from setupext.setupext import (
294 print_line, print_raw, print_status,
294 print_line, print_raw, print_status,
295 check_for_zopeinterface, check_for_twisted,
295 check_for_zopeinterface, check_for_twisted,
296 check_for_foolscap, check_for_pyopenssl,
296 check_for_foolscap, check_for_pyopenssl,
297 check_for_sphinx, check_for_pygments,
297 check_for_sphinx, check_for_pygments,
298 check_for_nose, check_for_pexpect
298 check_for_nose, check_for_pexpect
299 )
299 )
300 print_line()
300 print_line()
301 print_raw("BUILDING IPYTHON")
301 print_raw("BUILDING IPYTHON")
302 print_status('python', sys.version)
302 print_status('python', sys.version)
303 print_status('platform', sys.platform)
303 print_status('platform', sys.platform)
304 if sys.platform == 'win32':
304 if sys.platform == 'win32':
305 print_status('Windows version', sys.getwindowsversion())
305 print_status('Windows version', sys.getwindowsversion())
306
306
307 print_raw("")
307 print_raw("")
308 print_raw("OPTIONAL DEPENDENCIES")
308 print_raw("OPTIONAL DEPENDENCIES")
309
309
310 check_for_zopeinterface()
310 check_for_zopeinterface()
311 check_for_twisted()
311 check_for_twisted()
312 check_for_foolscap()
312 check_for_foolscap()
313 check_for_pyopenssl()
313 check_for_pyopenssl()
314 check_for_sphinx()
314 check_for_sphinx()
315 check_for_pygments()
315 check_for_pygments()
316 check_for_nose()
316 check_for_nose()
317 check_for_pexpect()
317 check_for_pexpect()
318
318
319
319
320 def record_commit_info(pkg_dir, build_cmd=build_py):
320 def record_commit_info(pkg_dir, build_cmd=build_py):
321 """ Return extended build command class for recording commit
321 """ Return extended build command class for recording commit
322
322
323 The extended command tries to run git to find the current commit, getting
323 The extended command tries to run git to find the current commit, getting
324 the empty string if it fails. It then writes the commit hash into a file
324 the empty string if it fails. It then writes the commit hash into a file
325 in the `pkg_dir` path, named ``.git_commit_info.ini``.
325 in the `pkg_dir` path, named ``.git_commit_info.ini``.
326
326
327 In due course this information can be used by the package after it is
327 In due course this information can be used by the package after it is
328 installed, to tell you what commit it was installed from if known.
328 installed, to tell you what commit it was installed from if known.
329
329
330 To make use of this system, you need a package with a .git_commit_info.ini
330 To make use of this system, you need a package with a .git_commit_info.ini
331 file - e.g. ``myproject/.git_commit_info.ini`` - that might well look like
331 file - e.g. ``myproject/.git_commit_info.ini`` - that might well look like
332 this::
332 this::
333
333
334 # This is an ini file that may contain information about the code state
334 # This is an ini file that may contain information about the code state
335 [commit hash]
335 [commit hash]
336 # The line below may contain a valid hash if it has been substituted
336 # The line below may contain a valid hash if it has been substituted
337 # during 'git archive'
337 # during 'git archive'
338 archive_subst_hash=$Format:%h$
338 archive_subst_hash=$Format:%h$
339 # This line may be modified by the install process
339 # This line may be modified by the install process
340 install_hash=
340 install_hash=
341
341
342 The .git_commit_info file above is also designed to be used with git
342 The .git_commit_info file above is also designed to be used with git
343 substitution - so you probably also want a ``.gitattributes`` file in the
343 substitution - so you probably also want a ``.gitattributes`` file in the
344 root directory of your working tree that contains something like this::
344 root directory of your working tree that contains something like this::
345
345
346 myproject/.git_commit_info.ini export-subst
346 myproject/.git_commit_info.ini export-subst
347
347
348 That will cause the ``.git_commit_info.ini`` file to get filled in by ``git
348 That will cause the ``.git_commit_info.ini`` file to get filled in by ``git
349 archive`` - useful in case someone makes such an archive - for example with
349 archive`` - useful in case someone makes such an archive - for example with
350 via the github 'download source' button.
350 via the github 'download source' button.
351
351
352 Although all the above will work as is, you might consider having something
352 Although all the above will work as is, you might consider having something
353 like a ``get_info()`` function in your package to display the commit
353 like a ``get_info()`` function in your package to display the commit
354 information at the terminal. See the ``pkg_info.py`` module in the nipy
354 information at the terminal. See the ``pkg_info.py`` module in the nipy
355 package for an example.
355 package for an example.
356 """
356 """
357 class MyBuildPy(build_cmd):
357 class MyBuildPy(build_cmd):
358 ''' Subclass to write commit data into installation tree '''
358 ''' Subclass to write commit data into installation tree '''
359 def run(self):
359 def run(self):
360 build_py.run(self)
360 build_py.run(self)
361 import subprocess
361 import subprocess
362 proc = subprocess.Popen('git rev-parse --short HEAD',
362 proc = subprocess.Popen('git rev-parse --short HEAD',
363 stdout=subprocess.PIPE,
363 stdout=subprocess.PIPE,
364 stderr=subprocess.PIPE,
364 stderr=subprocess.PIPE,
365 shell=True)
365 shell=True)
366 repo_commit, _ = proc.communicate()
366 repo_commit, _ = proc.communicate()
367 # We write the installation commit even if it's empty
367 # We write the installation commit even if it's empty
368 cfg_parser = ConfigParser()
368 cfg_parser = ConfigParser()
369 cfg_parser.read(pjoin(pkg_dir, '.git_commit_info.ini'))
369 cfg_parser.read(pjoin(pkg_dir, '.git_commit_info.ini'))
370 cfg_parser.set('commit hash', 'install_hash', repo_commit)
370 cfg_parser.set('commit hash', 'install_hash', repo_commit)
371 out_pth = pjoin(self.build_lib, pkg_dir, '.git_commit_info.ini')
371 out_pth = pjoin(self.build_lib, pkg_dir, '.git_commit_info.ini')
372 out_file = open(out_pth, 'wt')
372 out_file = open(out_pth, 'wt')
373 cfg_parser.write(out_file)
373 cfg_parser.write(out_file)
374 out_file.close()
374 out_file.close()
375 return MyBuildPy
375 return MyBuildPy
General Comments 0
You need to be logged in to leave comments. Login now