##// 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 ]]
332 ]
335 gui_scripts = []
333 suffix = str(sys.version_info[0])
336 scripts = dict(console_scripts=console_scripts, gui_scripts=gui_scripts)
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
367
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')
337 else:
384 else:
338 parallel_scripts = pjoin('IPython','parallel','scripts')
385 raise
339 main_scripts = pjoin('IPython','scripts')
386
340 scripts = [
387 class install_symlinked(install):
341 pjoin(parallel_scripts, 'ipengine'),
388 def run(self):
342 pjoin(parallel_scripts, 'ipcontroller'),
389 if sys.platform == 'win32':
343 pjoin(parallel_scripts, 'ipcluster'),
390 raise Exception("This doesn't work on Windows.")
344 pjoin(parallel_scripts, 'iplogger'),
391 install.run(self)
345 pjoin(main_scripts, 'ipython'),
392
346 pjoin(main_scripts, 'irunner'),
393 # 'sub_commands': a list of commands this command might have to run to
347 pjoin(main_scripts, 'iptest')
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),
348 ]
397 ]
349 return scripts
350
351 class build_scripts_rename(build_scripts):
352 """Use this on Python 3 to rename scripts to ipython3 etc."""
353 _suffix = '3'
354
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
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 # Verify all dependencies
413 # Verify all dependencies
General Comments 0
You need to be logged in to leave comments. Login now