##// END OF EJS Templates
setupbase.py (find_packages): Unused, remove
Matthias Koeppe -
Show More
@@ -1,332 +1,310 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 import os
15 import os
16 import re
16 import re
17 import sys
17 import sys
18 from glob import glob
18 from glob import glob
19 from logging import log
19 from logging import log
20
20
21 from setuptools import Command
21 from setuptools import Command
22 from setuptools.command.build_py import build_py
22 from setuptools.command.build_py import build_py
23
23
24 from setuptools.command.install import install
24 from setuptools.command.install import install
25 from setuptools.command.install_scripts import install_scripts
25 from setuptools.command.install_scripts import install_scripts
26
26
27
27
28 #-------------------------------------------------------------------------------
28 #-------------------------------------------------------------------------------
29 # Useful globals and utility functions
29 # Useful globals and utility functions
30 #-------------------------------------------------------------------------------
30 #-------------------------------------------------------------------------------
31
31
32 # A few handy globals
32 # A few handy globals
33 isfile = os.path.isfile
33 isfile = os.path.isfile
34 pjoin = os.path.join
34 pjoin = os.path.join
35 repo_root = os.path.dirname(os.path.abspath(__file__))
35 repo_root = os.path.dirname(os.path.abspath(__file__))
36
36
37 def execfile(fname, globs, locs=None):
37 def execfile(fname, globs, locs=None):
38 locs = locs or globs
38 locs = locs or globs
39 with open(fname, encoding="utf-8") as f:
39 with open(fname, encoding="utf-8") as f:
40 exec(compile(f.read(), fname, "exec"), globs, locs)
40 exec(compile(f.read(), fname, "exec"), globs, locs)
41
41
42 # A little utility we'll need below, since glob() does NOT allow you to do
42 # A little utility we'll need below, since glob() does NOT allow you to do
43 # exclusion on multiple endings!
43 # exclusion on multiple endings!
44 def file_doesnt_endwith(test,endings):
44 def file_doesnt_endwith(test,endings):
45 """Return true if test is a file and its name does NOT end with any
45 """Return true if test is a file and its name does NOT end with any
46 of the strings listed in endings."""
46 of the strings listed in endings."""
47 if not isfile(test):
47 if not isfile(test):
48 return False
48 return False
49 for e in endings:
49 for e in endings:
50 if test.endswith(e):
50 if test.endswith(e):
51 return False
51 return False
52 return True
52 return True
53
53
54 #---------------------------------------------------------------------------
54 #---------------------------------------------------------------------------
55 # Basic project information
55 # Basic project information
56 #---------------------------------------------------------------------------
56 #---------------------------------------------------------------------------
57
57
58 # release.py contains version, authors, license, url, keywords, etc.
58 # release.py contains version, authors, license, url, keywords, etc.
59 execfile(pjoin(repo_root, 'IPython','core','release.py'), globals())
59 execfile(pjoin(repo_root, 'IPython','core','release.py'), globals())
60
60
61 # Create a dict with the basic information
61 # Create a dict with the basic information
62 # This dict is eventually passed to setup after additional keys are added.
62 # This dict is eventually passed to setup after additional keys are added.
63 setup_args = dict(
63 setup_args = dict(
64 author = author,
64 author = author,
65 author_email = author_email,
65 author_email = author_email,
66 license = license,
66 license = license,
67 )
67 )
68
68
69
70 #---------------------------------------------------------------------------
71 # Find packages
72 #---------------------------------------------------------------------------
73
74 def find_packages():
75 """
76 Find all of IPython's packages.
77 """
78 excludes = ['deathrow', 'quarantine']
79 packages = []
80 for directory, subdirs, files in os.walk("IPython"):
81 package = directory.replace(os.path.sep, ".")
82 if any(package.startswith("IPython." + exc) for exc in excludes):
83 # package is to be excluded (e.g. deathrow)
84 continue
85 if '__init__.py' not in files:
86 # not a package
87 continue
88 packages.append(package)
89 return packages
90
91 #---------------------------------------------------------------------------
69 #---------------------------------------------------------------------------
92 # Check package data
70 # Check package data
93 #---------------------------------------------------------------------------
71 #---------------------------------------------------------------------------
94
72
95 def check_package_data(package_data):
73 def check_package_data(package_data):
96 """verify that package_data globs make sense"""
74 """verify that package_data globs make sense"""
97 print("checking package data")
75 print("checking package data")
98 for pkg, data in package_data.items():
76 for pkg, data in package_data.items():
99 pkg_root = pjoin(*pkg.split('.'))
77 pkg_root = pjoin(*pkg.split('.'))
100 for d in data:
78 for d in data:
101 path = pjoin(pkg_root, d)
79 path = pjoin(pkg_root, d)
102 if '*' in path:
80 if '*' in path:
103 assert len(glob(path)) > 0, "No files match pattern %s" % path
81 assert len(glob(path)) > 0, "No files match pattern %s" % path
104 else:
82 else:
105 assert os.path.exists(path), "Missing package data: %s" % path
83 assert os.path.exists(path), "Missing package data: %s" % path
106
84
107
85
108 def check_package_data_first(command):
86 def check_package_data_first(command):
109 """decorator for checking package_data before running a given command
87 """decorator for checking package_data before running a given command
110
88
111 Probably only needs to wrap build_py
89 Probably only needs to wrap build_py
112 """
90 """
113 class DecoratedCommand(command):
91 class DecoratedCommand(command):
114 def run(self):
92 def run(self):
115 check_package_data(self.package_data)
93 check_package_data(self.package_data)
116 command.run(self)
94 command.run(self)
117 return DecoratedCommand
95 return DecoratedCommand
118
96
119
97
120 #---------------------------------------------------------------------------
98 #---------------------------------------------------------------------------
121 # Find data files
99 # Find data files
122 #---------------------------------------------------------------------------
100 #---------------------------------------------------------------------------
123
101
124 def find_data_files():
102 def find_data_files():
125 """
103 """
126 Find IPython's data_files.
104 Find IPython's data_files.
127
105
128 Just man pages at this point.
106 Just man pages at this point.
129 """
107 """
130
108
131 if "freebsd" in sys.platform:
109 if "freebsd" in sys.platform:
132 manpagebase = pjoin('man', 'man1')
110 manpagebase = pjoin('man', 'man1')
133 else:
111 else:
134 manpagebase = pjoin('share', 'man', 'man1')
112 manpagebase = pjoin('share', 'man', 'man1')
135
113
136 # Simple file lists can be made by hand
114 # Simple file lists can be made by hand
137 manpages = [f for f in glob(pjoin('docs','man','*.1.gz')) if isfile(f)]
115 manpages = [f for f in glob(pjoin('docs','man','*.1.gz')) if isfile(f)]
138 if not manpages:
116 if not manpages:
139 # When running from a source tree, the manpages aren't gzipped
117 # When running from a source tree, the manpages aren't gzipped
140 manpages = [f for f in glob(pjoin('docs','man','*.1')) if isfile(f)]
118 manpages = [f for f in glob(pjoin('docs','man','*.1')) if isfile(f)]
141
119
142 # And assemble the entire output list
120 # And assemble the entire output list
143 data_files = [ (manpagebase, manpages) ]
121 data_files = [ (manpagebase, manpages) ]
144
122
145 return data_files
123 return data_files
146
124
147
125
148 # The two functions below are copied from IPython.utils.path, so we don't need
126 # The two functions below are copied from IPython.utils.path, so we don't need
149 # to import IPython during setup, which fails on Python 3.
127 # to import IPython during setup, which fails on Python 3.
150
128
151 def target_outdated(target,deps):
129 def target_outdated(target,deps):
152 """Determine whether a target is out of date.
130 """Determine whether a target is out of date.
153
131
154 target_outdated(target,deps) -> 1/0
132 target_outdated(target,deps) -> 1/0
155
133
156 deps: list of filenames which MUST exist.
134 deps: list of filenames which MUST exist.
157 target: single filename which may or may not exist.
135 target: single filename which may or may not exist.
158
136
159 If target doesn't exist or is older than any file listed in deps, return
137 If target doesn't exist or is older than any file listed in deps, return
160 true, otherwise return false.
138 true, otherwise return false.
161 """
139 """
162 try:
140 try:
163 target_time = os.path.getmtime(target)
141 target_time = os.path.getmtime(target)
164 except os.error:
142 except os.error:
165 return 1
143 return 1
166 for dep in deps:
144 for dep in deps:
167 dep_time = os.path.getmtime(dep)
145 dep_time = os.path.getmtime(dep)
168 if dep_time > target_time:
146 if dep_time > target_time:
169 #print "For target",target,"Dep failed:",dep # dbg
147 #print "For target",target,"Dep failed:",dep # dbg
170 #print "times (dep,tar):",dep_time,target_time # dbg
148 #print "times (dep,tar):",dep_time,target_time # dbg
171 return 1
149 return 1
172 return 0
150 return 0
173
151
174
152
175 def target_update(target,deps,cmd):
153 def target_update(target,deps,cmd):
176 """Update a target with a given command given a list of dependencies.
154 """Update a target with a given command given a list of dependencies.
177
155
178 target_update(target,deps,cmd) -> runs cmd if target is outdated.
156 target_update(target,deps,cmd) -> runs cmd if target is outdated.
179
157
180 This is just a wrapper around target_outdated() which calls the given
158 This is just a wrapper around target_outdated() which calls the given
181 command if target is outdated."""
159 command if target is outdated."""
182
160
183 if target_outdated(target,deps):
161 if target_outdated(target,deps):
184 os.system(cmd)
162 os.system(cmd)
185
163
186 #---------------------------------------------------------------------------
164 #---------------------------------------------------------------------------
187 # Find scripts
165 # Find scripts
188 #---------------------------------------------------------------------------
166 #---------------------------------------------------------------------------
189
167
190 def find_entry_points():
168 def find_entry_points():
191 """Defines the command line entry points for IPython
169 """Defines the command line entry points for IPython
192
170
193 This always uses setuptools-style entry points. When setuptools is not in
171 This always uses setuptools-style entry points. When setuptools is not in
194 use, our own build_scripts_entrypt class below parses these and builds
172 use, our own build_scripts_entrypt class below parses these and builds
195 command line scripts.
173 command line scripts.
196
174
197 Each of our entry points gets a plain name, e.g. ipython, and a name
175 Each of our entry points gets a plain name, e.g. ipython, and a name
198 suffixed with the Python major version number, e.g. ipython3.
176 suffixed with the Python major version number, e.g. ipython3.
199 """
177 """
200 ep = [
178 ep = [
201 'ipython%s = IPython:start_ipython',
179 'ipython%s = IPython:start_ipython',
202 ]
180 ]
203 major_suffix = str(sys.version_info[0])
181 major_suffix = str(sys.version_info[0])
204 return [e % "" for e in ep] + [e % major_suffix for e in ep]
182 return [e % "" for e in ep] + [e % major_suffix for e in ep]
205
183
206
184
207 class install_lib_symlink(Command):
185 class install_lib_symlink(Command):
208 user_options = [
186 user_options = [
209 ('install-dir=', 'd', "directory to install to"),
187 ('install-dir=', 'd', "directory to install to"),
210 ]
188 ]
211
189
212 def initialize_options(self):
190 def initialize_options(self):
213 self.install_dir = None
191 self.install_dir = None
214
192
215 def finalize_options(self):
193 def finalize_options(self):
216 self.set_undefined_options('symlink',
194 self.set_undefined_options('symlink',
217 ('install_lib', 'install_dir'),
195 ('install_lib', 'install_dir'),
218 )
196 )
219
197
220 def run(self):
198 def run(self):
221 if sys.platform == 'win32':
199 if sys.platform == 'win32':
222 raise Exception("This doesn't work on Windows.")
200 raise Exception("This doesn't work on Windows.")
223 pkg = os.path.join(os.getcwd(), 'IPython')
201 pkg = os.path.join(os.getcwd(), 'IPython')
224 dest = os.path.join(self.install_dir, 'IPython')
202 dest = os.path.join(self.install_dir, 'IPython')
225 if os.path.islink(dest):
203 if os.path.islink(dest):
226 print('removing existing symlink at %s' % dest)
204 print('removing existing symlink at %s' % dest)
227 os.unlink(dest)
205 os.unlink(dest)
228 print('symlinking %s -> %s' % (pkg, dest))
206 print('symlinking %s -> %s' % (pkg, dest))
229 os.symlink(pkg, dest)
207 os.symlink(pkg, dest)
230
208
231 class unsymlink(install):
209 class unsymlink(install):
232 def run(self):
210 def run(self):
233 dest = os.path.join(self.install_lib, 'IPython')
211 dest = os.path.join(self.install_lib, 'IPython')
234 if os.path.islink(dest):
212 if os.path.islink(dest):
235 print('removing symlink at %s' % dest)
213 print('removing symlink at %s' % dest)
236 os.unlink(dest)
214 os.unlink(dest)
237 else:
215 else:
238 print('No symlink exists at %s' % dest)
216 print('No symlink exists at %s' % dest)
239
217
240 class install_symlinked(install):
218 class install_symlinked(install):
241 def run(self):
219 def run(self):
242 if sys.platform == 'win32':
220 if sys.platform == 'win32':
243 raise Exception("This doesn't work on Windows.")
221 raise Exception("This doesn't work on Windows.")
244
222
245 # Run all sub-commands (at least those that need to be run)
223 # Run all sub-commands (at least those that need to be run)
246 for cmd_name in self.get_sub_commands():
224 for cmd_name in self.get_sub_commands():
247 self.run_command(cmd_name)
225 self.run_command(cmd_name)
248
226
249 # 'sub_commands': a list of commands this command might have to run to
227 # 'sub_commands': a list of commands this command might have to run to
250 # get its work done. See cmd.py for more info.
228 # get its work done. See cmd.py for more info.
251 sub_commands = [('install_lib_symlink', lambda self:True),
229 sub_commands = [('install_lib_symlink', lambda self:True),
252 ('install_scripts_sym', lambda self:True),
230 ('install_scripts_sym', lambda self:True),
253 ]
231 ]
254
232
255 class install_scripts_for_symlink(install_scripts):
233 class install_scripts_for_symlink(install_scripts):
256 """Redefined to get options from 'symlink' instead of 'install'.
234 """Redefined to get options from 'symlink' instead of 'install'.
257
235
258 I love distutils almost as much as I love setuptools.
236 I love distutils almost as much as I love setuptools.
259 """
237 """
260 def finalize_options(self):
238 def finalize_options(self):
261 self.set_undefined_options('build', ('build_scripts', 'build_dir'))
239 self.set_undefined_options('build', ('build_scripts', 'build_dir'))
262 self.set_undefined_options('symlink',
240 self.set_undefined_options('symlink',
263 ('install_scripts', 'install_dir'),
241 ('install_scripts', 'install_dir'),
264 ('force', 'force'),
242 ('force', 'force'),
265 ('skip_build', 'skip_build'),
243 ('skip_build', 'skip_build'),
266 )
244 )
267
245
268
246
269 #---------------------------------------------------------------------------
247 #---------------------------------------------------------------------------
270 # VCS related
248 # VCS related
271 #---------------------------------------------------------------------------
249 #---------------------------------------------------------------------------
272
250
273
251
274 def git_prebuild(pkg_dir, build_cmd=build_py):
252 def git_prebuild(pkg_dir, build_cmd=build_py):
275 """Return extended build or sdist command class for recording commit
253 """Return extended build or sdist command class for recording commit
276
254
277 records git commit in IPython.utils._sysinfo.commit
255 records git commit in IPython.utils._sysinfo.commit
278
256
279 for use in IPython.utils.sysinfo.sys_info() calls after installation.
257 for use in IPython.utils.sysinfo.sys_info() calls after installation.
280 """
258 """
281
259
282 class MyBuildPy(build_cmd):
260 class MyBuildPy(build_cmd):
283 ''' Subclass to write commit data into installation tree '''
261 ''' Subclass to write commit data into installation tree '''
284 def run(self):
262 def run(self):
285 # loose as `.dev` is suppose to be invalid
263 # loose as `.dev` is suppose to be invalid
286 print("check version number")
264 print("check version number")
287 loose_pep440re = re.compile(r'^(\d+)\.(\d+)\.(\d+((a|b|rc)\d+)?)(\.post\d+)?(\.dev\d*)?$')
265 loose_pep440re = re.compile(r'^(\d+)\.(\d+)\.(\d+((a|b|rc)\d+)?)(\.post\d+)?(\.dev\d*)?$')
288 if not loose_pep440re.match(version):
266 if not loose_pep440re.match(version):
289 raise ValueError("Version number '%s' is not valid (should match [N!]N(.N)*[{a|b|rc}N][.postN][.devN])" % version)
267 raise ValueError("Version number '%s' is not valid (should match [N!]N(.N)*[{a|b|rc}N][.postN][.devN])" % version)
290
268
291
269
292 build_cmd.run(self)
270 build_cmd.run(self)
293 # this one will only fire for build commands
271 # this one will only fire for build commands
294 if hasattr(self, 'build_lib'):
272 if hasattr(self, 'build_lib'):
295 self._record_commit(self.build_lib)
273 self._record_commit(self.build_lib)
296
274
297 def make_release_tree(self, base_dir, files):
275 def make_release_tree(self, base_dir, files):
298 # this one will fire for sdist
276 # this one will fire for sdist
299 build_cmd.make_release_tree(self, base_dir, files)
277 build_cmd.make_release_tree(self, base_dir, files)
300 self._record_commit(base_dir)
278 self._record_commit(base_dir)
301
279
302 def _record_commit(self, base_dir):
280 def _record_commit(self, base_dir):
303 import subprocess
281 import subprocess
304 proc = subprocess.Popen('git rev-parse --short HEAD',
282 proc = subprocess.Popen('git rev-parse --short HEAD',
305 stdout=subprocess.PIPE,
283 stdout=subprocess.PIPE,
306 stderr=subprocess.PIPE,
284 stderr=subprocess.PIPE,
307 shell=True)
285 shell=True)
308 repo_commit, _ = proc.communicate()
286 repo_commit, _ = proc.communicate()
309 repo_commit = repo_commit.strip().decode("ascii")
287 repo_commit = repo_commit.strip().decode("ascii")
310
288
311 out_pth = pjoin(base_dir, pkg_dir, 'utils', '_sysinfo.py')
289 out_pth = pjoin(base_dir, pkg_dir, 'utils', '_sysinfo.py')
312 if os.path.isfile(out_pth) and not repo_commit:
290 if os.path.isfile(out_pth) and not repo_commit:
313 # nothing to write, don't clobber
291 # nothing to write, don't clobber
314 return
292 return
315
293
316 print("writing git commit '%s' to %s" % (repo_commit, out_pth))
294 print("writing git commit '%s' to %s" % (repo_commit, out_pth))
317
295
318 # remove to avoid overwriting original via hard link
296 # remove to avoid overwriting original via hard link
319 try:
297 try:
320 os.remove(out_pth)
298 os.remove(out_pth)
321 except (IOError, OSError):
299 except (IOError, OSError):
322 pass
300 pass
323 with open(out_pth, "w", encoding="utf-8") as out_file:
301 with open(out_pth, "w", encoding="utf-8") as out_file:
324 out_file.writelines(
302 out_file.writelines(
325 [
303 [
326 "# GENERATED BY setup.py\n",
304 "# GENERATED BY setup.py\n",
327 'commit = "%s"\n' % repo_commit,
305 'commit = "%s"\n' % repo_commit,
328 ]
306 ]
329 )
307 )
330
308
331 return MyBuildPy
309 return MyBuildPy
332
310
General Comments 0
You need to be logged in to leave comments. Login now