##// END OF EJS Templates
Exclude IPython.quarantine from installation.
Thomas Kluyver -
Show More
@@ -1,398 +1,398 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 try:
26 try:
27 from configparser import ConfigParser
27 from configparser import ConfigParser
28 except:
28 except:
29 from ConfigParser import ConfigParser
29 from ConfigParser import ConfigParser
30 from distutils.command.build_py import build_py
30 from distutils.command.build_py import build_py
31 from glob import glob
31 from glob import glob
32
32
33 from setupext import install_data_ext
33 from setupext import install_data_ext
34
34
35 #-------------------------------------------------------------------------------
35 #-------------------------------------------------------------------------------
36 # Useful globals and utility functions
36 # Useful globals and utility functions
37 #-------------------------------------------------------------------------------
37 #-------------------------------------------------------------------------------
38
38
39 # A few handy globals
39 # A few handy globals
40 isfile = os.path.isfile
40 isfile = os.path.isfile
41 pjoin = os.path.join
41 pjoin = os.path.join
42
42
43 def oscmd(s):
43 def oscmd(s):
44 print(">", s)
44 print(">", s)
45 os.system(s)
45 os.system(s)
46
46
47 # Py3 compatibility hacks, without assuming IPython itself is installed with
47 # Py3 compatibility hacks, without assuming IPython itself is installed with
48 # the full py3compat machinery.
48 # the full py3compat machinery.
49
49
50 try:
50 try:
51 execfile
51 execfile
52 except NameError:
52 except NameError:
53 def execfile(fname, globs, locs=None):
53 def execfile(fname, globs, locs=None):
54 locs = locs or globs
54 locs = locs or globs
55 exec(compile(open(fname).read(), fname, "exec"), globs, locs)
55 exec(compile(open(fname).read(), fname, "exec"), globs, locs)
56
56
57 # A little utility we'll need below, since glob() does NOT allow you to do
57 # A little utility we'll need below, since glob() does NOT allow you to do
58 # exclusion on multiple endings!
58 # exclusion on multiple endings!
59 def file_doesnt_endwith(test,endings):
59 def file_doesnt_endwith(test,endings):
60 """Return true if test is a file and its name does NOT end with any
60 """Return true if test is a file and its name does NOT end with any
61 of the strings listed in endings."""
61 of the strings listed in endings."""
62 if not isfile(test):
62 if not isfile(test):
63 return False
63 return False
64 for e in endings:
64 for e in endings:
65 if test.endswith(e):
65 if test.endswith(e):
66 return False
66 return False
67 return True
67 return True
68
68
69 #---------------------------------------------------------------------------
69 #---------------------------------------------------------------------------
70 # Basic project information
70 # Basic project information
71 #---------------------------------------------------------------------------
71 #---------------------------------------------------------------------------
72
72
73 # release.py contains version, authors, license, url, keywords, etc.
73 # release.py contains version, authors, license, url, keywords, etc.
74 execfile(pjoin('IPython','core','release.py'), globals())
74 execfile(pjoin('IPython','core','release.py'), globals())
75
75
76 # Create a dict with the basic information
76 # Create a dict with the basic information
77 # This dict is eventually passed to setup after additional keys are added.
77 # This dict is eventually passed to setup after additional keys are added.
78 setup_args = dict(
78 setup_args = dict(
79 name = name,
79 name = name,
80 version = version,
80 version = version,
81 description = description,
81 description = description,
82 long_description = long_description,
82 long_description = long_description,
83 author = author,
83 author = author,
84 author_email = author_email,
84 author_email = author_email,
85 url = url,
85 url = url,
86 download_url = download_url,
86 download_url = download_url,
87 license = license,
87 license = license,
88 platforms = platforms,
88 platforms = platforms,
89 keywords = keywords,
89 keywords = keywords,
90 classifiers = classifiers,
90 classifiers = classifiers,
91 cmdclass = {'install_data': install_data_ext},
91 cmdclass = {'install_data': install_data_ext},
92 )
92 )
93
93
94
94
95 #---------------------------------------------------------------------------
95 #---------------------------------------------------------------------------
96 # Find packages
96 # Find packages
97 #---------------------------------------------------------------------------
97 #---------------------------------------------------------------------------
98
98
99 def find_packages():
99 def find_packages():
100 """
100 """
101 Find all of IPython's packages.
101 Find all of IPython's packages.
102 """
102 """
103 excludes = ['deathrow']
103 excludes = ['deathrow', 'quarantine']
104 packages = []
104 packages = []
105 for dir,subdirs,files in os.walk('IPython'):
105 for dir,subdirs,files in os.walk('IPython'):
106 package = dir.replace(os.path.sep, '.')
106 package = dir.replace(os.path.sep, '.')
107 if any([ package.startswith('IPython.'+exc) for exc in excludes ]):
107 if any(package.startswith('IPython.'+exc) for exc in excludes):
108 # package is to be excluded (e.g. deathrow)
108 # package is to be excluded (e.g. deathrow)
109 continue
109 continue
110 if '__init__.py' not in files:
110 if '__init__.py' not in files:
111 # not a package
111 # not a package
112 continue
112 continue
113 packages.append(package)
113 packages.append(package)
114 return packages
114 return packages
115
115
116 #---------------------------------------------------------------------------
116 #---------------------------------------------------------------------------
117 # Find package data
117 # Find package data
118 #---------------------------------------------------------------------------
118 #---------------------------------------------------------------------------
119
119
120 def find_package_data():
120 def find_package_data():
121 """
121 """
122 Find IPython's package_data.
122 Find IPython's package_data.
123 """
123 """
124 # This is not enough for these things to appear in an sdist.
124 # This is not enough for these things to appear in an sdist.
125 # We need to muck with the MANIFEST to get this to work
125 # We need to muck with the MANIFEST to get this to work
126
126
127 # exclude static things that we don't ship (e.g. mathjax)
127 # exclude static things that we don't ship (e.g. mathjax)
128 excludes = ['mathjax']
128 excludes = ['mathjax']
129
129
130 # add 'static/' prefix to exclusions, and tuplify for use in startswith
130 # add 'static/' prefix to exclusions, and tuplify for use in startswith
131 excludes = tuple([os.path.join('static', ex) for ex in excludes])
131 excludes = tuple([os.path.join('static', ex) for ex in excludes])
132
132
133 # walk notebook resources:
133 # walk notebook resources:
134 cwd = os.getcwd()
134 cwd = os.getcwd()
135 os.chdir(os.path.join('IPython', 'frontend', 'html', 'notebook'))
135 os.chdir(os.path.join('IPython', 'frontend', 'html', 'notebook'))
136 static_walk = list(os.walk('static'))
136 static_walk = list(os.walk('static'))
137 os.chdir(cwd)
137 os.chdir(cwd)
138 static_data = []
138 static_data = []
139 for parent, dirs, files in static_walk:
139 for parent, dirs, files in static_walk:
140 if parent.startswith(excludes):
140 if parent.startswith(excludes):
141 continue
141 continue
142 for f in files:
142 for f in files:
143 static_data.append(os.path.join(parent, f))
143 static_data.append(os.path.join(parent, f))
144
144
145 package_data = {
145 package_data = {
146 'IPython.config.profile' : ['README*', '*/*.py'],
146 'IPython.config.profile' : ['README*', '*/*.py'],
147 'IPython.testing' : ['*.txt'],
147 'IPython.testing' : ['*.txt'],
148 'IPython.frontend.html.notebook' : ['templates/*'] + static_data,
148 'IPython.frontend.html.notebook' : ['templates/*'] + static_data,
149 'IPython.frontend.qt.console' : ['resources/icon/*.svg'],
149 'IPython.frontend.qt.console' : ['resources/icon/*.svg'],
150 }
150 }
151 return package_data
151 return package_data
152
152
153
153
154 #---------------------------------------------------------------------------
154 #---------------------------------------------------------------------------
155 # Find data files
155 # Find data files
156 #---------------------------------------------------------------------------
156 #---------------------------------------------------------------------------
157
157
158 def make_dir_struct(tag,base,out_base):
158 def make_dir_struct(tag,base,out_base):
159 """Make the directory structure of all files below a starting dir.
159 """Make the directory structure of all files below a starting dir.
160
160
161 This is just a convenience routine to help build a nested directory
161 This is just a convenience routine to help build a nested directory
162 hierarchy because distutils is too stupid to do this by itself.
162 hierarchy because distutils is too stupid to do this by itself.
163
163
164 XXX - this needs a proper docstring!
164 XXX - this needs a proper docstring!
165 """
165 """
166
166
167 # we'll use these a lot below
167 # we'll use these a lot below
168 lbase = len(base)
168 lbase = len(base)
169 pathsep = os.path.sep
169 pathsep = os.path.sep
170 lpathsep = len(pathsep)
170 lpathsep = len(pathsep)
171
171
172 out = []
172 out = []
173 for (dirpath,dirnames,filenames) in os.walk(base):
173 for (dirpath,dirnames,filenames) in os.walk(base):
174 # we need to strip out the dirpath from the base to map it to the
174 # we need to strip out the dirpath from the base to map it to the
175 # output (installation) path. This requires possibly stripping the
175 # output (installation) path. This requires possibly stripping the
176 # path separator, because otherwise pjoin will not work correctly
176 # path separator, because otherwise pjoin will not work correctly
177 # (pjoin('foo/','/bar') returns '/bar').
177 # (pjoin('foo/','/bar') returns '/bar').
178
178
179 dp_eff = dirpath[lbase:]
179 dp_eff = dirpath[lbase:]
180 if dp_eff.startswith(pathsep):
180 if dp_eff.startswith(pathsep):
181 dp_eff = dp_eff[lpathsep:]
181 dp_eff = dp_eff[lpathsep:]
182 # The output path must be anchored at the out_base marker
182 # The output path must be anchored at the out_base marker
183 out_path = pjoin(out_base,dp_eff)
183 out_path = pjoin(out_base,dp_eff)
184 # Now we can generate the final filenames. Since os.walk only produces
184 # Now we can generate the final filenames. Since os.walk only produces
185 # filenames, we must join back with the dirpath to get full valid file
185 # filenames, we must join back with the dirpath to get full valid file
186 # paths:
186 # paths:
187 pfiles = [pjoin(dirpath,f) for f in filenames]
187 pfiles = [pjoin(dirpath,f) for f in filenames]
188 # Finally, generate the entry we need, which is a pari of (output
188 # Finally, generate the entry we need, which is a pari of (output
189 # path, files) for use as a data_files parameter in install_data.
189 # path, files) for use as a data_files parameter in install_data.
190 out.append((out_path, pfiles))
190 out.append((out_path, pfiles))
191
191
192 return out
192 return out
193
193
194
194
195 def find_data_files():
195 def find_data_files():
196 """
196 """
197 Find IPython's data_files.
197 Find IPython's data_files.
198
198
199 Most of these are docs.
199 Most of these are docs.
200 """
200 """
201
201
202 docdirbase = pjoin('share', 'doc', 'ipython')
202 docdirbase = pjoin('share', 'doc', 'ipython')
203 manpagebase = pjoin('share', 'man', 'man1')
203 manpagebase = pjoin('share', 'man', 'man1')
204
204
205 # Simple file lists can be made by hand
205 # Simple file lists can be made by hand
206 manpages = filter(isfile, glob(pjoin('docs','man','*.1.gz')))
206 manpages = filter(isfile, glob(pjoin('docs','man','*.1.gz')))
207 if not manpages:
207 if not manpages:
208 # When running from a source tree, the manpages aren't gzipped
208 # When running from a source tree, the manpages aren't gzipped
209 manpages = filter(isfile, glob(pjoin('docs','man','*.1')))
209 manpages = filter(isfile, glob(pjoin('docs','man','*.1')))
210 igridhelpfiles = filter(isfile,
210 igridhelpfiles = filter(isfile,
211 glob(pjoin('IPython','extensions','igrid_help.*')))
211 glob(pjoin('IPython','extensions','igrid_help.*')))
212
212
213 # For nested structures, use the utility above
213 # For nested structures, use the utility above
214 example_files = make_dir_struct(
214 example_files = make_dir_struct(
215 'data',
215 'data',
216 pjoin('docs','examples'),
216 pjoin('docs','examples'),
217 pjoin(docdirbase,'examples')
217 pjoin(docdirbase,'examples')
218 )
218 )
219 manual_files = make_dir_struct(
219 manual_files = make_dir_struct(
220 'data',
220 'data',
221 pjoin('docs','html'),
221 pjoin('docs','html'),
222 pjoin(docdirbase,'manual')
222 pjoin(docdirbase,'manual')
223 )
223 )
224
224
225 # And assemble the entire output list
225 # And assemble the entire output list
226 data_files = [ (manpagebase, manpages),
226 data_files = [ (manpagebase, manpages),
227 (pjoin(docdirbase, 'extensions'), igridhelpfiles),
227 (pjoin(docdirbase, 'extensions'), igridhelpfiles),
228 ] + manual_files + example_files
228 ] + manual_files + example_files
229
229
230 return data_files
230 return data_files
231
231
232
232
233 def make_man_update_target(manpage):
233 def make_man_update_target(manpage):
234 """Return a target_update-compliant tuple for the given manpage.
234 """Return a target_update-compliant tuple for the given manpage.
235
235
236 Parameters
236 Parameters
237 ----------
237 ----------
238 manpage : string
238 manpage : string
239 Name of the manpage, must include the section number (trailing number).
239 Name of the manpage, must include the section number (trailing number).
240
240
241 Example
241 Example
242 -------
242 -------
243
243
244 >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE
244 >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE
245 ('docs/man/ipython.1.gz',
245 ('docs/man/ipython.1.gz',
246 ['docs/man/ipython.1'],
246 ['docs/man/ipython.1'],
247 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz')
247 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz')
248 """
248 """
249 man_dir = pjoin('docs', 'man')
249 man_dir = pjoin('docs', 'man')
250 manpage_gz = manpage + '.gz'
250 manpage_gz = manpage + '.gz'
251 manpath = pjoin(man_dir, manpage)
251 manpath = pjoin(man_dir, manpage)
252 manpath_gz = pjoin(man_dir, manpage_gz)
252 manpath_gz = pjoin(man_dir, manpage_gz)
253 gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" %
253 gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" %
254 locals() )
254 locals() )
255 return (manpath_gz, [manpath], gz_cmd)
255 return (manpath_gz, [manpath], gz_cmd)
256
256
257 # The two functions below are copied from IPython.utils.path, so we don't need
257 # The two functions below are copied from IPython.utils.path, so we don't need
258 # to import IPython during setup, which fails on Python 3.
258 # to import IPython during setup, which fails on Python 3.
259
259
260 def target_outdated(target,deps):
260 def target_outdated(target,deps):
261 """Determine whether a target is out of date.
261 """Determine whether a target is out of date.
262
262
263 target_outdated(target,deps) -> 1/0
263 target_outdated(target,deps) -> 1/0
264
264
265 deps: list of filenames which MUST exist.
265 deps: list of filenames which MUST exist.
266 target: single filename which may or may not exist.
266 target: single filename which may or may not exist.
267
267
268 If target doesn't exist or is older than any file listed in deps, return
268 If target doesn't exist or is older than any file listed in deps, return
269 true, otherwise return false.
269 true, otherwise return false.
270 """
270 """
271 try:
271 try:
272 target_time = os.path.getmtime(target)
272 target_time = os.path.getmtime(target)
273 except os.error:
273 except os.error:
274 return 1
274 return 1
275 for dep in deps:
275 for dep in deps:
276 dep_time = os.path.getmtime(dep)
276 dep_time = os.path.getmtime(dep)
277 if dep_time > target_time:
277 if dep_time > target_time:
278 #print "For target",target,"Dep failed:",dep # dbg
278 #print "For target",target,"Dep failed:",dep # dbg
279 #print "times (dep,tar):",dep_time,target_time # dbg
279 #print "times (dep,tar):",dep_time,target_time # dbg
280 return 1
280 return 1
281 return 0
281 return 0
282
282
283
283
284 def target_update(target,deps,cmd):
284 def target_update(target,deps,cmd):
285 """Update a target with a given command given a list of dependencies.
285 """Update a target with a given command given a list of dependencies.
286
286
287 target_update(target,deps,cmd) -> runs cmd if target is outdated.
287 target_update(target,deps,cmd) -> runs cmd if target is outdated.
288
288
289 This is just a wrapper around target_outdated() which calls the given
289 This is just a wrapper around target_outdated() which calls the given
290 command if target is outdated."""
290 command if target is outdated."""
291
291
292 if target_outdated(target,deps):
292 if target_outdated(target,deps):
293 os.system(cmd)
293 os.system(cmd)
294
294
295 #---------------------------------------------------------------------------
295 #---------------------------------------------------------------------------
296 # Find scripts
296 # Find scripts
297 #---------------------------------------------------------------------------
297 #---------------------------------------------------------------------------
298
298
299 def find_scripts(entry_points=False, suffix=''):
299 def find_scripts(entry_points=False, suffix=''):
300 """Find IPython's scripts.
300 """Find IPython's scripts.
301
301
302 if entry_points is True:
302 if entry_points is True:
303 return setuptools entry_point-style definitions
303 return setuptools entry_point-style definitions
304 else:
304 else:
305 return file paths of plain scripts [default]
305 return file paths of plain scripts [default]
306
306
307 suffix is appended to script names if entry_points is True, so that the
307 suffix is appended to script names if entry_points is True, so that the
308 Python 3 scripts get named "ipython3" etc.
308 Python 3 scripts get named "ipython3" etc.
309 """
309 """
310 if entry_points:
310 if entry_points:
311 console_scripts = [s % suffix for s in [
311 console_scripts = [s % suffix for s in [
312 'ipython%s = IPython.frontend.terminal.ipapp:launch_new_instance',
312 'ipython%s = IPython.frontend.terminal.ipapp:launch_new_instance',
313 'pycolor%s = IPython.utils.PyColorize:main',
313 'pycolor%s = IPython.utils.PyColorize:main',
314 'ipcontroller%s = IPython.parallel.apps.ipcontrollerapp:launch_new_instance',
314 'ipcontroller%s = IPython.parallel.apps.ipcontrollerapp:launch_new_instance',
315 'ipengine%s = IPython.parallel.apps.ipengineapp:launch_new_instance',
315 'ipengine%s = IPython.parallel.apps.ipengineapp:launch_new_instance',
316 'iplogger%s = IPython.parallel.apps.iploggerapp:launch_new_instance',
316 'iplogger%s = IPython.parallel.apps.iploggerapp:launch_new_instance',
317 'ipcluster%s = IPython.parallel.apps.ipclusterapp:launch_new_instance',
317 'ipcluster%s = IPython.parallel.apps.ipclusterapp:launch_new_instance',
318 'iptest%s = IPython.testing.iptest:main',
318 'iptest%s = IPython.testing.iptest:main',
319 'irunner%s = IPython.lib.irunner:main'
319 'irunner%s = IPython.lib.irunner:main'
320 ]]
320 ]]
321 gui_scripts = [s % suffix for s in [
321 gui_scripts = [s % suffix for s in [
322 'ipython%s-qtconsole = IPython.frontend.qt.console.qtconsoleapp:main',
322 'ipython%s-qtconsole = IPython.frontend.qt.console.qtconsoleapp:main',
323 ]]
323 ]]
324 scripts = dict(console_scripts=console_scripts, gui_scripts=gui_scripts)
324 scripts = dict(console_scripts=console_scripts, gui_scripts=gui_scripts)
325 else:
325 else:
326 parallel_scripts = pjoin('IPython','parallel','scripts')
326 parallel_scripts = pjoin('IPython','parallel','scripts')
327 main_scripts = pjoin('IPython','scripts')
327 main_scripts = pjoin('IPython','scripts')
328 scripts = [
328 scripts = [
329 pjoin(parallel_scripts, 'ipengine'),
329 pjoin(parallel_scripts, 'ipengine'),
330 pjoin(parallel_scripts, 'ipcontroller'),
330 pjoin(parallel_scripts, 'ipcontroller'),
331 pjoin(parallel_scripts, 'ipcluster'),
331 pjoin(parallel_scripts, 'ipcluster'),
332 pjoin(parallel_scripts, 'iplogger'),
332 pjoin(parallel_scripts, 'iplogger'),
333 pjoin(main_scripts, 'ipython'),
333 pjoin(main_scripts, 'ipython'),
334 pjoin(main_scripts, 'pycolor'),
334 pjoin(main_scripts, 'pycolor'),
335 pjoin(main_scripts, 'irunner'),
335 pjoin(main_scripts, 'irunner'),
336 pjoin(main_scripts, 'iptest')
336 pjoin(main_scripts, 'iptest')
337 ]
337 ]
338 return scripts
338 return scripts
339
339
340 #---------------------------------------------------------------------------
340 #---------------------------------------------------------------------------
341 # Verify all dependencies
341 # Verify all dependencies
342 #---------------------------------------------------------------------------
342 #---------------------------------------------------------------------------
343
343
344 def check_for_dependencies():
344 def check_for_dependencies():
345 """Check for IPython's dependencies.
345 """Check for IPython's dependencies.
346
346
347 This function should NOT be called if running under setuptools!
347 This function should NOT be called if running under setuptools!
348 """
348 """
349 from setupext.setupext import (
349 from setupext.setupext import (
350 print_line, print_raw, print_status,
350 print_line, print_raw, print_status,
351 check_for_sphinx, check_for_pygments,
351 check_for_sphinx, check_for_pygments,
352 check_for_nose, check_for_pexpect,
352 check_for_nose, check_for_pexpect,
353 check_for_pyzmq, check_for_readline
353 check_for_pyzmq, check_for_readline
354 )
354 )
355 print_line()
355 print_line()
356 print_raw("BUILDING IPYTHON")
356 print_raw("BUILDING IPYTHON")
357 print_status('python', sys.version)
357 print_status('python', sys.version)
358 print_status('platform', sys.platform)
358 print_status('platform', sys.platform)
359 if sys.platform == 'win32':
359 if sys.platform == 'win32':
360 print_status('Windows version', sys.getwindowsversion())
360 print_status('Windows version', sys.getwindowsversion())
361
361
362 print_raw("")
362 print_raw("")
363 print_raw("OPTIONAL DEPENDENCIES")
363 print_raw("OPTIONAL DEPENDENCIES")
364
364
365 check_for_sphinx()
365 check_for_sphinx()
366 check_for_pygments()
366 check_for_pygments()
367 check_for_nose()
367 check_for_nose()
368 check_for_pexpect()
368 check_for_pexpect()
369 check_for_pyzmq()
369 check_for_pyzmq()
370 check_for_readline()
370 check_for_readline()
371
371
372 def record_commit_info(pkg_dir, build_cmd=build_py):
372 def record_commit_info(pkg_dir, build_cmd=build_py):
373 """ Return extended build command class for recording commit
373 """ Return extended build command class for recording commit
374
374
375 records git commit in IPython.utils._sysinfo.commit
375 records git commit in IPython.utils._sysinfo.commit
376
376
377 for use in IPython.utils.sysinfo.sys_info() calls after installation.
377 for use in IPython.utils.sysinfo.sys_info() calls after installation.
378 """
378 """
379
379
380 class MyBuildPy(build_cmd):
380 class MyBuildPy(build_cmd):
381 ''' Subclass to write commit data into installation tree '''
381 ''' Subclass to write commit data into installation tree '''
382 def run(self):
382 def run(self):
383 build_cmd.run(self)
383 build_cmd.run(self)
384 import subprocess
384 import subprocess
385 proc = subprocess.Popen('git rev-parse --short HEAD',
385 proc = subprocess.Popen('git rev-parse --short HEAD',
386 stdout=subprocess.PIPE,
386 stdout=subprocess.PIPE,
387 stderr=subprocess.PIPE,
387 stderr=subprocess.PIPE,
388 shell=True)
388 shell=True)
389 repo_commit, _ = proc.communicate()
389 repo_commit, _ = proc.communicate()
390 repo_commit = repo_commit.strip()
390 repo_commit = repo_commit.strip()
391 # We write the installation commit even if it's empty
391 # We write the installation commit even if it's empty
392 out_pth = pjoin(self.build_lib, pkg_dir, 'utils', '_sysinfo.py')
392 out_pth = pjoin(self.build_lib, pkg_dir, 'utils', '_sysinfo.py')
393 with open(out_pth, 'w') as out_file:
393 with open(out_pth, 'w') as out_file:
394 out_file.writelines([
394 out_file.writelines([
395 '# GENERATED BY setup.py\n',
395 '# GENERATED BY setup.py\n',
396 'commit = "%s"\n' % repo_commit.decode('ascii'),
396 'commit = "%s"\n' % repo_commit.decode('ascii'),
397 ])
397 ])
398 return MyBuildPy
398 return MyBuildPy
General Comments 0
You need to be logged in to leave comments. Login now