Skip to content

Commit f9cc179

Browse files
committed
RF: let setuptools do some dependency checking
Let setuptools do dependency checking when packages are not installed, or they are easy to install.
1 parent 3debbe2 commit f9cc179

File tree

2 files changed

+56
-43
lines changed

2 files changed

+56
-43
lines changed

setup.py

Lines changed: 23 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,9 @@
1111
# update it when the contents of directories change.
1212
if exists('MANIFEST'): os.remove('MANIFEST')
1313

14-
# Import build helpers
15-
try:
16-
from nisext.sexts import package_check
17-
except ImportError:
18-
raise RuntimeError('Need nisext package from nibabel installation'
19-
' - please install nibabel first')
20-
2114
from setup_helpers import (generate_a_pyrex_source, get_comrec_build,
22-
cmdclass, INFO_VARS)
15+
cmdclass, INFO_VARS, get_pkg_version,
16+
version_error_msg)
2317

2418
# monkey-patch numpy distutils to use Cython instead of Pyrex
2519
from numpy.distutils.command.build_src import build_src
@@ -60,42 +54,28 @@ def configuration(parent_package='',top_path=None):
6054
if not 'extra_setuptools_args' in globals():
6155
extra_setuptools_args = dict()
6256

63-
6457
# Hard and soft dependency checking
65-
package_check('numpy', INFO_VARS['NUMPY_MIN_VERSION'])
66-
package_check('scipy', INFO_VARS['SCIPY_MIN_VERSION'])
67-
package_check('nibabel', INFO_VARS['NIBABEL_MIN_VERSION'])
68-
package_check('sympy', INFO_VARS['SYMPY_MIN_VERSION'])
69-
def _mayavi_version(pkg_name):
70-
"""Mayavi2 pruned enthought. namespace at 4.0.0
71-
"""
72-
v = ''
73-
try:
74-
from mayavi import version
75-
v = version.version
76-
if v == '':
77-
v = '4.0.0' # must be the one in Debian
78-
except ImportError:
79-
from enthought.mayavi import version
80-
v = version.version
81-
return v
82-
package_check('mayavi',
83-
INFO_VARS['MAYAVI_MIN_VERSION'],
84-
optional=True,
85-
version_getter=_mayavi_version)
86-
# Cython can be a build dependency
87-
def _cython_version(pkg_name):
88-
from Cython.Compiler.Version import version
89-
return version
90-
package_check('cython',
91-
INFO_VARS['CYTHON_MIN_VERSION'],
92-
optional=True,
93-
version_getter=_cython_version,
94-
messages={'opt suffix': ' - you will not be able '
95-
'to rebuild Cython source files into C files',
96-
'missing opt': 'Missing optional build-time '
97-
'package "%s"'}
98-
)
58+
DEPS = (
59+
('numpy', INFO_VARS['NUMPY_MIN_VERSION'], 'setup_requires', True),
60+
('scipy', INFO_VARS['SCIPY_MIN_VERSION'], 'install_requires', True),
61+
('nibabel', INFO_VARS['NIBABEL_MIN_VERSION'], 'install_requires', False),
62+
('sympy', INFO_VARS['SYMPY_MIN_VERSION'], 'install_requires', False))
63+
64+
using_setuptools = 'setuptools' in sys.modules
65+
66+
for name, min_ver, req_type, heavy in DEPS:
67+
found_ver = get_pkg_version(name)
68+
ver_err_msg = version_error_msg(name, found_ver, min_ver)
69+
if not using_setuptools:
70+
if ver_err_msg != None:
71+
raise RuntimeError(ver_err_msg)
72+
else: # Using setuptools
73+
# Add packages to given section of setup/install_requires
74+
if ver_err_msg != None or not heavy:
75+
new_req = '{0}>={1}'.format(name, min_ver)
76+
old_reqs = extra_setuptools_args.get(req_type, [])
77+
extra_setuptools_args[req_type] = old_reqs + [new_req]
78+
9979

10080
################################################################################
10181
# commands for installing the data

setup_helpers.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,39 @@ def run(self):
372372
return MyBuildPy
373373

374374

375+
def get_pkg_version(pkg_name):
376+
""" Return package version for `pkg_name` if installed
377+
378+
Returns
379+
-------
380+
pkg_version : str or None
381+
Return None if package not importable. Return 'unknown' if standard
382+
``__version__`` string not present. Otherwise return version string.
383+
"""
384+
try:
385+
pkg = __import__(pkg_name)
386+
except ImportError:
387+
return None
388+
try:
389+
return pkg.__version__
390+
except AttributeError:
391+
return 'unknown'
392+
393+
394+
def version_error_msg(pkg_name, found_ver, min_ver):
395+
""" Return informative error message for version or None
396+
"""
397+
if found_ver is None:
398+
return 'We need package {0}, but not importable'.format(pkg_name)
399+
if found_ver == 'unknown':
400+
msg = 'We need {0} version {1}, but cannot get version'.format(
401+
pkg_name, min_ver)
402+
if LooseVersion(found_ver) >= LooseVersion(min_ver):
403+
return None
404+
return 'We need {0} version {1}, but found version {2}'.format(
405+
pkg_name, found_ver, min_ver)
406+
407+
375408
# The command classes for distutils, used by setup.py
376409
cmdclass = {'api_docs': APIDocs,
377410
'clean': Clean,

0 commit comments

Comments
 (0)