##// END OF EJS Templates
Fix manpage path in FreeBSD...
Po-Chuan Hsieh -
Show More
@@ -1,404 +1,407 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
11
12 # Copyright (c) IPython Development Team.
12 # Copyright (c) IPython Development Team.
13 # Distributed under the terms of the Modified BSD License.
13 # Distributed under the terms of the Modified BSD License.
14
14
15
15
16 import re
16 import re
17 import os
17 import os
18 import sys
18 import sys
19
19
20 from distutils import log
20 from distutils import log
21 from distutils.command.build_py import build_py
21 from distutils.command.build_py import build_py
22 from distutils.command.build_scripts import build_scripts
22 from distutils.command.build_scripts import build_scripts
23 from distutils.command.install import install
23 from distutils.command.install import install
24 from distutils.command.install_scripts import install_scripts
24 from distutils.command.install_scripts import install_scripts
25 from distutils.cmd import Command
25 from distutils.cmd import Command
26 from glob import glob
26 from glob import glob
27
27
28 from setupext import install_data_ext
28 from setupext import install_data_ext
29
29
30 #-------------------------------------------------------------------------------
30 #-------------------------------------------------------------------------------
31 # Useful globals and utility functions
31 # Useful globals and utility functions
32 #-------------------------------------------------------------------------------
32 #-------------------------------------------------------------------------------
33
33
34 # A few handy globals
34 # A few handy globals
35 isfile = os.path.isfile
35 isfile = os.path.isfile
36 pjoin = os.path.join
36 pjoin = os.path.join
37 repo_root = os.path.dirname(os.path.abspath(__file__))
37 repo_root = os.path.dirname(os.path.abspath(__file__))
38
38
39 def execfile(fname, globs, locs=None):
39 def execfile(fname, globs, locs=None):
40 locs = locs or globs
40 locs = locs or globs
41 with open(fname) as f:
41 with open(fname) as f:
42 exec(compile(f.read(), fname, "exec"), globs, locs)
42 exec(compile(f.read(), fname, "exec"), globs, locs)
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(repo_root, 'IPython','core','release.py'), globals())
61 execfile(pjoin(repo_root, 'IPython','core','release.py'), globals())
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 license = license,
73 license = license,
74 platforms = platforms,
74 platforms = platforms,
75 keywords = keywords,
75 keywords = keywords,
76 classifiers = classifiers,
76 classifiers = classifiers,
77 cmdclass = {'install_data': install_data_ext},
77 cmdclass = {'install_data': install_data_ext},
78 project_urls={
78 project_urls={
79 'Documentation': 'https://ipython.readthedocs.io/',
79 'Documentation': 'https://ipython.readthedocs.io/',
80 'Funding' : 'https://numfocus.org/',
80 'Funding' : 'https://numfocus.org/',
81 'Source' : 'https://github.com/ipython/ipython',
81 'Source' : 'https://github.com/ipython/ipython',
82 'Tracker' : 'https://github.com/ipython/ipython/issues',
82 'Tracker' : 'https://github.com/ipython/ipython/issues',
83 }
83 }
84 )
84 )
85
85
86
86
87 #---------------------------------------------------------------------------
87 #---------------------------------------------------------------------------
88 # Find packages
88 # Find packages
89 #---------------------------------------------------------------------------
89 #---------------------------------------------------------------------------
90
90
91 def find_packages():
91 def find_packages():
92 """
92 """
93 Find all of IPython's packages.
93 Find all of IPython's packages.
94 """
94 """
95 excludes = ['deathrow', 'quarantine']
95 excludes = ['deathrow', 'quarantine']
96 packages = []
96 packages = []
97 for dir,subdirs,files in os.walk('IPython'):
97 for dir,subdirs,files in os.walk('IPython'):
98 package = dir.replace(os.path.sep, '.')
98 package = dir.replace(os.path.sep, '.')
99 if any(package.startswith('IPython.'+exc) for exc in excludes):
99 if any(package.startswith('IPython.'+exc) for exc in excludes):
100 # package is to be excluded (e.g. deathrow)
100 # package is to be excluded (e.g. deathrow)
101 continue
101 continue
102 if '__init__.py' not in files:
102 if '__init__.py' not in files:
103 # not a package
103 # not a package
104 continue
104 continue
105 packages.append(package)
105 packages.append(package)
106 return packages
106 return packages
107
107
108 #---------------------------------------------------------------------------
108 #---------------------------------------------------------------------------
109 # Find package data
109 # Find package data
110 #---------------------------------------------------------------------------
110 #---------------------------------------------------------------------------
111
111
112 def find_package_data():
112 def find_package_data():
113 """
113 """
114 Find IPython's package_data.
114 Find IPython's package_data.
115 """
115 """
116 # This is not enough for these things to appear in an sdist.
116 # This is not enough for these things to appear in an sdist.
117 # We need to muck with the MANIFEST to get this to work
117 # We need to muck with the MANIFEST to get this to work
118
118
119 package_data = {
119 package_data = {
120 'IPython.core' : ['profile/README*'],
120 'IPython.core' : ['profile/README*'],
121 'IPython.core.tests' : ['*.png', '*.jpg', 'daft_extension/*.py'],
121 'IPython.core.tests' : ['*.png', '*.jpg', 'daft_extension/*.py'],
122 'IPython.lib.tests' : ['*.wav'],
122 'IPython.lib.tests' : ['*.wav'],
123 'IPython.testing.plugin' : ['*.txt'],
123 'IPython.testing.plugin' : ['*.txt'],
124 }
124 }
125
125
126 return package_data
126 return package_data
127
127
128
128
129 def check_package_data(package_data):
129 def check_package_data(package_data):
130 """verify that package_data globs make sense"""
130 """verify that package_data globs make sense"""
131 print("checking package data")
131 print("checking package data")
132 for pkg, data in package_data.items():
132 for pkg, data in package_data.items():
133 pkg_root = pjoin(*pkg.split('.'))
133 pkg_root = pjoin(*pkg.split('.'))
134 for d in data:
134 for d in data:
135 path = pjoin(pkg_root, d)
135 path = pjoin(pkg_root, d)
136 if '*' in path:
136 if '*' in path:
137 assert len(glob(path)) > 0, "No files match pattern %s" % path
137 assert len(glob(path)) > 0, "No files match pattern %s" % path
138 else:
138 else:
139 assert os.path.exists(path), "Missing package data: %s" % path
139 assert os.path.exists(path), "Missing package data: %s" % path
140
140
141
141
142 def check_package_data_first(command):
142 def check_package_data_first(command):
143 """decorator for checking package_data before running a given command
143 """decorator for checking package_data before running a given command
144
144
145 Probably only needs to wrap build_py
145 Probably only needs to wrap build_py
146 """
146 """
147 class DecoratedCommand(command):
147 class DecoratedCommand(command):
148 def run(self):
148 def run(self):
149 check_package_data(self.package_data)
149 check_package_data(self.package_data)
150 command.run(self)
150 command.run(self)
151 return DecoratedCommand
151 return DecoratedCommand
152
152
153
153
154 #---------------------------------------------------------------------------
154 #---------------------------------------------------------------------------
155 # Find data files
155 # Find data files
156 #---------------------------------------------------------------------------
156 #---------------------------------------------------------------------------
157
157
158 def find_data_files():
158 def find_data_files():
159 """
159 """
160 Find IPython's data_files.
160 Find IPython's data_files.
161
161
162 Just man pages at this point.
162 Just man pages at this point.
163 """
163 """
164
164
165 manpagebase = pjoin('share', 'man', 'man1')
165 if "freebsd" in sys.platform:
166 manpagebase = pjoin('man', 'man1')
167 else:
168 manpagebase = pjoin('share', 'man', 'man1')
166
169
167 # Simple file lists can be made by hand
170 # Simple file lists can be made by hand
168 manpages = [f for f in glob(pjoin('docs','man','*.1.gz')) if isfile(f)]
171 manpages = [f for f in glob(pjoin('docs','man','*.1.gz')) if isfile(f)]
169 if not manpages:
172 if not manpages:
170 # When running from a source tree, the manpages aren't gzipped
173 # When running from a source tree, the manpages aren't gzipped
171 manpages = [f for f in glob(pjoin('docs','man','*.1')) if isfile(f)]
174 manpages = [f for f in glob(pjoin('docs','man','*.1')) if isfile(f)]
172
175
173 # And assemble the entire output list
176 # And assemble the entire output list
174 data_files = [ (manpagebase, manpages) ]
177 data_files = [ (manpagebase, manpages) ]
175
178
176 return data_files
179 return data_files
177
180
178
181
179 # The two functions below are copied from IPython.utils.path, so we don't need
182 # The two functions below are copied from IPython.utils.path, so we don't need
180 # to import IPython during setup, which fails on Python 3.
183 # to import IPython during setup, which fails on Python 3.
181
184
182 def target_outdated(target,deps):
185 def target_outdated(target,deps):
183 """Determine whether a target is out of date.
186 """Determine whether a target is out of date.
184
187
185 target_outdated(target,deps) -> 1/0
188 target_outdated(target,deps) -> 1/0
186
189
187 deps: list of filenames which MUST exist.
190 deps: list of filenames which MUST exist.
188 target: single filename which may or may not exist.
191 target: single filename which may or may not exist.
189
192
190 If target doesn't exist or is older than any file listed in deps, return
193 If target doesn't exist or is older than any file listed in deps, return
191 true, otherwise return false.
194 true, otherwise return false.
192 """
195 """
193 try:
196 try:
194 target_time = os.path.getmtime(target)
197 target_time = os.path.getmtime(target)
195 except os.error:
198 except os.error:
196 return 1
199 return 1
197 for dep in deps:
200 for dep in deps:
198 dep_time = os.path.getmtime(dep)
201 dep_time = os.path.getmtime(dep)
199 if dep_time > target_time:
202 if dep_time > target_time:
200 #print "For target",target,"Dep failed:",dep # dbg
203 #print "For target",target,"Dep failed:",dep # dbg
201 #print "times (dep,tar):",dep_time,target_time # dbg
204 #print "times (dep,tar):",dep_time,target_time # dbg
202 return 1
205 return 1
203 return 0
206 return 0
204
207
205
208
206 def target_update(target,deps,cmd):
209 def target_update(target,deps,cmd):
207 """Update a target with a given command given a list of dependencies.
210 """Update a target with a given command given a list of dependencies.
208
211
209 target_update(target,deps,cmd) -> runs cmd if target is outdated.
212 target_update(target,deps,cmd) -> runs cmd if target is outdated.
210
213
211 This is just a wrapper around target_outdated() which calls the given
214 This is just a wrapper around target_outdated() which calls the given
212 command if target is outdated."""
215 command if target is outdated."""
213
216
214 if target_outdated(target,deps):
217 if target_outdated(target,deps):
215 os.system(cmd)
218 os.system(cmd)
216
219
217 #---------------------------------------------------------------------------
220 #---------------------------------------------------------------------------
218 # Find scripts
221 # Find scripts
219 #---------------------------------------------------------------------------
222 #---------------------------------------------------------------------------
220
223
221 def find_entry_points():
224 def find_entry_points():
222 """Defines the command line entry points for IPython
225 """Defines the command line entry points for IPython
223
226
224 This always uses setuptools-style entry points. When setuptools is not in
227 This always uses setuptools-style entry points. When setuptools is not in
225 use, our own build_scripts_entrypt class below parses these and builds
228 use, our own build_scripts_entrypt class below parses these and builds
226 command line scripts.
229 command line scripts.
227
230
228 Each of our entry points gets both a plain name, e.g. ipython, and one
231 Each of our entry points gets both a plain name, e.g. ipython, and one
229 suffixed with the Python major version number, e.g. ipython3.
232 suffixed with the Python major version number, e.g. ipython3.
230 """
233 """
231 ep = [
234 ep = [
232 'ipython%s = IPython:start_ipython',
235 'ipython%s = IPython:start_ipython',
233 'iptest%s = IPython.testing.iptestcontroller:main',
236 'iptest%s = IPython.testing.iptestcontroller:main',
234 ]
237 ]
235 suffix = str(sys.version_info[0])
238 suffix = str(sys.version_info[0])
236 return [e % '' for e in ep] + [e % suffix for e in ep]
239 return [e % '' for e in ep] + [e % suffix for e in ep]
237
240
238 script_src = """#!{executable}
241 script_src = """#!{executable}
239 # This script was automatically generated by setup.py
242 # This script was automatically generated by setup.py
240 if __name__ == '__main__':
243 if __name__ == '__main__':
241 from {mod} import {func}
244 from {mod} import {func}
242 {func}()
245 {func}()
243 """
246 """
244
247
245 class build_scripts_entrypt(build_scripts):
248 class build_scripts_entrypt(build_scripts):
246 """Build the command line scripts
249 """Build the command line scripts
247
250
248 Parse setuptools style entry points and write simple scripts to run the
251 Parse setuptools style entry points and write simple scripts to run the
249 target functions.
252 target functions.
250
253
251 On Windows, this also creates .cmd wrappers for the scripts so that you can
254 On Windows, this also creates .cmd wrappers for the scripts so that you can
252 easily launch them from a command line.
255 easily launch them from a command line.
253 """
256 """
254 def run(self):
257 def run(self):
255 self.mkpath(self.build_dir)
258 self.mkpath(self.build_dir)
256 outfiles = []
259 outfiles = []
257 for script in find_entry_points():
260 for script in find_entry_points():
258 name, entrypt = script.split('=')
261 name, entrypt = script.split('=')
259 name = name.strip()
262 name = name.strip()
260 entrypt = entrypt.strip()
263 entrypt = entrypt.strip()
261 outfile = os.path.join(self.build_dir, name)
264 outfile = os.path.join(self.build_dir, name)
262 outfiles.append(outfile)
265 outfiles.append(outfile)
263 print('Writing script to', outfile)
266 print('Writing script to', outfile)
264
267
265 mod, func = entrypt.split(':')
268 mod, func = entrypt.split(':')
266 with open(outfile, 'w') as f:
269 with open(outfile, 'w') as f:
267 f.write(script_src.format(executable=sys.executable,
270 f.write(script_src.format(executable=sys.executable,
268 mod=mod, func=func))
271 mod=mod, func=func))
269
272
270 if sys.platform == 'win32':
273 if sys.platform == 'win32':
271 # Write .cmd wrappers for Windows so 'ipython' etc. work at the
274 # Write .cmd wrappers for Windows so 'ipython' etc. work at the
272 # command line
275 # command line
273 cmd_file = os.path.join(self.build_dir, name + '.cmd')
276 cmd_file = os.path.join(self.build_dir, name + '.cmd')
274 cmd = r'@"{python}" "%~dp0\{script}" %*\r\n'.format(
277 cmd = r'@"{python}" "%~dp0\{script}" %*\r\n'.format(
275 python=sys.executable, script=name)
278 python=sys.executable, script=name)
276 log.info("Writing %s wrapper script" % cmd_file)
279 log.info("Writing %s wrapper script" % cmd_file)
277 with open(cmd_file, 'w') as f:
280 with open(cmd_file, 'w') as f:
278 f.write(cmd)
281 f.write(cmd)
279
282
280 return outfiles, outfiles
283 return outfiles, outfiles
281
284
282 class install_lib_symlink(Command):
285 class install_lib_symlink(Command):
283 user_options = [
286 user_options = [
284 ('install-dir=', 'd', "directory to install to"),
287 ('install-dir=', 'd', "directory to install to"),
285 ]
288 ]
286
289
287 def initialize_options(self):
290 def initialize_options(self):
288 self.install_dir = None
291 self.install_dir = None
289
292
290 def finalize_options(self):
293 def finalize_options(self):
291 self.set_undefined_options('symlink',
294 self.set_undefined_options('symlink',
292 ('install_lib', 'install_dir'),
295 ('install_lib', 'install_dir'),
293 )
296 )
294
297
295 def run(self):
298 def run(self):
296 if sys.platform == 'win32':
299 if sys.platform == 'win32':
297 raise Exception("This doesn't work on Windows.")
300 raise Exception("This doesn't work on Windows.")
298 pkg = os.path.join(os.getcwd(), 'IPython')
301 pkg = os.path.join(os.getcwd(), 'IPython')
299 dest = os.path.join(self.install_dir, 'IPython')
302 dest = os.path.join(self.install_dir, 'IPython')
300 if os.path.islink(dest):
303 if os.path.islink(dest):
301 print('removing existing symlink at %s' % dest)
304 print('removing existing symlink at %s' % dest)
302 os.unlink(dest)
305 os.unlink(dest)
303 print('symlinking %s -> %s' % (pkg, dest))
306 print('symlinking %s -> %s' % (pkg, dest))
304 os.symlink(pkg, dest)
307 os.symlink(pkg, dest)
305
308
306 class unsymlink(install):
309 class unsymlink(install):
307 def run(self):
310 def run(self):
308 dest = os.path.join(self.install_lib, 'IPython')
311 dest = os.path.join(self.install_lib, 'IPython')
309 if os.path.islink(dest):
312 if os.path.islink(dest):
310 print('removing symlink at %s' % dest)
313 print('removing symlink at %s' % dest)
311 os.unlink(dest)
314 os.unlink(dest)
312 else:
315 else:
313 print('No symlink exists at %s' % dest)
316 print('No symlink exists at %s' % dest)
314
317
315 class install_symlinked(install):
318 class install_symlinked(install):
316 def run(self):
319 def run(self):
317 if sys.platform == 'win32':
320 if sys.platform == 'win32':
318 raise Exception("This doesn't work on Windows.")
321 raise Exception("This doesn't work on Windows.")
319
322
320 # Run all sub-commands (at least those that need to be run)
323 # Run all sub-commands (at least those that need to be run)
321 for cmd_name in self.get_sub_commands():
324 for cmd_name in self.get_sub_commands():
322 self.run_command(cmd_name)
325 self.run_command(cmd_name)
323
326
324 # 'sub_commands': a list of commands this command might have to run to
327 # 'sub_commands': a list of commands this command might have to run to
325 # get its work done. See cmd.py for more info.
328 # get its work done. See cmd.py for more info.
326 sub_commands = [('install_lib_symlink', lambda self:True),
329 sub_commands = [('install_lib_symlink', lambda self:True),
327 ('install_scripts_sym', lambda self:True),
330 ('install_scripts_sym', lambda self:True),
328 ]
331 ]
329
332
330 class install_scripts_for_symlink(install_scripts):
333 class install_scripts_for_symlink(install_scripts):
331 """Redefined to get options from 'symlink' instead of 'install'.
334 """Redefined to get options from 'symlink' instead of 'install'.
332
335
333 I love distutils almost as much as I love setuptools.
336 I love distutils almost as much as I love setuptools.
334 """
337 """
335 def finalize_options(self):
338 def finalize_options(self):
336 self.set_undefined_options('build', ('build_scripts', 'build_dir'))
339 self.set_undefined_options('build', ('build_scripts', 'build_dir'))
337 self.set_undefined_options('symlink',
340 self.set_undefined_options('symlink',
338 ('install_scripts', 'install_dir'),
341 ('install_scripts', 'install_dir'),
339 ('force', 'force'),
342 ('force', 'force'),
340 ('skip_build', 'skip_build'),
343 ('skip_build', 'skip_build'),
341 )
344 )
342
345
343
346
344 #---------------------------------------------------------------------------
347 #---------------------------------------------------------------------------
345 # VCS related
348 # VCS related
346 #---------------------------------------------------------------------------
349 #---------------------------------------------------------------------------
347
350
348
351
349 def git_prebuild(pkg_dir, build_cmd=build_py):
352 def git_prebuild(pkg_dir, build_cmd=build_py):
350 """Return extended build or sdist command class for recording commit
353 """Return extended build or sdist command class for recording commit
351
354
352 records git commit in IPython.utils._sysinfo.commit
355 records git commit in IPython.utils._sysinfo.commit
353
356
354 for use in IPython.utils.sysinfo.sys_info() calls after installation.
357 for use in IPython.utils.sysinfo.sys_info() calls after installation.
355 """
358 """
356
359
357 class MyBuildPy(build_cmd):
360 class MyBuildPy(build_cmd):
358 ''' Subclass to write commit data into installation tree '''
361 ''' Subclass to write commit data into installation tree '''
359 def run(self):
362 def run(self):
360 # loose as `.dev` is suppose to be invalid
363 # loose as `.dev` is suppose to be invalid
361 print("check version number")
364 print("check version number")
362 loose_pep440re = re.compile(r'^(\d+)\.(\d+)\.(\d+((a|b|rc)\d+)?)(\.post\d+)?(\.dev\d*)?$')
365 loose_pep440re = re.compile(r'^(\d+)\.(\d+)\.(\d+((a|b|rc)\d+)?)(\.post\d+)?(\.dev\d*)?$')
363 if not loose_pep440re.match(version):
366 if not loose_pep440re.match(version):
364 raise ValueError("Version number '%s' is not valid (should match [N!]N(.N)*[{a|b|rc}N][.postN][.devN])" % version)
367 raise ValueError("Version number '%s' is not valid (should match [N!]N(.N)*[{a|b|rc}N][.postN][.devN])" % version)
365
368
366
369
367 build_cmd.run(self)
370 build_cmd.run(self)
368 # this one will only fire for build commands
371 # this one will only fire for build commands
369 if hasattr(self, 'build_lib'):
372 if hasattr(self, 'build_lib'):
370 self._record_commit(self.build_lib)
373 self._record_commit(self.build_lib)
371
374
372 def make_release_tree(self, base_dir, files):
375 def make_release_tree(self, base_dir, files):
373 # this one will fire for sdist
376 # this one will fire for sdist
374 build_cmd.make_release_tree(self, base_dir, files)
377 build_cmd.make_release_tree(self, base_dir, files)
375 self._record_commit(base_dir)
378 self._record_commit(base_dir)
376
379
377 def _record_commit(self, base_dir):
380 def _record_commit(self, base_dir):
378 import subprocess
381 import subprocess
379 proc = subprocess.Popen('git rev-parse --short HEAD',
382 proc = subprocess.Popen('git rev-parse --short HEAD',
380 stdout=subprocess.PIPE,
383 stdout=subprocess.PIPE,
381 stderr=subprocess.PIPE,
384 stderr=subprocess.PIPE,
382 shell=True)
385 shell=True)
383 repo_commit, _ = proc.communicate()
386 repo_commit, _ = proc.communicate()
384 repo_commit = repo_commit.strip().decode("ascii")
387 repo_commit = repo_commit.strip().decode("ascii")
385
388
386 out_pth = pjoin(base_dir, pkg_dir, 'utils', '_sysinfo.py')
389 out_pth = pjoin(base_dir, pkg_dir, 'utils', '_sysinfo.py')
387 if os.path.isfile(out_pth) and not repo_commit:
390 if os.path.isfile(out_pth) and not repo_commit:
388 # nothing to write, don't clobber
391 # nothing to write, don't clobber
389 return
392 return
390
393
391 print("writing git commit '%s' to %s" % (repo_commit, out_pth))
394 print("writing git commit '%s' to %s" % (repo_commit, out_pth))
392
395
393 # remove to avoid overwriting original via hard link
396 # remove to avoid overwriting original via hard link
394 try:
397 try:
395 os.remove(out_pth)
398 os.remove(out_pth)
396 except (IOError, OSError):
399 except (IOError, OSError):
397 pass
400 pass
398 with open(out_pth, 'w') as out_file:
401 with open(out_pth, 'w') as out_file:
399 out_file.writelines([
402 out_file.writelines([
400 '# GENERATED BY setup.py\n',
403 '# GENERATED BY setup.py\n',
401 'commit = u"%s"\n' % repo_commit,
404 'commit = u"%s"\n' % repo_commit,
402 ])
405 ])
403 return MyBuildPy
406 return MyBuildPy
404
407
General Comments 0
You need to be logged in to leave comments. Login now