diff --git a/setup.py b/setup.py index a98f793a8..b15fe4733 100755 --- a/setup.py +++ b/setup.py @@ -6,12 +6,16 @@ Under Posix environments it works like a typical setup.py script. Under Windows, the command sdist is not supported, since IPython requires utilities which are not available under Windows.""" -#***************************************************************************** -# Copyright (C) 2001-2005 Fernando Perez +#------------------------------------------------------------------------------- +# Copyright (C) 2008 The IPython Development Team # # Distributed under the terms of the BSD License. The full license is in # the file COPYING, distributed as part of this software. -#***************************************************************************** +#------------------------------------------------------------------------------- + +#------------------------------------------------------------------------------- +# Imports +#------------------------------------------------------------------------------- # Stdlib imports import os @@ -24,35 +28,24 @@ from glob import glob if os.path.exists('MANIFEST'): os.remove('MANIFEST') from distutils.core import setup -from setupext import install_data_ext # Local imports from IPython.genutils import target_update -# A few handy globals +from setupbase import ( + setup_args, + find_packages, + find_package_data, + find_scripts, + find_data_files, + check_for_dependencies +) + isfile = os.path.isfile -pjoin = os.path.join -############################################################################## -# Utility functions -def oscmd(s): - print ">", s - os.system(s) - -# A little utility we'll need below, since glob() does NOT allow you to do -# exclusion on multiple endings! -def file_doesnt_endwith(test,endings): - """Return true if test is a file and its name does NOT end with any - of the strings listed in endings.""" - if not isfile(test): - return False - for e in endings: - if test.endswith(e): - return False - return True - -############################################################################### -# Main code begins +#------------------------------------------------------------------------------- +# Handle OS specific things +#------------------------------------------------------------------------------- if os.name == 'posix': os_name = 'posix' @@ -69,6 +62,10 @@ if os_name == 'windows' and 'sdist' in sys.argv: print 'The sdist command is not available under Windows. Exiting.' sys.exit(1) +#------------------------------------------------------------------------------- +# Things related to the IPython documentation +#------------------------------------------------------------------------------- + # update the manuals when building a source dist if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'): import textwrap @@ -98,89 +95,68 @@ if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'): [ target_update(*t) for t in to_update ] -# Release.py contains version, authors, license, url, keywords, etc. -execfile(pjoin('IPython','Release.py')) +#--------------------------------------------------------------------------- +# Find all the packages, package data, scripts and data_files +#--------------------------------------------------------------------------- -# I can't find how to make distutils create a nested dir. structure, so -# in the meantime do it manually. Butt ugly. -# Note that http://www.redbrick.dcu.ie/~noel/distutils.html, ex. 2/3, contain -# information on how to do this more cleanly once python 2.4 can be assumed. -# Thanks to Noel for the tip. -docdirbase = 'share/doc/ipython' -manpagebase = 'share/man/man1' +packages = find_packages() +package_data = find_package_data() +scripts = find_scripts() +data_files = find_data_files() -# We only need to exclude from this things NOT already excluded in the -# MANIFEST.in file. -exclude = ('.sh','.1.gz') -docfiles = filter(lambda f:file_doesnt_endwith(f,exclude),glob('doc/*')) -examfiles = filter(isfile, glob('doc/examples/*.py')) -manfiles = filter(isfile, glob('doc/manual/*')) -manstatic = filter(isfile, glob('doc/manual/_static/*')) -manpages = filter(isfile, glob('doc/*.1.gz')) +#--------------------------------------------------------------------------- +# Handle dependencies and setuptools specific things +#--------------------------------------------------------------------------- -cfgfiles = filter(isfile, glob('IPython/UserConfig/*')) -scriptfiles = filter(isfile, ['scripts/ipython','scripts/pycolor', - 'scripts/irunner']) - -igridhelpfiles = filter(isfile, glob('IPython/Extensions/igrid_help.*')) - -# Script to be run by the windows binary installer after the default setup -# routine, to add shortcuts and similar windows-only things. Windows -# post-install scripts MUST reside in the scripts/ dir, otherwise distutils -# doesn't find them. -if 'bdist_wininst' in sys.argv: - if len(sys.argv) > 2 and ('sdist' in sys.argv or 'bdist_rpm' in sys.argv): - print >> sys.stderr,"ERROR: bdist_wininst must be run alone. Exiting." - sys.exit(1) - scriptfiles.append('scripts/ipython_win_post_install.py') - -datafiles = [('data', docdirbase, docfiles), - ('data', pjoin(docdirbase, 'examples'),examfiles), - ('data', pjoin(docdirbase, 'manual'),manfiles), - ('data', pjoin(docdirbase, 'manual/_static'),manstatic), - ('data', manpagebase, manpages), - ('data',pjoin(docdirbase, 'extensions'),igridhelpfiles), - ] +# This dict is used for passing extra arguments that are setuptools +# specific to setup +setuptools_extra_args = {} if 'setuptools' in sys.modules: - # setuptools config for egg building - egg_extra_kwds = { - 'entry_points': { - 'console_scripts': [ + setuptools_extra_args['zip_safe'] = False + setuptools_extra_args['entry_points'] = { + 'console_scripts': [ 'ipython = IPython.ipapi:launch_new_instance', - 'pycolor = IPython.PyColorize:main' - ]} - } - scriptfiles = [] + 'pycolor = IPython.PyColorize:main', + 'ipcontroller = IPython.kernel.scripts.ipcontroller:main', + 'ipengine = IPython.kernel.scripts.ipengine:main', + 'ipcluster = IPython.kernel.scripts.ipcluster:main' + ] + } + setup_args["extras_require"] = dict( + kernel = [ + "zope.interface>=3.4.1", + "Twisted>=8.0.1", + "foolscap>=0.2.6" + ], + doc=['Sphinx>=0.3','pygments'], + test='nose>=0.10.1', + security=["pyOpenSSL>=0.6"] + ) + # Allow setuptools to handle the scripts + scripts = [] # eggs will lack docs, examples - datafiles = [] + data_files = [] else: - # Normal, non-setuptools install - egg_extra_kwds = {} # package_data of setuptools was introduced to distutils in 2.4 + cfgfiles = filter(isfile, glob('IPython/UserConfig/*')) if sys.version_info < (2,4): - datafiles.append(('lib', 'IPython/UserConfig', cfgfiles)) - -# Call the setup() routine which does most of the work -setup(name = name, - version = version, - description = description, - long_description = long_description, - author = authors['Fernando'][0], - author_email = authors['Fernando'][1], - url = url, - download_url = download_url, - license = license, - platforms = platforms, - keywords = keywords, - packages = ['IPython', 'IPython.Extensions', 'IPython.external', - 'IPython.gui', 'IPython.gui.wx', - 'IPython.UserConfig'], - scripts = scriptfiles, - package_data = {'IPython.UserConfig' : ['*'] }, - - cmdclass = {'install_data': install_data_ext}, - data_files = datafiles, - # extra params needed for eggs - **egg_extra_kwds - ) + data_files.append(('lib', 'IPython/UserConfig', cfgfiles)) + # If we are running without setuptools, call this function which will + # check for dependencies an inform the user what is needed. This is + # just to make life easy for users. + check_for_dependencies() + + +#--------------------------------------------------------------------------- +# Do the actual setup now +#--------------------------------------------------------------------------- + +setup_args['packages'] = packages +setup_args['package_data'] = package_data +setup_args['scripts'] = scripts +setup_args['data_files'] = data_files +setup_args.update(setuptools_extra_args) + +if __name__ == '__main__': + setup(**setup_args) diff --git a/setupbase.py b/setupbase.py new file mode 100644 index 000000000..41954cdc5 --- /dev/null +++ b/setupbase.py @@ -0,0 +1,201 @@ +# encoding: utf-8 + +__docformat__ = "restructuredtext en" + +#------------------------------------------------------------------------------- +# Copyright (C) 2008 The IPython Development Team +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#------------------------------------------------------------------------------- + +#------------------------------------------------------------------------------- +# Imports +#------------------------------------------------------------------------------- + +import os, sys + +from glob import glob + +from setupext import install_data_ext + +#------------------------------------------------------------------------------- +# Useful globals and utility functions +#------------------------------------------------------------------------------- + +# A few handy globals +isfile = os.path.isfile +pjoin = os.path.join + +def oscmd(s): + print ">", s + os.system(s) + +# A little utility we'll need below, since glob() does NOT allow you to do +# exclusion on multiple endings! +def file_doesnt_endwith(test,endings): + """Return true if test is a file and its name does NOT end with any + of the strings listed in endings.""" + if not isfile(test): + return False + for e in endings: + if test.endswith(e): + return False + return True + +#--------------------------------------------------------------------------- +# Basic project information +#--------------------------------------------------------------------------- + +# Release.py contains version, authors, license, url, keywords, etc. +execfile(pjoin('IPython','Release.py')) + +# Create a dict with the basic information +# This dict is eventually passed to setup after additional keys are added. +setup_args = dict( + name = name, + version = version, + description = description, + long_description = long_description, + author = author, + author_email = author_email, + url = url, + download_url = download_url, + license = license, + platforms = platforms, + keywords = keywords, + cmdclass = {'install_data': install_data_ext}, + ) + + +#--------------------------------------------------------------------------- +# Find packages +#--------------------------------------------------------------------------- + +def add_package(packages, pname, config=False, tests=False, scripts=False, others=None): + packages.append('.'.join(['ipython1',pname])) + if config: + packages.append('.'.join(['ipython1',pname,'config'])) + if tests: + packages.append('.'.join(['ipython1',pname,'tests'])) + if scripts: + packages.append('.'.join(['ipython1',pname,'scripts'])) + if others is not None: + for o in others: + packages.append('.'.join(['ipython1',pname,o])) + +def find_packages(): + packages = ['ipython'] + add_package(packages, 'config', tests=True) + add_package(packages , 'Extensions') + add_package(packages, 'external') + add_package(packages, 'gui') + add_package(packages, 'gui.wx') + add_package(packages, 'kernel', config=True, tests=True, scripts=True) + add_package(packages, 'kernel.core', config=True, tests=True) + add_package(packages, 'testing', tests=True) + add_package(packages, 'tools', tests=True) + add_package(packages, 'UserConfig') + return packages + +#--------------------------------------------------------------------------- +# Find package data +#--------------------------------------------------------------------------- + +def find_package_data(): + # This is not enough for these things to appear in an sdist. + # We need to muck with the MANIFEST to get this to work + package_data = {'IPython.UserConfig' : ['*'] } + return package_data + + +#--------------------------------------------------------------------------- +# Find data files +#--------------------------------------------------------------------------- + +def find_data_files(): + + # I can't find how to make distutils create a nested dir. structure, so + # in the meantime do it manually. Butt ugly. + # Note that http://www.redbrick.dcu.ie/~noel/distutils.html, ex. 2/3, contain + # information on how to do this more cleanly once python 2.4 can be assumed. + # Thanks to Noel for the tip. + docdirbase = 'share/doc/ipython' + manpagebase = 'share/man/man1' + + # We only need to exclude from this things NOT already excluded in the + # MANIFEST.in file. + exclude = ('.sh','.1.gz') + docfiles = filter(lambda f:file_doesnt_endwith(f,exclude),glob('doc/*')) + examfiles = filter(isfile, glob('doc/examples/*.py')) + manfiles = filter(isfile, glob('doc/manual/*')) + manstatic = filter(isfile, glob('doc/manual/_static/*')) + manpages = filter(isfile, glob('doc/*.1.gz')) + scriptfiles = filter(isfile, ['scripts/ipython','scripts/pycolor', + 'scripts/irunner']) + igridhelpfiles = filter(isfile, glob('IPython/Extensions/igrid_help.*')) + + data_files = [('data', docdirbase, docfiles), + ('data', pjoin(docdirbase, 'examples'),examfiles), + ('data', pjoin(docdirbase, 'manual'),manfiles), + ('data', pjoin(docdirbase, 'manual/_static'),manstatic), + ('data', manpagebase, manpages), + ('data',pjoin(docdirbase, 'extensions'),igridhelpfiles), + ] + return data_files + +#--------------------------------------------------------------------------- +# Find scripts +#--------------------------------------------------------------------------- + +def find_scripts(): + scripts = [] + scripts.append('ipython1/kernel/scripts/ipengine') + scripts.append('ipython1/kernel/scripts/ipcontroller') + scripts.append('ipython1/kernel/scripts/ipcluster') + scripts.append('scripts/ipython') + scripts.append('scripts/pycolor') + scripts.append('scripts/irunner') + + # Script to be run by the windows binary installer after the default setup + # routine, to add shortcuts and similar windows-only things. Windows + # post-install scripts MUST reside in the scripts/ dir, otherwise distutils + # doesn't find them. + if 'bdist_wininst' in sys.argv: + if len(sys.argv) > 2 and ('sdist' in sys.argv or 'bdist_rpm' in sys.argv): + print >> sys.stderr,"ERROR: bdist_wininst must be run alone. Exiting." + sys.exit(1) + scripts.append('scripts/ipython_win_post_install.py') + + return scripts + +#--------------------------------------------------------------------------- +# Find scripts +#--------------------------------------------------------------------------- + +def check_for_dependencies(): + from setupext.setupext import ( + print_line, print_raw, print_status, print_message, + check_for_zopeinterface, check_for_twisted, + check_for_foolscap, check_for_pyopenssl, + check_for_sphinx, check_for_pygments, + check_for_nose, check_for_pexpect + ) + print_line() + print_raw("BUILDING IPYTHON") + print_status('python', sys.version) + print_status('platform', sys.platform) + if sys.platform == 'win32': + print_status('Windows version', sys.getwindowsversion()) + + print_raw("") + print_raw("OPTIONAL DEPENDENCIES") + + check_for_zopeinterface() + check_for_twisted() + check_for_foolscap() + check_for_pyopenssl() + check_for_sphinx() + check_for_pygments() + check_for_nose() + check_for_pexpect() \ No newline at end of file