##// END OF EJS Templates
Rework setup to allow installing on Python 2 and 3....
Thomas Kluyver -
Show More
@@ -58,8 +58,8 b' from setupbase import ('
58 setup_args,
58 setup_args,
59 find_packages,
59 find_packages,
60 find_package_data,
60 find_package_data,
61 find_scripts,
61 find_entry_points,
62 build_scripts_rename,
62 build_scripts_entrypt,
63 find_data_files,
63 find_data_files,
64 check_for_dependencies,
64 check_for_dependencies,
65 git_prebuild,
65 git_prebuild,
@@ -68,6 +68,9 b' from setupbase import ('
68 require_submodules,
68 require_submodules,
69 UpdateSubmodules,
69 UpdateSubmodules,
70 CompileCSS,
70 CompileCSS,
71 install_symlinked,
72 install_lib_symlink,
73 install_scripts_for_symlink,
71 )
74 )
72 from setupext import setupext
75 from setupext import setupext
73
76
@@ -148,7 +151,6 b' require_clean_submodules()'
148
151
149 # update the manuals when building a source dist
152 # update the manuals when building a source dist
150 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
153 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
151 import textwrap
152
154
153 # List of things to be updated. Each entry is a triplet of args for
155 # List of things to be updated. Each entry is a triplet of args for
154 # target_update()
156 # target_update()
@@ -231,6 +233,9 b" setup_args['cmdclass'] = {"
231 'upload_wininst' : UploadWindowsInstallers,
233 'upload_wininst' : UploadWindowsInstallers,
232 'submodule' : UpdateSubmodules,
234 'submodule' : UpdateSubmodules,
233 'css' : CompileCSS,
235 'css' : CompileCSS,
236 'symlink': install_symlinked,
237 'install_lib_symlink': install_lib_symlink,
238 'install_scripts_sym': install_scripts_for_symlink,
234 }
239 }
235
240
236 #---------------------------------------------------------------------------
241 #---------------------------------------------------------------------------
@@ -263,7 +268,7 b" if 'setuptools' in sys.modules:"
263 setup_args['cmdclass']['develop'] = require_submodules(develop)
268 setup_args['cmdclass']['develop'] = require_submodules(develop)
264
269
265 setuptools_extra_args['zip_safe'] = False
270 setuptools_extra_args['zip_safe'] = False
266 setuptools_extra_args['entry_points'] = find_scripts(True, suffix = '3' if PY3 else '')
271 setuptools_extra_args['entry_points'] = {'console_scripts':find_entry_points()}
267 setup_args['extras_require'] = dict(
272 setup_args['extras_require'] = dict(
268 parallel = 'pyzmq>=2.1.11',
273 parallel = 'pyzmq>=2.1.11',
269 qtconsole = ['pyzmq>=2.1.11', 'pygments'],
274 qtconsole = ['pyzmq>=2.1.11', 'pygments'],
@@ -316,10 +321,10 b' else:'
316 # check for dependencies an inform the user what is needed. This is
321 # check for dependencies an inform the user what is needed. This is
317 # just to make life easy for users.
322 # just to make life easy for users.
318 check_for_dependencies()
323 check_for_dependencies()
319 setup_args['scripts'] = find_scripts(False)
324 # scripts has to be a non-empty list, or install_scripts isn't called
320 if PY3:
325 setup_args['scripts'] = [e.split('=')[0].strip() for e in find_entry_points()]
321 # Rename scripts with '3' suffix
326
322 setup_args['cmdclass']['build_scripts'] = build_scripts_rename
327 setup_args['cmdclass']['build_scripts'] = build_scripts_entrypt
323
328
324 #---------------------------------------------------------------------------
329 #---------------------------------------------------------------------------
325 # Do the actual setup now
330 # Do the actual setup now
@@ -20,15 +20,14 b' from __future__ import print_function'
20 #-------------------------------------------------------------------------------
20 #-------------------------------------------------------------------------------
21 # Imports
21 # Imports
22 #-------------------------------------------------------------------------------
22 #-------------------------------------------------------------------------------
23 import errno
23 import os
24 import os
24 import sys
25 import sys
25
26
26 try:
27 from configparser import ConfigParser
28 except:
29 from ConfigParser import ConfigParser
30 from distutils.command.build_py import build_py
27 from distutils.command.build_py import build_py
31 from distutils.command.build_scripts import build_scripts
28 from distutils.command.build_scripts import build_scripts
29 from distutils.command.install import install
30 from distutils.command.install_scripts import install_scripts
32 from distutils.cmd import Command
31 from distutils.cmd import Command
33 from glob import glob
32 from glob import glob
34 from subprocess import call
33 from subprocess import call
@@ -311,7 +310,7 b' def target_update(target,deps,cmd):'
311 # Find scripts
310 # Find scripts
312 #---------------------------------------------------------------------------
311 #---------------------------------------------------------------------------
313
312
314 def find_scripts(entry_points=False, suffix=''):
313 def find_entry_points():
315 """Find IPython's scripts.
314 """Find IPython's scripts.
316
315
317 if entry_points is True:
316 if entry_points is True:
@@ -322,8 +321,7 b" def find_scripts(entry_points=False, suffix=''):"
322 suffix is appended to script names if entry_points is True, so that the
321 suffix is appended to script names if entry_points is True, so that the
323 Python 3 scripts get named "ipython3" etc.
322 Python 3 scripts get named "ipython3" etc.
324 """
323 """
325 if entry_points:
324 ep = [
326 console_scripts = [s % suffix for s in [
327 'ipython%s = IPython:start_ipython',
325 'ipython%s = IPython:start_ipython',
328 'ipcontroller%s = IPython.parallel.apps.ipcontrollerapp:launch_new_instance',
326 'ipcontroller%s = IPython.parallel.apps.ipcontrollerapp:launch_new_instance',
329 'ipengine%s = IPython.parallel.apps.ipengineapp:launch_new_instance',
327 'ipengine%s = IPython.parallel.apps.ipengineapp:launch_new_instance',
@@ -331,37 +329,85 b" def find_scripts(entry_points=False, suffix=''):"
331 'ipcluster%s = IPython.parallel.apps.ipclusterapp:launch_new_instance',
329 'ipcluster%s = IPython.parallel.apps.ipclusterapp:launch_new_instance',
332 'iptest%s = IPython.testing.iptestcontroller:main',
330 'iptest%s = IPython.testing.iptestcontroller:main',
333 'irunner%s = IPython.lib.irunner:main',
331 'irunner%s = IPython.lib.irunner:main',
334 ]]
335 gui_scripts = []
336 scripts = dict(console_scripts=console_scripts, gui_scripts=gui_scripts)
337 else:
338 parallel_scripts = pjoin('IPython','parallel','scripts')
339 main_scripts = pjoin('IPython','scripts')
340 scripts = [
341 pjoin(parallel_scripts, 'ipengine'),
342 pjoin(parallel_scripts, 'ipcontroller'),
343 pjoin(parallel_scripts, 'ipcluster'),
344 pjoin(parallel_scripts, 'iplogger'),
345 pjoin(main_scripts, 'ipython'),
346 pjoin(main_scripts, 'irunner'),
347 pjoin(main_scripts, 'iptest')
348 ]
332 ]
349 return scripts
333 suffix = str(sys.version_info[0])
334 return [e % '' for e in ep] + [e % suffix for e in ep]
335
336 script_src = """#!{executable}
337 from {mod} import {func}
338 {func}()
339 """
340
341 class build_scripts_entrypt(build_scripts):
342 def run(self):
343 self.mkpath(self.build_dir)
344 outfiles = []
345 for script in find_entry_points():
346 name, entrypt = script.split('=')
347 name = name.strip()
348 entrypt = entrypt.strip()
349 outfile = os.path.join(self.build_dir, name)
350 outfiles.append(outfile)
351 print('Writing script to', outfile)
352
353 mod, func = entrypt.split(':')
354 with open(outfile, 'w') as f:
355 f.write(script_src.format(executable=sys.executable,
356 mod=mod, func=func))
357
358 return outfiles, outfiles
359
360 class install_lib_symlink(Command):
361 user_options = [
362 ('install-dir=', 'd', "directory to install to"),
363 ]
364
365 def initialize_options(self):
366 self.install_dir = None
350
367
351 class build_scripts_rename(build_scripts):
368 def finalize_options(self):
352 """Use this on Python 3 to rename scripts to ipython3 etc."""
369 self.set_undefined_options('symlink',
353 _suffix = '3'
370 ('install_lib', 'install_dir'),
371 )
372
373 def run(self):
374 if sys.platform == 'win32':
375 raise Exception("This doesn't work on Windows.")
376 pkg = os.path.join(os.getcwd(), 'IPython')
377 dest = os.path.join(self.install_dir, 'IPython')
378 print('symlinking %s -> %s' % (pkg, dest))
379 try:
380 os.symlink(pkg, dest)
381 except OSError as e:
382 if e.errno == errno.EEXIST:
383 print('ALREADY EXISTS')
384 else:
385 raise
386
387 class install_symlinked(install):
388 def run(self):
389 if sys.platform == 'win32':
390 raise Exception("This doesn't work on Windows.")
391 install.run(self)
354
392
355 def copy_scripts(self):
393 # 'sub_commands': a list of commands this command might have to run to
356 outfiles, updated_files = super(build_scripts_rename, self).copy_scripts()
394 # get its work done. See cmd.py for more info.
357 new_outfiles = [p + self._suffix for p in outfiles]
395 sub_commands = [('install_lib_symlink', lambda self:True),
358 updated_files = [p + self._suffix for p in updated_files]
396 ('install_scripts_sym', lambda self:True),
359 for old, new in zip(outfiles, new_outfiles):
397 ]
360 if os.path.exists(new):
398
361 os.unlink(new)
399 class install_scripts_for_symlink(install_scripts):
362 self.move_file(old, new)
400 """Redefined to get options from 'symlink' instead of 'install'.
363 return new_outfiles, updated_files
401
364
402 I love distutils almost as much as I love setuptools.
403 """
404 def finalize_options(self):
405 self.set_undefined_options('build', ('build_scripts', 'build_dir'))
406 self.set_undefined_options('symlink',
407 ('install_scripts', 'install_dir'),
408 ('force', 'force'),
409 ('skip_build', 'skip_build'),
410 )
365
411
366 #---------------------------------------------------------------------------
412 #---------------------------------------------------------------------------
367 # Verify all dependencies
413 # Verify all dependencies
General Comments 0
You need to be logged in to leave comments. Login now