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