-
Notifications
You must be signed in to change notification settings - Fork 576
/
version.py
183 lines (155 loc) · 5.74 KB
/
version.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# *- encoding: utf-8 -*-
"""
nilearn version, required package versions, and utilities for checking
"""
# Author: Loic Esteve, Ben Cipollini
# License: simplified BSD
# PEP0440 compatible formatted version, see:
# https://www.python.org/dev/peps/pep-0440/
#
# Generic release markers:
# X.Y
# X.Y.Z # For bugfix releases
#
# Admissible pre-release markers:
# X.YaN # Alpha release
# X.YbN # Beta release
# X.YrcN # Release Candidate
# X.Y # Final release
#
# Dev branch marker is: 'X.Y.dev' or 'X.Y.devN' where N is an integer.
# 'X.Y.dev0' is the canonical version of 'X.Y.dev'
#
__version__ = '0.9.2'
_NILEARN_INSTALL_MSG = 'See %s for installation information.' % (
'https://nilearn.github.io/stable/introduction.html#installation')
import operator
# This is a tuple to preserve order, so that dependencies are checked
# in some meaningful order (more => less 'core').
REQUIRED_MODULE_METADATA = (
('numpy', {
'min_version': '1.16',
'required_at_installation': True,
'install_info': _NILEARN_INSTALL_MSG}),
('scipy', {
'min_version': '1.2',
'required_at_installation': True,
'install_info': _NILEARN_INSTALL_MSG}),
('sklearn', {
'min_version': '0.21',
'required_at_installation': True,
'install_info': _NILEARN_INSTALL_MSG}),
('joblib', {
'min_version': '0.12',
'required_at_installation': True,
'install_info': _NILEARN_INSTALL_MSG}),
('nibabel', {
'min_version': '2.5',
'required_at_installation': False}),
('pandas', {
'min_version': '0.24.0',
'required_at_installation': True,
'install_info': _NILEARN_INSTALL_MSG}),
("requests", {
"min_version": "2",
"required_at_installation": False
})
)
OPTIONAL_MATPLOTLIB_MIN_VERSION = '2.0'
def _import_module_with_version_check(
module_name,
minimum_version,
install_info=None):
"""Check that module is installed with a recent enough version."""
try:
module = __import__(module_name)
except ImportError as exc:
user_friendly_info = ('Module "{0}" could not be found. {1}').format(
module_name,
install_info or 'Please install it properly to use nilearn.')
exc.args += (user_friendly_info,)
# Necessary for Python 3 because the repr/str of ImportError
# objects was changed in Python 3
if hasattr(exc, 'msg'):
exc.msg += '. ' + user_friendly_info
raise
# Avoid choking on modules with no __version__ attribute
module_version = getattr(module, '__version__', '0.0.0')
version_too_old = (
not _compare_version(module_version, '>=', minimum_version)
)
if version_too_old:
message = (
'A {module_name} version of at least {minimum_version} '
'is required to use nilearn. {module_version} was found. '
'Please upgrade {module_name}').format(
module_name=module_name,
minimum_version=minimum_version,
module_version=module_version)
raise ImportError(message)
return module
VERSION_OPERATORS = {
"==": operator.eq,
"!=": operator.ne,
">": operator.gt,
">=": operator.ge,
"<": operator.lt,
"<=": operator.le,
}
def _compare_version(version_a, operator, version_b):
"""Compare two version strings via a user-specified operator.
``distutils`` has been deprecated since Python 3.10 and is scheduled
for removal from the standard library with the release of Python 3.12.
For version comparisons, we use setuptools's `parse_version` if available.
Note: This function is inspired from MNE-Python.
See https://github.com/mne-tools/mne-python/blob/main/mne/fixes.py
Parameters
----------
version_a : :obj:`str`
First version string.
operator : {'==', '!=','>', '<', '>=', '<='}
Operator to compare ``version_a`` and ``version_b`` in the form of
``version_a operator version_b``.
version_b : :obj:`str`
Second version string.
Returns
-------
result : :obj:`bool`
The result of the version comparison.
"""
# TODO:
# The setuptools doc encourages the use of importlib.metadata instead
# of pkg_resources. However, importlib.metadata is only part of the stdlib
# for Python >= 3.8. When Nilearn will only support Python >= 3.8,
# please consider changing the following line to:
# from importlib.metadata import version as parse
try:
from pkg_resources import parse_version as parse # noqa:F401
except ImportError:
from distutils.version import LooseVersion as parse # noqa:F401
if operator not in VERSION_OPERATORS:
raise ValueError(
"'_compare_version' received an unexpected "
"operator {0}.".format(operator)
)
return VERSION_OPERATORS[operator](parse(version_a), parse(version_b))
def _check_module_dependencies(is_nilearn_installing=False):
"""Throw an exception if nilearn dependencies are not installed.
Parameters
----------
is_nilearn_installing: boolean
if True, only error on missing packages that cannot be auto-installed.
if False, error on any missing package.
Throws
-------
ImportError
"""
for (module_name, module_metadata) in REQUIRED_MODULE_METADATA:
if not (is_nilearn_installing and
not module_metadata['required_at_installation']):
# Skip check only when installing and it's a module that
# will be auto-installed.
_import_module_with_version_check(
module_name=module_name,
minimum_version=module_metadata['min_version'],
install_info=module_metadata.get('install_info'))