##// 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 58 setup_args,
59 59 find_packages,
60 60 find_package_data,
61 find_scripts,
62 build_scripts_rename,
61 find_entry_points,
62 build_scripts_entrypt,
63 63 find_data_files,
64 64 check_for_dependencies,
65 65 git_prebuild,
@@ -68,6 +68,9 b' from setupbase import ('
68 68 require_submodules,
69 69 UpdateSubmodules,
70 70 CompileCSS,
71 install_symlinked,
72 install_lib_symlink,
73 install_scripts_for_symlink,
71 74 )
72 75 from setupext import setupext
73 76
@@ -148,7 +151,6 b' require_clean_submodules()'
148 151
149 152 # update the manuals when building a source dist
150 153 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
151 import textwrap
152 154
153 155 # List of things to be updated. Each entry is a triplet of args for
154 156 # target_update()
@@ -231,6 +233,9 b" setup_args['cmdclass'] = {"
231 233 'upload_wininst' : UploadWindowsInstallers,
232 234 'submodule' : UpdateSubmodules,
233 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 268 setup_args['cmdclass']['develop'] = require_submodules(develop)
264 269
265 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 272 setup_args['extras_require'] = dict(
268 273 parallel = 'pyzmq>=2.1.11',
269 274 qtconsole = ['pyzmq>=2.1.11', 'pygments'],
@@ -316,10 +321,10 b' else:'
316 321 # check for dependencies an inform the user what is needed. This is
317 322 # just to make life easy for users.
318 323 check_for_dependencies()
319 setup_args['scripts'] = find_scripts(False)
320 if PY3:
321 # Rename scripts with '3' suffix
322 setup_args['cmdclass']['build_scripts'] = build_scripts_rename
324 # scripts has to be a non-empty list, or install_scripts isn't called
325 setup_args['scripts'] = [e.split('=')[0].strip() for e in find_entry_points()]
326
327 setup_args['cmdclass']['build_scripts'] = build_scripts_entrypt
323 328
324 329 #---------------------------------------------------------------------------
325 330 # Do the actual setup now
@@ -20,15 +20,14 b' from __future__ import print_function'
20 20 #-------------------------------------------------------------------------------
21 21 # Imports
22 22 #-------------------------------------------------------------------------------
23 import errno
23 24 import os
24 25 import sys
25 26
26 try:
27 from configparser import ConfigParser
28 except:
29 from ConfigParser import ConfigParser
30 27 from distutils.command.build_py import build_py
31 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 31 from distutils.cmd import Command
33 32 from glob import glob
34 33 from subprocess import call
@@ -311,7 +310,7 b' def target_update(target,deps,cmd):'
311 310 # Find scripts
312 311 #---------------------------------------------------------------------------
313 312
314 def find_scripts(entry_points=False, suffix=''):
313 def find_entry_points():
315 314 """Find IPython's scripts.
316 315
317 316 if entry_points is True:
@@ -322,8 +321,7 b" def find_scripts(entry_points=False, suffix=''):"
322 321 suffix is appended to script names if entry_points is True, so that the
323 322 Python 3 scripts get named "ipython3" etc.
324 323 """
325 if entry_points:
326 console_scripts = [s % suffix for s in [
324 ep = [
327 325 'ipython%s = IPython:start_ipython',
328 326 'ipcontroller%s = IPython.parallel.apps.ipcontrollerapp:launch_new_instance',
329 327 'ipengine%s = IPython.parallel.apps.ipengineapp:launch_new_instance',
@@ -331,37 +329,85 b" def find_scripts(entry_points=False, suffix=''):"
331 329 'ipcluster%s = IPython.parallel.apps.ipclusterapp:launch_new_instance',
332 330 'iptest%s = IPython.testing.iptestcontroller:main',
333 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):
352 """Use this on Python 3 to rename scripts to ipython3 etc."""
353 _suffix = '3'
368 def finalize_options(self):
369 self.set_undefined_options('symlink',
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):
356 outfiles, updated_files = super(build_scripts_rename, self).copy_scripts()
357 new_outfiles = [p + self._suffix for p in outfiles]
358 updated_files = [p + self._suffix for p in updated_files]
359 for old, new in zip(outfiles, new_outfiles):
360 if os.path.exists(new):
361 os.unlink(new)
362 self.move_file(old, new)
363 return new_outfiles, updated_files
364
393 # 'sub_commands': a list of commands this command might have to run to
394 # get its work done. See cmd.py for more info.
395 sub_commands = [('install_lib_symlink', lambda self:True),
396 ('install_scripts_sym', lambda self:True),
397 ]
398
399 class install_scripts_for_symlink(install_scripts):
400 """Redefined to get options from 'symlink' instead of 'install'.
401
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 413 # Verify all dependencies
General Comments 0
You need to be logged in to leave comments. Login now