Skip to content

Commit a380ded

Browse files
committed
♻️ Update Nipype version check and automate future updates of said check
1 parent d951119 commit a380ded

File tree

3 files changed

+109
-64
lines changed

3 files changed

+109
-64
lines changed

CPAC/pipeline/cpac_pipeline.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@
209209
from CPAC.utils.trimmer import the_trimmer
210210
from CPAC.utils import Configuration, set_subject
211211
from CPAC.utils.docs import version_report
212+
from CPAC.utils.versioning import REQUIREMENTS
212213
from CPAC.qc.pipeline import create_qc_workflow
213214
from CPAC.qc.xcp import qc_xcp
214215

@@ -552,11 +553,11 @@ def run_workflow(sub_dict, c, run, pipeline_timing_info=None, p_name=None,
552553
log_nodes_initial(workflow)
553554

554555
# Add status callback function that writes in callback log
555-
if nipype.__version__ not in ('1.8.5'):
556-
err_msg = "This version of Nipype may not be compatible with " \
557-
"CPAC v%s, please install Nipype version 1.8.5\n" \
558-
% (CPAC.__version__)
559-
logger.error(err_msg)
556+
nipype_version = REQUIREMENTS['nipype']
557+
if nipype.__version__ != nipype_version:
558+
logger.warning('This version of Nipype may not be compatible '
559+
f'with CPAC v{CPAC.__version__}, please '
560+
f'install Nipype version {nipype_version}\n')
560561

561562
if plugin_args['n_procs'] == 1:
562563
plugin = 'Linear'

CPAC/utils/versioning/__init__.py

Lines changed: 4 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -14,62 +14,7 @@
1414

1515
# You should have received a copy of the GNU Lesser General Public
1616
# License along with C-PAC. If not, see <https://www.gnu.org/licenses/>.
17-
"""Gather and report dependency versions alphabetically"""
18-
from subprocess import PIPE, Popen
19-
import sys
20-
from pkg_resources import working_set
21-
22-
23-
def cli_version(command, dependency=None, in_result=True, delimiter=' ',
24-
formatting=None):
25-
"""Collect a version from a CLI
26-
27-
Parameters
28-
----------
29-
command : str
30-
31-
dependency : str, optional
32-
software name to report if not included in result
33-
34-
in_result : boolean, optional
35-
parse software name from result?
36-
37-
delimiter : str, optional
38-
if parsing software name from result, what's the delimiter?
39-
40-
formatting : func, optional
41-
if result needs any formatting, function to do so
42-
43-
Returns
44-
-------
45-
dict
46-
{software: version}
47-
"""
48-
with Popen(command, stdout=PIPE, shell=True) as _command:
49-
_version = _command.stdout.read().decode('utf-8')
50-
if formatting is not None:
51-
_version = formatting(_version)
52-
if in_result:
53-
return dict([tuple(_version.split(delimiter, 1))])
54-
return {dependency: _version}
55-
56-
57-
def _version_sort(_version_item):
58-
"""Key to report by case-insensitive dependecy name"""
59-
return _version_item[0].lower()
60-
61-
def first_line(stdout):
62-
"""Return first line of stdout"""
63-
if '\n' in stdout:
64-
return stdout.split('\n', 1)[0]
65-
return stdout
66-
67-
68-
PYTHON_PACKAGES = dict(sorted({
69-
d.key: d.version for d in list(working_set)}.items(), key=_version_sort))
70-
REPORTED = dict(sorted({
71-
**cli_version('ldd --version', formatting=first_line),
72-
'Python': sys.version.replace('\n', ' ').replace(' ', ' ')
73-
}.items(), key=_version_sort))
74-
75-
__all__ = ['PYTHON_PACKAGES', 'REPORTED']
17+
"""Gather and report versions"""
18+
from CPAC.utils.versioning.dependencies import PYTHON_PACKAGES, REPORTED, \
19+
REQUIREMENTS
20+
__all__ = ['PYTHON_PACKAGES', 'REPORTED', 'REQUIREMENTS']
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# Copyright (C) 2022 C-PAC Developers
2+
3+
# This file is part of C-PAC.
4+
5+
# C-PAC is free software: you can redistribute it and/or modify it under
6+
# the terms of the GNU Lesser General Public License as published by the
7+
# Free Software Foundation, either version 3 of the License, or (at your
8+
# option) any later version.
9+
10+
# C-PAC is distributed in the hope that it will be useful, but WITHOUT
11+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13+
# License for more details.
14+
15+
# You should have received a copy of the GNU Lesser General Public
16+
# License along with C-PAC. If not, see <https://www.gnu.org/licenses/>.
17+
"""Gather and report dependency versions alphabetically"""
18+
try:
19+
from importlib.metadata import distributions
20+
except ModuleNotFoundError:
21+
from importlib_metadata import distributions
22+
from pathlib import Path
23+
from subprocess import PIPE, Popen, STDOUT
24+
import sys
25+
26+
__all__ = ['PYTHON_PACKAGES', 'REPORTED', 'REQUIREMENTS']
27+
28+
29+
def cli_version(command, dependency=None, in_result=True, delimiter=' ',
30+
formatting=None):
31+
"""Collect a version from a CLI
32+
33+
Parameters
34+
----------
35+
command : str
36+
37+
dependency : str, optional
38+
software name to report if not included in result
39+
40+
in_result : boolean, optional
41+
parse software name from result?
42+
43+
delimiter : str, optional
44+
if parsing software name from result, what's the delimiter?
45+
46+
formatting : func, optional
47+
if result needs any formatting, function to do so
48+
49+
Returns
50+
-------
51+
dict
52+
{software: version}
53+
"""
54+
with Popen(command, stdout=PIPE, stderr=STDOUT, shell=True) as _command:
55+
_version = _command.stdout.read().decode('utf-8')
56+
if int(_command.poll()) == 127: # handle missing command
57+
return {}
58+
if formatting is not None:
59+
_version = formatting(_version)
60+
if in_result:
61+
return dict([tuple(_version.split(delimiter, 1))])
62+
return {dependency: _version}
63+
64+
65+
def first_line(stdout):
66+
"""Return first line of stdout"""
67+
if '\n' in stdout:
68+
return stdout.split('\n', 1)[0]
69+
return stdout
70+
71+
72+
def requirements() -> dict:
73+
"""Create a dictionary from requirements.txt"""
74+
import CPAC
75+
reqs = {}
76+
with open(Path(CPAC.__path__[0]).parent.joinpath('requirements.txt'), 'r',
77+
encoding='utf8') as _req:
78+
for line in _req.readlines():
79+
for delimiter in ['==', ' @ ']:
80+
if delimiter in line:
81+
key, value = line.split(delimiter, 1)
82+
reqs[key.strip()] = value.strip()
83+
continue
84+
return reqs
85+
86+
87+
def _version_sort(_version_item):
88+
"""Key to report by case-insensitive dependecy name"""
89+
return _version_item[0].lower()
90+
91+
92+
PYTHON_PACKAGES = dict(sorted({
93+
d.name: d.version for d in list(distributions())}.items(),
94+
key=_version_sort))
95+
REPORTED = dict(sorted({
96+
**cli_version('ldd --version', formatting=first_line),
97+
'Python': sys.version.replace('\n', ' ').replace(' ', ' ')
98+
}.items(), key=_version_sort))
99+
REQUIREMENTS = requirements()

0 commit comments

Comments
 (0)