Source code for jnrbase.pip_support

#
"""pip_support - pip workarounds support."""
# Copyright © 2014-2020  James Rowe <jnrowe@gmail.com>
#                        Nathan McGregor <nathan.mcgregor@astrium.eads.net>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# This file is part of jnrbase.
#
# jnrbase is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# jnrbase is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# jnrbase.  If not, see <http://www.gnu.org/licenses/>.

# pip, both as a tool and a package manager, are not available on many of the
# systems I use.  However, lots of Python users like to use it so we’ll need to
# support the workflow to some extent…

import re
from pathlib import Path
from sys import version_info
from typing import List

__eval_env = {
    '__builtins__': {},
    'python_version': '{0.major}.{0.minor}'.format(version_info)
}


[docs]def parse_requires(__fname: Path) -> List[str]: """Parse ``pip``-style requirements files. This is a *very* naïve parser, but very few packages make use of the more advanced features. Support for other features will be added only when packages in the wild depend on them. Args: __fname: Base file to pass Returns: Parsed dependencies """ deps = [] with __fname.open() as req_file: entries = [s.split('#')[0].strip() for s in req_file.readlines()] for dep in entries: if not dep: continue elif dep.startswith('-r '): include = dep.split()[1] if '/' not in include: include = __fname.parent / include else: include = Path(include) deps.extend(parse_requires(include)) continue elif ';' in dep: dep, marker = [s.strip() for s in dep.split(';')] # Support for other markers will be added when they’re actually # found in the wild match = re.fullmatch( r""" (?:python_version) # Supported markers \s* (?:<=?|==|>=?) # Supported comparisons \s* (?P<quote>(?:'|"))(?:[\d\.]+)(?P=quote) # Test """, marker, re.VERBOSE) if not match: raise ValueError(f'Invalid marker {marker!r}') if not eval(marker, __eval_env): # pylint: disable=eval-used continue deps.append(dep) return deps