##// END OF EJS Templates
Add SVG qt console icon to package data.
Fernando Perez -
Show More
@@ -1,32 +1,34 b''
1 include ipython.py
1 include ipython.py
2 include setupbase.py
2 include setupbase.py
3 include setupegg.py
3 include setupegg.py
4
4
5 graft setupext
5 graft setupext
6
6
7 graft scripts
7 graft scripts
8
8
9 # Load main dir but exclude things we don't want in the distro
9 # Load main dir but exclude things we don't want in the distro
10 graft IPython
10 graft IPython
11 prune IPython/deathrow
11 prune IPython/deathrow
12 prune IPython/frontend/html/notebook/static/mathjax
12 prune IPython/frontend/html/notebook/static/mathjax
13
13
14 include IPython/.git_commit_info.ini
14 include IPython/.git_commit_info.ini
15
15
16 include IPython/frontend/qt/console/resources/icon/IPythonConsole.svg
17
16 graft docs
18 graft docs
17 exclude docs/\#*
19 exclude docs/\#*
18 exclude docs/man/*.1
20 exclude docs/man/*.1
19
21
20 # docs subdirs we want to skip
22 # docs subdirs we want to skip
21 prune docs/attic
23 prune docs/attic
22 prune docs/build
24 prune docs/build
23 prune docs/gh-pages
25 prune docs/gh-pages
24
26
25
27
26 global-exclude *~
28 global-exclude *~
27 global-exclude *.flc
29 global-exclude *.flc
28 global-exclude *.pyc
30 global-exclude *.pyc
29 global-exclude .dircopy.log
31 global-exclude .dircopy.log
30 global-exclude .svn
32 global-exclude .svn
31 global-exclude .bzr
33 global-exclude .bzr
32 global-exclude .hgignore
34 global-exclude .hgignore
@@ -1,377 +1,378 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 try:
47 try:
48 execfile
48 execfile
49 except NameError:
49 except NameError:
50 def execfile(fname, globs, locs=None):
50 def execfile(fname, globs, locs=None):
51 locs = locs or globs
51 locs = locs or globs
52 exec(compile(open(fname).read(), fname, "exec"), globs, locs)
52 exec(compile(open(fname).read(), fname, "exec"), globs, locs)
53
53
54 # A little utility we'll need below, since glob() does NOT allow you to do
54 # A little utility we'll need below, since glob() does NOT allow you to do
55 # exclusion on multiple endings!
55 # exclusion on multiple endings!
56 def file_doesnt_endwith(test,endings):
56 def file_doesnt_endwith(test,endings):
57 """Return true if test is a file and its name does NOT end with any
57 """Return true if test is a file and its name does NOT end with any
58 of the strings listed in endings."""
58 of the strings listed in endings."""
59 if not isfile(test):
59 if not isfile(test):
60 return False
60 return False
61 for e in endings:
61 for e in endings:
62 if test.endswith(e):
62 if test.endswith(e):
63 return False
63 return False
64 return True
64 return True
65
65
66 #---------------------------------------------------------------------------
66 #---------------------------------------------------------------------------
67 # Basic project information
67 # Basic project information
68 #---------------------------------------------------------------------------
68 #---------------------------------------------------------------------------
69
69
70 # release.py contains version, authors, license, url, keywords, etc.
70 # release.py contains version, authors, license, url, keywords, etc.
71 execfile(pjoin('IPython','core','release.py'), globals())
71 execfile(pjoin('IPython','core','release.py'), globals())
72
72
73 # Create a dict with the basic information
73 # Create a dict with the basic information
74 # This dict is eventually passed to setup after additional keys are added.
74 # This dict is eventually passed to setup after additional keys are added.
75 setup_args = dict(
75 setup_args = dict(
76 name = name,
76 name = name,
77 version = version,
77 version = version,
78 description = description,
78 description = description,
79 long_description = long_description,
79 long_description = long_description,
80 author = author,
80 author = author,
81 author_email = author_email,
81 author_email = author_email,
82 url = url,
82 url = url,
83 download_url = download_url,
83 download_url = download_url,
84 license = license,
84 license = license,
85 platforms = platforms,
85 platforms = platforms,
86 keywords = keywords,
86 keywords = keywords,
87 classifiers = classifiers,
87 classifiers = classifiers,
88 cmdclass = {'install_data': install_data_ext},
88 cmdclass = {'install_data': install_data_ext},
89 )
89 )
90
90
91
91
92 #---------------------------------------------------------------------------
92 #---------------------------------------------------------------------------
93 # Find packages
93 # Find packages
94 #---------------------------------------------------------------------------
94 #---------------------------------------------------------------------------
95
95
96 def find_packages():
96 def find_packages():
97 """
97 """
98 Find all of IPython's packages.
98 Find all of IPython's packages.
99 """
99 """
100 excludes = ['deathrow']
100 excludes = ['deathrow']
101 packages = []
101 packages = []
102 for dir,subdirs,files in os.walk('IPython'):
102 for dir,subdirs,files in os.walk('IPython'):
103 package = dir.replace(os.path.sep, '.')
103 package = dir.replace(os.path.sep, '.')
104 if any([ package.startswith('IPython.'+exc) for exc in excludes ]):
104 if any([ package.startswith('IPython.'+exc) for exc in excludes ]):
105 # package is to be excluded (e.g. deathrow)
105 # package is to be excluded (e.g. deathrow)
106 continue
106 continue
107 if '__init__.py' not in files:
107 if '__init__.py' not in files:
108 # not a package
108 # not a package
109 continue
109 continue
110 packages.append(package)
110 packages.append(package)
111 return packages
111 return packages
112
112
113 #---------------------------------------------------------------------------
113 #---------------------------------------------------------------------------
114 # Find package data
114 # Find package data
115 #---------------------------------------------------------------------------
115 #---------------------------------------------------------------------------
116
116
117 def find_package_data():
117 def find_package_data():
118 """
118 """
119 Find IPython's package_data.
119 Find IPython's package_data.
120 """
120 """
121 # This is not enough for these things to appear in an sdist.
121 # This is not enough for these things to appear in an sdist.
122 # We need to muck with the MANIFEST to get this to work
122 # We need to muck with the MANIFEST to get this to work
123
123
124 # walk notebook resources:
124 # walk notebook resources:
125 cwd = os.getcwd()
125 cwd = os.getcwd()
126 os.chdir(os.path.join('IPython', 'frontend', 'html', 'notebook'))
126 os.chdir(os.path.join('IPython', 'frontend', 'html', 'notebook'))
127 static_walk = list(os.walk('static'))
127 static_walk = list(os.walk('static'))
128 os.chdir(cwd)
128 os.chdir(cwd)
129 static_data = []
129 static_data = []
130 for parent, dirs, files in static_walk:
130 for parent, dirs, files in static_walk:
131 for f in files:
131 for f in files:
132 static_data.append(os.path.join(parent, f))
132 static_data.append(os.path.join(parent, f))
133
133
134 package_data = {
134 package_data = {
135 'IPython.config.profile' : ['README', '*/*.py'],
135 'IPython.config.profile' : ['README', '*/*.py'],
136 'IPython.testing' : ['*.txt'],
136 'IPython.testing' : ['*.txt'],
137 'IPython.frontend.html.notebook' : ['templates/*']+static_data
137 'IPython.frontend.html.notebook' : ['templates/*'] + static_data,
138 'IPython.frontend.qt.console' : ['resources/icon/*.svg'],
138 }
139 }
139 return package_data
140 return package_data
140
141
141
142
142 #---------------------------------------------------------------------------
143 #---------------------------------------------------------------------------
143 # Find data files
144 # Find data files
144 #---------------------------------------------------------------------------
145 #---------------------------------------------------------------------------
145
146
146 def make_dir_struct(tag,base,out_base):
147 def make_dir_struct(tag,base,out_base):
147 """Make the directory structure of all files below a starting dir.
148 """Make the directory structure of all files below a starting dir.
148
149
149 This is just a convenience routine to help build a nested directory
150 This is just a convenience routine to help build a nested directory
150 hierarchy because distutils is too stupid to do this by itself.
151 hierarchy because distutils is too stupid to do this by itself.
151
152
152 XXX - this needs a proper docstring!
153 XXX - this needs a proper docstring!
153 """
154 """
154
155
155 # we'll use these a lot below
156 # we'll use these a lot below
156 lbase = len(base)
157 lbase = len(base)
157 pathsep = os.path.sep
158 pathsep = os.path.sep
158 lpathsep = len(pathsep)
159 lpathsep = len(pathsep)
159
160
160 out = []
161 out = []
161 for (dirpath,dirnames,filenames) in os.walk(base):
162 for (dirpath,dirnames,filenames) in os.walk(base):
162 # we need to strip out the dirpath from the base to map it to the
163 # we need to strip out the dirpath from the base to map it to the
163 # output (installation) path. This requires possibly stripping the
164 # output (installation) path. This requires possibly stripping the
164 # path separator, because otherwise pjoin will not work correctly
165 # path separator, because otherwise pjoin will not work correctly
165 # (pjoin('foo/','/bar') returns '/bar').
166 # (pjoin('foo/','/bar') returns '/bar').
166
167
167 dp_eff = dirpath[lbase:]
168 dp_eff = dirpath[lbase:]
168 if dp_eff.startswith(pathsep):
169 if dp_eff.startswith(pathsep):
169 dp_eff = dp_eff[lpathsep:]
170 dp_eff = dp_eff[lpathsep:]
170 # The output path must be anchored at the out_base marker
171 # The output path must be anchored at the out_base marker
171 out_path = pjoin(out_base,dp_eff)
172 out_path = pjoin(out_base,dp_eff)
172 # Now we can generate the final filenames. Since os.walk only produces
173 # Now we can generate the final filenames. Since os.walk only produces
173 # filenames, we must join back with the dirpath to get full valid file
174 # filenames, we must join back with the dirpath to get full valid file
174 # paths:
175 # paths:
175 pfiles = [pjoin(dirpath,f) for f in filenames]
176 pfiles = [pjoin(dirpath,f) for f in filenames]
176 # Finally, generate the entry we need, which is a pari of (output
177 # Finally, generate the entry we need, which is a pari of (output
177 # path, files) for use as a data_files parameter in install_data.
178 # path, files) for use as a data_files parameter in install_data.
178 out.append((out_path, pfiles))
179 out.append((out_path, pfiles))
179
180
180 return out
181 return out
181
182
182
183
183 def find_data_files():
184 def find_data_files():
184 """
185 """
185 Find IPython's data_files.
186 Find IPython's data_files.
186
187
187 Most of these are docs.
188 Most of these are docs.
188 """
189 """
189
190
190 docdirbase = pjoin('share', 'doc', 'ipython')
191 docdirbase = pjoin('share', 'doc', 'ipython')
191 manpagebase = pjoin('share', 'man', 'man1')
192 manpagebase = pjoin('share', 'man', 'man1')
192
193
193 # Simple file lists can be made by hand
194 # Simple file lists can be made by hand
194 manpages = filter(isfile, glob(pjoin('docs','man','*.1.gz')))
195 manpages = filter(isfile, glob(pjoin('docs','man','*.1.gz')))
195 if not manpages:
196 if not manpages:
196 # When running from a source tree, the manpages aren't gzipped
197 # When running from a source tree, the manpages aren't gzipped
197 manpages = filter(isfile, glob(pjoin('docs','man','*.1')))
198 manpages = filter(isfile, glob(pjoin('docs','man','*.1')))
198 igridhelpfiles = filter(isfile,
199 igridhelpfiles = filter(isfile,
199 glob(pjoin('IPython','extensions','igrid_help.*')))
200 glob(pjoin('IPython','extensions','igrid_help.*')))
200
201
201 # For nested structures, use the utility above
202 # For nested structures, use the utility above
202 example_files = make_dir_struct(
203 example_files = make_dir_struct(
203 'data',
204 'data',
204 pjoin('docs','examples'),
205 pjoin('docs','examples'),
205 pjoin(docdirbase,'examples')
206 pjoin(docdirbase,'examples')
206 )
207 )
207 manual_files = make_dir_struct(
208 manual_files = make_dir_struct(
208 'data',
209 'data',
209 pjoin('docs','html'),
210 pjoin('docs','html'),
210 pjoin(docdirbase,'manual')
211 pjoin(docdirbase,'manual')
211 )
212 )
212
213
213 # And assemble the entire output list
214 # And assemble the entire output list
214 data_files = [ (manpagebase, manpages),
215 data_files = [ (manpagebase, manpages),
215 (pjoin(docdirbase, 'extensions'), igridhelpfiles),
216 (pjoin(docdirbase, 'extensions'), igridhelpfiles),
216 ] + manual_files + example_files
217 ] + manual_files + example_files
217
218
218 return data_files
219 return data_files
219
220
220
221
221 def make_man_update_target(manpage):
222 def make_man_update_target(manpage):
222 """Return a target_update-compliant tuple for the given manpage.
223 """Return a target_update-compliant tuple for the given manpage.
223
224
224 Parameters
225 Parameters
225 ----------
226 ----------
226 manpage : string
227 manpage : string
227 Name of the manpage, must include the section number (trailing number).
228 Name of the manpage, must include the section number (trailing number).
228
229
229 Example
230 Example
230 -------
231 -------
231
232
232 >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE
233 >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE
233 ('docs/man/ipython.1.gz',
234 ('docs/man/ipython.1.gz',
234 ['docs/man/ipython.1'],
235 ['docs/man/ipython.1'],
235 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz')
236 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz')
236 """
237 """
237 man_dir = pjoin('docs', 'man')
238 man_dir = pjoin('docs', 'man')
238 manpage_gz = manpage + '.gz'
239 manpage_gz = manpage + '.gz'
239 manpath = pjoin(man_dir, manpage)
240 manpath = pjoin(man_dir, manpage)
240 manpath_gz = pjoin(man_dir, manpage_gz)
241 manpath_gz = pjoin(man_dir, manpage_gz)
241 gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" %
242 gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" %
242 locals() )
243 locals() )
243 return (manpath_gz, [manpath], gz_cmd)
244 return (manpath_gz, [manpath], gz_cmd)
244
245
245 #---------------------------------------------------------------------------
246 #---------------------------------------------------------------------------
246 # Find scripts
247 # Find scripts
247 #---------------------------------------------------------------------------
248 #---------------------------------------------------------------------------
248
249
249 def find_scripts(entry_points=False, suffix=''):
250 def find_scripts(entry_points=False, suffix=''):
250 """Find IPython's scripts.
251 """Find IPython's scripts.
251
252
252 if entry_points is True:
253 if entry_points is True:
253 return setuptools entry_point-style definitions
254 return setuptools entry_point-style definitions
254 else:
255 else:
255 return file paths of plain scripts [default]
256 return file paths of plain scripts [default]
256
257
257 suffix is appended to script names if entry_points is True, so that the
258 suffix is appended to script names if entry_points is True, so that the
258 Python 3 scripts get named "ipython3" etc.
259 Python 3 scripts get named "ipython3" etc.
259 """
260 """
260 if entry_points:
261 if entry_points:
261 console_scripts = [s % suffix for s in [
262 console_scripts = [s % suffix for s in [
262 'ipython%s = IPython.frontend.terminal.ipapp:launch_new_instance',
263 'ipython%s = IPython.frontend.terminal.ipapp:launch_new_instance',
263 'pycolor%s = IPython.utils.PyColorize:main',
264 'pycolor%s = IPython.utils.PyColorize:main',
264 'ipcontroller%s = IPython.parallel.apps.ipcontrollerapp:launch_new_instance',
265 'ipcontroller%s = IPython.parallel.apps.ipcontrollerapp:launch_new_instance',
265 'ipengine%s = IPython.parallel.apps.ipengineapp:launch_new_instance',
266 'ipengine%s = IPython.parallel.apps.ipengineapp:launch_new_instance',
266 'iplogger%s = IPython.parallel.apps.iploggerapp:launch_new_instance',
267 'iplogger%s = IPython.parallel.apps.iploggerapp:launch_new_instance',
267 'ipcluster%s = IPython.parallel.apps.ipclusterapp:launch_new_instance',
268 'ipcluster%s = IPython.parallel.apps.ipclusterapp:launch_new_instance',
268 'iptest%s = IPython.testing.iptest:main',
269 'iptest%s = IPython.testing.iptest:main',
269 'irunner%s = IPython.lib.irunner:main'
270 'irunner%s = IPython.lib.irunner:main'
270 ]]
271 ]]
271 gui_scripts = [s % suffix for s in [
272 gui_scripts = [s % suffix for s in [
272 'ipython%s-qtconsole = IPython.frontend.qt.console.qtconsoleapp:main',
273 'ipython%s-qtconsole = IPython.frontend.qt.console.qtconsoleapp:main',
273 ]]
274 ]]
274 scripts = dict(console_scripts=console_scripts, gui_scripts=gui_scripts)
275 scripts = dict(console_scripts=console_scripts, gui_scripts=gui_scripts)
275 else:
276 else:
276 parallel_scripts = pjoin('IPython','parallel','scripts')
277 parallel_scripts = pjoin('IPython','parallel','scripts')
277 main_scripts = pjoin('IPython','scripts')
278 main_scripts = pjoin('IPython','scripts')
278 scripts = [
279 scripts = [
279 pjoin(parallel_scripts, 'ipengine'),
280 pjoin(parallel_scripts, 'ipengine'),
280 pjoin(parallel_scripts, 'ipcontroller'),
281 pjoin(parallel_scripts, 'ipcontroller'),
281 pjoin(parallel_scripts, 'ipcluster'),
282 pjoin(parallel_scripts, 'ipcluster'),
282 pjoin(parallel_scripts, 'iplogger'),
283 pjoin(parallel_scripts, 'iplogger'),
283 pjoin(main_scripts, 'ipython'),
284 pjoin(main_scripts, 'ipython'),
284 pjoin(main_scripts, 'pycolor'),
285 pjoin(main_scripts, 'pycolor'),
285 pjoin(main_scripts, 'irunner'),
286 pjoin(main_scripts, 'irunner'),
286 pjoin(main_scripts, 'iptest')
287 pjoin(main_scripts, 'iptest')
287 ]
288 ]
288 return scripts
289 return scripts
289
290
290 #---------------------------------------------------------------------------
291 #---------------------------------------------------------------------------
291 # Verify all dependencies
292 # Verify all dependencies
292 #---------------------------------------------------------------------------
293 #---------------------------------------------------------------------------
293
294
294 def check_for_dependencies():
295 def check_for_dependencies():
295 """Check for IPython's dependencies.
296 """Check for IPython's dependencies.
296
297
297 This function should NOT be called if running under setuptools!
298 This function should NOT be called if running under setuptools!
298 """
299 """
299 from setupext.setupext import (
300 from setupext.setupext import (
300 print_line, print_raw, print_status,
301 print_line, print_raw, print_status,
301 check_for_sphinx, check_for_pygments,
302 check_for_sphinx, check_for_pygments,
302 check_for_nose, check_for_pexpect,
303 check_for_nose, check_for_pexpect,
303 check_for_pyzmq, check_for_readline
304 check_for_pyzmq, check_for_readline
304 )
305 )
305 print_line()
306 print_line()
306 print_raw("BUILDING IPYTHON")
307 print_raw("BUILDING IPYTHON")
307 print_status('python', sys.version)
308 print_status('python', sys.version)
308 print_status('platform', sys.platform)
309 print_status('platform', sys.platform)
309 if sys.platform == 'win32':
310 if sys.platform == 'win32':
310 print_status('Windows version', sys.getwindowsversion())
311 print_status('Windows version', sys.getwindowsversion())
311
312
312 print_raw("")
313 print_raw("")
313 print_raw("OPTIONAL DEPENDENCIES")
314 print_raw("OPTIONAL DEPENDENCIES")
314
315
315 check_for_sphinx()
316 check_for_sphinx()
316 check_for_pygments()
317 check_for_pygments()
317 check_for_nose()
318 check_for_nose()
318 check_for_pexpect()
319 check_for_pexpect()
319 check_for_pyzmq()
320 check_for_pyzmq()
320 check_for_readline()
321 check_for_readline()
321
322
322 def record_commit_info(pkg_dir, build_cmd=build_py):
323 def record_commit_info(pkg_dir, build_cmd=build_py):
323 """ Return extended build command class for recording commit
324 """ Return extended build command class for recording commit
324
325
325 The extended command tries to run git to find the current commit, getting
326 The extended command tries to run git to find the current commit, getting
326 the empty string if it fails. It then writes the commit hash into a file
327 the empty string if it fails. It then writes the commit hash into a file
327 in the `pkg_dir` path, named ``.git_commit_info.ini``.
328 in the `pkg_dir` path, named ``.git_commit_info.ini``.
328
329
329 In due course this information can be used by the package after it is
330 In due course this information can be used by the package after it is
330 installed, to tell you what commit it was installed from if known.
331 installed, to tell you what commit it was installed from if known.
331
332
332 To make use of this system, you need a package with a .git_commit_info.ini
333 To make use of this system, you need a package with a .git_commit_info.ini
333 file - e.g. ``myproject/.git_commit_info.ini`` - that might well look like
334 file - e.g. ``myproject/.git_commit_info.ini`` - that might well look like
334 this::
335 this::
335
336
336 # This is an ini file that may contain information about the code state
337 # This is an ini file that may contain information about the code state
337 [commit hash]
338 [commit hash]
338 # The line below may contain a valid hash if it has been substituted
339 # The line below may contain a valid hash if it has been substituted
339 # during 'git archive'
340 # during 'git archive'
340 archive_subst_hash=$Format:%h$
341 archive_subst_hash=$Format:%h$
341 # This line may be modified by the install process
342 # This line may be modified by the install process
342 install_hash=
343 install_hash=
343
344
344 The .git_commit_info file above is also designed to be used with git
345 The .git_commit_info file above is also designed to be used with git
345 substitution - so you probably also want a ``.gitattributes`` file in the
346 substitution - so you probably also want a ``.gitattributes`` file in the
346 root directory of your working tree that contains something like this::
347 root directory of your working tree that contains something like this::
347
348
348 myproject/.git_commit_info.ini export-subst
349 myproject/.git_commit_info.ini export-subst
349
350
350 That will cause the ``.git_commit_info.ini`` file to get filled in by ``git
351 That will cause the ``.git_commit_info.ini`` file to get filled in by ``git
351 archive`` - useful in case someone makes such an archive - for example with
352 archive`` - useful in case someone makes such an archive - for example with
352 via the github 'download source' button.
353 via the github 'download source' button.
353
354
354 Although all the above will work as is, you might consider having something
355 Although all the above will work as is, you might consider having something
355 like a ``get_info()`` function in your package to display the commit
356 like a ``get_info()`` function in your package to display the commit
356 information at the terminal. See the ``pkg_info.py`` module in the nipy
357 information at the terminal. See the ``pkg_info.py`` module in the nipy
357 package for an example.
358 package for an example.
358 """
359 """
359 class MyBuildPy(build_cmd):
360 class MyBuildPy(build_cmd):
360 ''' Subclass to write commit data into installation tree '''
361 ''' Subclass to write commit data into installation tree '''
361 def run(self):
362 def run(self):
362 build_cmd.run(self)
363 build_cmd.run(self)
363 import subprocess
364 import subprocess
364 proc = subprocess.Popen('git rev-parse --short HEAD',
365 proc = subprocess.Popen('git rev-parse --short HEAD',
365 stdout=subprocess.PIPE,
366 stdout=subprocess.PIPE,
366 stderr=subprocess.PIPE,
367 stderr=subprocess.PIPE,
367 shell=True)
368 shell=True)
368 repo_commit, _ = proc.communicate()
369 repo_commit, _ = proc.communicate()
369 # We write the installation commit even if it's empty
370 # We write the installation commit even if it's empty
370 cfg_parser = ConfigParser()
371 cfg_parser = ConfigParser()
371 cfg_parser.read(pjoin(pkg_dir, '.git_commit_info.ini'))
372 cfg_parser.read(pjoin(pkg_dir, '.git_commit_info.ini'))
372 cfg_parser.set('commit hash', 'install_hash', repo_commit.decode('ascii'))
373 cfg_parser.set('commit hash', 'install_hash', repo_commit.decode('ascii'))
373 out_pth = pjoin(self.build_lib, pkg_dir, '.git_commit_info.ini')
374 out_pth = pjoin(self.build_lib, pkg_dir, '.git_commit_info.ini')
374 out_file = open(out_pth, 'wt')
375 out_file = open(out_pth, 'wt')
375 cfg_parser.write(out_file)
376 cfg_parser.write(out_file)
376 out_file.close()
377 out_file.close()
377 return MyBuildPy
378 return MyBuildPy
General Comments 0
You need to be logged in to leave comments. Login now