##// END OF EJS Templates
don't install deathrow
MinRK -
Show More
@@ -1,386 +1,385 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=['profile'])
106 add_package(packages, 'config', tests=True, others=['profile'])
107 add_package(packages, 'core', tests=True)
107 add_package(packages, 'core', tests=True)
108 add_package(packages, 'deathrow', tests=True)
109 add_package(packages, 'extensions')
108 add_package(packages, 'extensions')
110 add_package(packages, 'external')
109 add_package(packages, 'external')
111 add_package(packages, 'external.argparse')
110 add_package(packages, 'external.argparse')
112 add_package(packages, 'external.decorator')
111 add_package(packages, 'external.decorator')
113 add_package(packages, 'external.decorators')
112 add_package(packages, 'external.decorators')
114 add_package(packages, 'external.guid')
113 add_package(packages, 'external.guid')
115 add_package(packages, 'external.Itpl')
114 add_package(packages, 'external.Itpl')
116 add_package(packages, 'external.mglob')
115 add_package(packages, 'external.mglob')
117 add_package(packages, 'external.path')
116 add_package(packages, 'external.path')
118 add_package(packages, 'external.pexpect')
117 add_package(packages, 'external.pexpect')
119 add_package(packages, 'external.pyparsing')
118 add_package(packages, 'external.pyparsing')
120 add_package(packages, 'external.simplegeneric')
119 add_package(packages, 'external.simplegeneric')
121 add_package(packages, 'external.ssh')
120 add_package(packages, 'external.ssh')
122 add_package(packages, 'kernel')
121 add_package(packages, 'kernel')
123 add_package(packages, 'frontend')
122 add_package(packages, 'frontend')
124 add_package(packages, 'frontend.qt')
123 add_package(packages, 'frontend.qt')
125 add_package(packages, 'frontend.qt.console', tests=True)
124 add_package(packages, 'frontend.qt.console', tests=True)
126 add_package(packages, 'frontend.terminal', tests=True)
125 add_package(packages, 'frontend.terminal', tests=True)
127 add_package(packages, 'lib', tests=True)
126 add_package(packages, 'lib', tests=True)
128 add_package(packages, 'parallel', tests=True, scripts=True,
127 add_package(packages, 'parallel', tests=True, scripts=True,
129 others=['apps','engine','client','controller'])
128 others=['apps','engine','client','controller'])
130 add_package(packages, 'quarantine', tests=True)
129 add_package(packages, 'quarantine', tests=True)
131 add_package(packages, 'scripts')
130 add_package(packages, 'scripts')
132 add_package(packages, 'testing', tests=True)
131 add_package(packages, 'testing', tests=True)
133 add_package(packages, 'testing.plugin', tests=False)
132 add_package(packages, 'testing.plugin', tests=False)
134 add_package(packages, 'utils', tests=True)
133 add_package(packages, 'utils', tests=True)
135 add_package(packages, 'zmq')
134 add_package(packages, 'zmq')
136 add_package(packages, 'zmq.pylab')
135 add_package(packages, 'zmq.pylab')
137 add_package(packages, 'zmq.gui')
136 add_package(packages, 'zmq.gui')
138 return packages
137 return packages
139
138
140 #---------------------------------------------------------------------------
139 #---------------------------------------------------------------------------
141 # Find package data
140 # Find package data
142 #---------------------------------------------------------------------------
141 #---------------------------------------------------------------------------
143
142
144 def find_package_data():
143 def find_package_data():
145 """
144 """
146 Find IPython's package_data.
145 Find IPython's package_data.
147 """
146 """
148 # This is not enough for these things to appear in an sdist.
147 # This is not enough for these things to appear in an sdist.
149 # We need to muck with the MANIFEST to get this to work
148 # We need to muck with the MANIFEST to get this to work
150 package_data = {
149 package_data = {
151 'IPython.config.profile' : ['README', '*/*.py'],
150 'IPython.config.profile' : ['README', '*/*.py'],
152 'IPython.testing' : ['*.txt'],
151 'IPython.testing' : ['*.txt'],
153 }
152 }
154 return package_data
153 return package_data
155
154
156
155
157 #---------------------------------------------------------------------------
156 #---------------------------------------------------------------------------
158 # Find data files
157 # Find data files
159 #---------------------------------------------------------------------------
158 #---------------------------------------------------------------------------
160
159
161 def make_dir_struct(tag,base,out_base):
160 def make_dir_struct(tag,base,out_base):
162 """Make the directory structure of all files below a starting dir.
161 """Make the directory structure of all files below a starting dir.
163
162
164 This is just a convenience routine to help build a nested directory
163 This is just a convenience routine to help build a nested directory
165 hierarchy because distutils is too stupid to do this by itself.
164 hierarchy because distutils is too stupid to do this by itself.
166
165
167 XXX - this needs a proper docstring!
166 XXX - this needs a proper docstring!
168 """
167 """
169
168
170 # we'll use these a lot below
169 # we'll use these a lot below
171 lbase = len(base)
170 lbase = len(base)
172 pathsep = os.path.sep
171 pathsep = os.path.sep
173 lpathsep = len(pathsep)
172 lpathsep = len(pathsep)
174
173
175 out = []
174 out = []
176 for (dirpath,dirnames,filenames) in os.walk(base):
175 for (dirpath,dirnames,filenames) in os.walk(base):
177 # we need to strip out the dirpath from the base to map it to the
176 # we need to strip out the dirpath from the base to map it to the
178 # output (installation) path. This requires possibly stripping the
177 # output (installation) path. This requires possibly stripping the
179 # path separator, because otherwise pjoin will not work correctly
178 # path separator, because otherwise pjoin will not work correctly
180 # (pjoin('foo/','/bar') returns '/bar').
179 # (pjoin('foo/','/bar') returns '/bar').
181
180
182 dp_eff = dirpath[lbase:]
181 dp_eff = dirpath[lbase:]
183 if dp_eff.startswith(pathsep):
182 if dp_eff.startswith(pathsep):
184 dp_eff = dp_eff[lpathsep:]
183 dp_eff = dp_eff[lpathsep:]
185 # The output path must be anchored at the out_base marker
184 # The output path must be anchored at the out_base marker
186 out_path = pjoin(out_base,dp_eff)
185 out_path = pjoin(out_base,dp_eff)
187 # Now we can generate the final filenames. Since os.walk only produces
186 # Now we can generate the final filenames. Since os.walk only produces
188 # filenames, we must join back with the dirpath to get full valid file
187 # filenames, we must join back with the dirpath to get full valid file
189 # paths:
188 # paths:
190 pfiles = [pjoin(dirpath,f) for f in filenames]
189 pfiles = [pjoin(dirpath,f) for f in filenames]
191 # Finally, generate the entry we need, which is a pari of (output
190 # Finally, generate the entry we need, which is a pari of (output
192 # path, files) for use as a data_files parameter in install_data.
191 # path, files) for use as a data_files parameter in install_data.
193 out.append((out_path, pfiles))
192 out.append((out_path, pfiles))
194
193
195 return out
194 return out
196
195
197
196
198 def find_data_files():
197 def find_data_files():
199 """
198 """
200 Find IPython's data_files.
199 Find IPython's data_files.
201
200
202 Most of these are docs.
201 Most of these are docs.
203 """
202 """
204
203
205 docdirbase = pjoin('share', 'doc', 'ipython')
204 docdirbase = pjoin('share', 'doc', 'ipython')
206 manpagebase = pjoin('share', 'man', 'man1')
205 manpagebase = pjoin('share', 'man', 'man1')
207
206
208 # Simple file lists can be made by hand
207 # Simple file lists can be made by hand
209 manpages = filter(isfile, glob(pjoin('docs','man','*.1.gz')))
208 manpages = filter(isfile, glob(pjoin('docs','man','*.1.gz')))
210 igridhelpfiles = filter(isfile,
209 igridhelpfiles = filter(isfile,
211 glob(pjoin('IPython','extensions','igrid_help.*')))
210 glob(pjoin('IPython','extensions','igrid_help.*')))
212
211
213 # For nested structures, use the utility above
212 # For nested structures, use the utility above
214 example_files = make_dir_struct(
213 example_files = make_dir_struct(
215 'data',
214 'data',
216 pjoin('docs','examples'),
215 pjoin('docs','examples'),
217 pjoin(docdirbase,'examples')
216 pjoin(docdirbase,'examples')
218 )
217 )
219 manual_files = make_dir_struct(
218 manual_files = make_dir_struct(
220 'data',
219 'data',
221 pjoin('docs','dist'),
220 pjoin('docs','dist'),
222 pjoin(docdirbase,'manual')
221 pjoin(docdirbase,'manual')
223 )
222 )
224
223
225 # And assemble the entire output list
224 # And assemble the entire output list
226 data_files = [ (manpagebase, manpages),
225 data_files = [ (manpagebase, manpages),
227 (pjoin(docdirbase, 'extensions'), igridhelpfiles),
226 (pjoin(docdirbase, 'extensions'), igridhelpfiles),
228 ] + manual_files + example_files
227 ] + manual_files + example_files
229
228
230 return data_files
229 return data_files
231
230
232
231
233 def make_man_update_target(manpage):
232 def make_man_update_target(manpage):
234 """Return a target_update-compliant tuple for the given manpage.
233 """Return a target_update-compliant tuple for the given manpage.
235
234
236 Parameters
235 Parameters
237 ----------
236 ----------
238 manpage : string
237 manpage : string
239 Name of the manpage, must include the section number (trailing number).
238 Name of the manpage, must include the section number (trailing number).
240
239
241 Example
240 Example
242 -------
241 -------
243
242
244 >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE
243 >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE
245 ('docs/man/ipython.1.gz',
244 ('docs/man/ipython.1.gz',
246 ['docs/man/ipython.1'],
245 ['docs/man/ipython.1'],
247 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz')
246 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz')
248 """
247 """
249 man_dir = pjoin('docs', 'man')
248 man_dir = pjoin('docs', 'man')
250 manpage_gz = manpage + '.gz'
249 manpage_gz = manpage + '.gz'
251 manpath = pjoin(man_dir, manpage)
250 manpath = pjoin(man_dir, manpage)
252 manpath_gz = pjoin(man_dir, manpage_gz)
251 manpath_gz = pjoin(man_dir, manpage_gz)
253 gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" %
252 gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" %
254 locals() )
253 locals() )
255 return (manpath_gz, [manpath], gz_cmd)
254 return (manpath_gz, [manpath], gz_cmd)
256
255
257 #---------------------------------------------------------------------------
256 #---------------------------------------------------------------------------
258 # Find scripts
257 # Find scripts
259 #---------------------------------------------------------------------------
258 #---------------------------------------------------------------------------
260
259
261 def find_scripts(entry_points=False):
260 def find_scripts(entry_points=False):
262 """Find IPython's scripts.
261 """Find IPython's scripts.
263
262
264 if entry_points is True:
263 if entry_points is True:
265 return setuptools entry_point-style definitions
264 return setuptools entry_point-style definitions
266 else:
265 else:
267 return file paths of plain scripts [default]
266 return file paths of plain scripts [default]
268 """
267 """
269 if entry_points:
268 if entry_points:
270 console_scripts = [
269 console_scripts = [
271 'ipython = IPython.frontend.terminal.ipapp:launch_new_instance',
270 'ipython = IPython.frontend.terminal.ipapp:launch_new_instance',
272 'pycolor = IPython.utils.PyColorize:main',
271 'pycolor = IPython.utils.PyColorize:main',
273 'ipcontroller = IPython.parallel.apps.ipcontrollerapp:launch_new_instance',
272 'ipcontroller = IPython.parallel.apps.ipcontrollerapp:launch_new_instance',
274 'ipengine = IPython.parallel.apps.ipengineapp:launch_new_instance',
273 'ipengine = IPython.parallel.apps.ipengineapp:launch_new_instance',
275 'iplogger = IPython.parallel.apps.iploggerapp:launch_new_instance',
274 'iplogger = IPython.parallel.apps.iploggerapp:launch_new_instance',
276 'ipcluster = IPython.parallel.apps.ipclusterapp:launch_new_instance',
275 'ipcluster = IPython.parallel.apps.ipclusterapp:launch_new_instance',
277 'iptest = IPython.testing.iptest:main',
276 'iptest = IPython.testing.iptest:main',
278 'irunner = IPython.lib.irunner:main'
277 'irunner = IPython.lib.irunner:main'
279 ]
278 ]
280 gui_scripts = [
279 gui_scripts = [
281 'ipython-qtconsole = IPython.frontend.qt.console.qtconsoleapp:main',
280 'ipython-qtconsole = IPython.frontend.qt.console.qtconsoleapp:main',
282 ]
281 ]
283 scripts = dict(console_scripts=console_scripts, gui_scripts=gui_scripts)
282 scripts = dict(console_scripts=console_scripts, gui_scripts=gui_scripts)
284 else:
283 else:
285 parallel_scripts = pjoin('IPython','parallel','scripts')
284 parallel_scripts = pjoin('IPython','parallel','scripts')
286 main_scripts = pjoin('IPython','scripts')
285 main_scripts = pjoin('IPython','scripts')
287 scripts = [
286 scripts = [
288 pjoin(parallel_scripts, 'ipengine'),
287 pjoin(parallel_scripts, 'ipengine'),
289 pjoin(parallel_scripts, 'ipcontroller'),
288 pjoin(parallel_scripts, 'ipcontroller'),
290 pjoin(parallel_scripts, 'ipcluster'),
289 pjoin(parallel_scripts, 'ipcluster'),
291 pjoin(parallel_scripts, 'iplogger'),
290 pjoin(parallel_scripts, 'iplogger'),
292 pjoin(main_scripts, 'ipython'),
291 pjoin(main_scripts, 'ipython'),
293 pjoin(main_scripts, 'pycolor'),
292 pjoin(main_scripts, 'pycolor'),
294 pjoin(main_scripts, 'irunner'),
293 pjoin(main_scripts, 'irunner'),
295 pjoin(main_scripts, 'iptest')
294 pjoin(main_scripts, 'iptest')
296 ]
295 ]
297 return scripts
296 return scripts
298
297
299 #---------------------------------------------------------------------------
298 #---------------------------------------------------------------------------
300 # Verify all dependencies
299 # Verify all dependencies
301 #---------------------------------------------------------------------------
300 #---------------------------------------------------------------------------
302
301
303 def check_for_dependencies():
302 def check_for_dependencies():
304 """Check for IPython's dependencies.
303 """Check for IPython's dependencies.
305
304
306 This function should NOT be called if running under setuptools!
305 This function should NOT be called if running under setuptools!
307 """
306 """
308 from setupext.setupext import (
307 from setupext.setupext import (
309 print_line, print_raw, print_status,
308 print_line, print_raw, print_status,
310 check_for_sphinx, check_for_pygments,
309 check_for_sphinx, check_for_pygments,
311 check_for_nose, check_for_pexpect,
310 check_for_nose, check_for_pexpect,
312 check_for_pyzmq, check_for_readline
311 check_for_pyzmq, check_for_readline
313 )
312 )
314 print_line()
313 print_line()
315 print_raw("BUILDING IPYTHON")
314 print_raw("BUILDING IPYTHON")
316 print_status('python', sys.version)
315 print_status('python', sys.version)
317 print_status('platform', sys.platform)
316 print_status('platform', sys.platform)
318 if sys.platform == 'win32':
317 if sys.platform == 'win32':
319 print_status('Windows version', sys.getwindowsversion())
318 print_status('Windows version', sys.getwindowsversion())
320
319
321 print_raw("")
320 print_raw("")
322 print_raw("OPTIONAL DEPENDENCIES")
321 print_raw("OPTIONAL DEPENDENCIES")
323
322
324 check_for_sphinx()
323 check_for_sphinx()
325 check_for_pygments()
324 check_for_pygments()
326 check_for_nose()
325 check_for_nose()
327 check_for_pexpect()
326 check_for_pexpect()
328 check_for_pyzmq()
327 check_for_pyzmq()
329 check_for_readline()
328 check_for_readline()
330
329
331 def record_commit_info(pkg_dir, build_cmd=build_py):
330 def record_commit_info(pkg_dir, build_cmd=build_py):
332 """ Return extended build command class for recording commit
331 """ Return extended build command class for recording commit
333
332
334 The extended command tries to run git to find the current commit, getting
333 The extended command tries to run git to find the current commit, getting
335 the empty string if it fails. It then writes the commit hash into a file
334 the empty string if it fails. It then writes the commit hash into a file
336 in the `pkg_dir` path, named ``.git_commit_info.ini``.
335 in the `pkg_dir` path, named ``.git_commit_info.ini``.
337
336
338 In due course this information can be used by the package after it is
337 In due course this information can be used by the package after it is
339 installed, to tell you what commit it was installed from if known.
338 installed, to tell you what commit it was installed from if known.
340
339
341 To make use of this system, you need a package with a .git_commit_info.ini
340 To make use of this system, you need a package with a .git_commit_info.ini
342 file - e.g. ``myproject/.git_commit_info.ini`` - that might well look like
341 file - e.g. ``myproject/.git_commit_info.ini`` - that might well look like
343 this::
342 this::
344
343
345 # This is an ini file that may contain information about the code state
344 # This is an ini file that may contain information about the code state
346 [commit hash]
345 [commit hash]
347 # The line below may contain a valid hash if it has been substituted
346 # The line below may contain a valid hash if it has been substituted
348 # during 'git archive'
347 # during 'git archive'
349 archive_subst_hash=$Format:%h$
348 archive_subst_hash=$Format:%h$
350 # This line may be modified by the install process
349 # This line may be modified by the install process
351 install_hash=
350 install_hash=
352
351
353 The .git_commit_info file above is also designed to be used with git
352 The .git_commit_info file above is also designed to be used with git
354 substitution - so you probably also want a ``.gitattributes`` file in the
353 substitution - so you probably also want a ``.gitattributes`` file in the
355 root directory of your working tree that contains something like this::
354 root directory of your working tree that contains something like this::
356
355
357 myproject/.git_commit_info.ini export-subst
356 myproject/.git_commit_info.ini export-subst
358
357
359 That will cause the ``.git_commit_info.ini`` file to get filled in by ``git
358 That will cause the ``.git_commit_info.ini`` file to get filled in by ``git
360 archive`` - useful in case someone makes such an archive - for example with
359 archive`` - useful in case someone makes such an archive - for example with
361 via the github 'download source' button.
360 via the github 'download source' button.
362
361
363 Although all the above will work as is, you might consider having something
362 Although all the above will work as is, you might consider having something
364 like a ``get_info()`` function in your package to display the commit
363 like a ``get_info()`` function in your package to display the commit
365 information at the terminal. See the ``pkg_info.py`` module in the nipy
364 information at the terminal. See the ``pkg_info.py`` module in the nipy
366 package for an example.
365 package for an example.
367 """
366 """
368 class MyBuildPy(build_cmd):
367 class MyBuildPy(build_cmd):
369 ''' Subclass to write commit data into installation tree '''
368 ''' Subclass to write commit data into installation tree '''
370 def run(self):
369 def run(self):
371 build_py.run(self)
370 build_py.run(self)
372 import subprocess
371 import subprocess
373 proc = subprocess.Popen('git rev-parse --short HEAD',
372 proc = subprocess.Popen('git rev-parse --short HEAD',
374 stdout=subprocess.PIPE,
373 stdout=subprocess.PIPE,
375 stderr=subprocess.PIPE,
374 stderr=subprocess.PIPE,
376 shell=True)
375 shell=True)
377 repo_commit, _ = proc.communicate()
376 repo_commit, _ = proc.communicate()
378 # We write the installation commit even if it's empty
377 # We write the installation commit even if it's empty
379 cfg_parser = ConfigParser()
378 cfg_parser = ConfigParser()
380 cfg_parser.read(pjoin(pkg_dir, '.git_commit_info.ini'))
379 cfg_parser.read(pjoin(pkg_dir, '.git_commit_info.ini'))
381 cfg_parser.set('commit hash', 'install_hash', repo_commit)
380 cfg_parser.set('commit hash', 'install_hash', repo_commit)
382 out_pth = pjoin(self.build_lib, pkg_dir, '.git_commit_info.ini')
381 out_pth = pjoin(self.build_lib, pkg_dir, '.git_commit_info.ini')
383 out_file = open(out_pth, 'wt')
382 out_file = open(out_pth, 'wt')
384 cfg_parser.write(out_file)
383 cfg_parser.write(out_file)
385 out_file.close()
384 out_file.close()
386 return MyBuildPy
385 return MyBuildPy
General Comments 0
You need to be logged in to leave comments. Login now