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