Add reqs2pkg

This tool reads in one or more python requirements files and generates
a list of distribution specific package names  the intent is to use it
something like:

  sudo ${package_manager} install $(deps2pkg -r requirements.txt -b)
  sudo pip install .

To install a python project that runs against the distribution provided
pagages rather than pypi wheels/dists

Change-Id: Icd0720311e7863190b84aa916f13e7efa830a4eb
This commit is contained in:
Tony Breeds
2022-08-29 13:54:31 -07:00
parent 2d447598e2
commit e72a16d6d9
2 changed files with 116 additions and 0 deletions

115
pymod2pkg/cli/reqs2pkg.py Normal file
View File

@@ -0,0 +1,115 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import argparse
import distro
import packaging.requirements
import pymod2pkg
import sys
def get_default_prefix(dist):
d_lower = dist.lower()
if 'ubuntu' in d_lower:
return "Depends"
return "Requires"
def main():
"""Process python requirements files into a list of distribution
packages"""
parser = argparse.ArgumentParser(
description='Process python requirements files into a list of '
'distribution packages'
)
parser.add_argument(
'--dist', help='distribution style (default: %(default)s)',
default=distro.LinuxDistribution().id().partition(' ')[0])
parser.add_argument('--pyver', help='Python versions to return. "py" is '
'the unversioned name',
action='append', choices=['py', 'py2', 'py3'],
default=[])
parser.add_argument('-r', '--requirements', action="append",
dest='requirements', required=True, default=[],
help="python requirements file to parse")
parser.add_argument('-v', '--verbose', dest='verbose', action='count',
default=1, help='Invrease verbosity of the program')
parser.add_argument('-b', '--brief', dest='verbose', action='store_const',
const=0, help='Only generate packagenames')
parser.add_argument('--prefix', dest='prefix', nargs='?', const=None,
help="Prefix the output with a string provided by "
"the user or one determined by the --dist value")
args = vars(parser.parse_args())
pyversions = args['pyver'] if args['pyver'] else ['py']
if len(pyversions) > 1:
print("Please select only one version of python", file=sys.stderr)
return 1
args['prefix'] = get_default_prefix(args['dist'])
for reqs_file in args['requirements']:
if args['verbose']:
print(f'Processing: {reqs_file}')
try:
with open(reqs_file) as f:
reqs_txt = [line.strip() for line in f.readlines()]
except FileNotFoundError as ex:
print(ex)
reqs = []
for line in reqs_txt:
if line.startswith('#') or line == '':
continue
# TODO(tonyb): Do we need to extend this so that it does the
# right thing when given muliple versions of python for example:
# requirements,txt":
# liba>2;python_version>=3
# altlib;python_version<3
# We should honor this based on pyversions
req = packaging.requirements.Requirement(line.split('#')[0])
pkg = pymod2pkg.module2package(req.name, args['dist'],
py_vers=pyversions)
# We can potentially extend this to include versions
# specifications. The exact output will clearly be
# distribution specific
reqs.append(pkg)
# This is slightly complex but it handles the following scenarios:
# $ reqs2pkg -r test-requirements.txt --dist ubuntu -b
# python-stestr
# python-testresources
# python-testtools
# $ reqs2pkg -r test-requirements.txt --dist ubuntu
# Processing: test-requirements.txt
# Depends: python-stestr, python-testresources, python-testtools
# $ reqs2pkg -r test-requirements.txt --dist rhel -b
# python-stestr
# python-testresources
# python-testtools
# $ reqs2pkg -r test-requirements.txt --dist rhel
# Processing: test-requirements.txt
# Requires: python-stestr
# Requires: python-testresources
# Requires: python-testtools
prefix = ''
if args['verbose']:
prefix = f"{args['prefix']}: "
if args['dist'].lower() in 'ubuntu':
delim = ", "
else:
delim = f"\n{prefix}"
if args['verbose']:
print(prefix + delim.join(reqs))
else:
print("\n".join(reqs))

View File

@@ -20,6 +20,7 @@ classifier =
[entry_points] [entry_points]
console_scripts = console_scripts =
pymod2pkg = pymod2pkg.cli.pymod2pkg:main pymod2pkg = pymod2pkg.cli.pymod2pkg:main
reqs2pkg = pymod2pkg.cli.reqs2pkg:main
[files] [files]
packages = packages =