|
| 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