Integrate normalize as part of the requirements tools
Rather than have this as an external tool that open codes some of the logic we have in the existing codebase we should integrate it. Change-Id: I979dcefeec4ae28705088d4fac1e41b4d33e40e0
This commit is contained in:
parent
2536cc3695
commit
4bb92e041c
@ -1,83 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# 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
|
||||
from distutils.version import LooseVersion
|
||||
|
||||
import pkg_resources
|
||||
|
||||
|
||||
def cmp_specifier(a, b):
|
||||
weight = {'>=': 0, '>': 0,
|
||||
'==': 1 , '~=': 1, '!=': 1,
|
||||
'<': 2., '<=': 2}
|
||||
wa, wb = weight[a[0]], weight[b[0]]
|
||||
res = cmp(wa, wb)
|
||||
if res != 0:
|
||||
return res
|
||||
else:
|
||||
return cmp(LooseVersion(a[1]), LooseVersion(b[1]))
|
||||
|
||||
|
||||
def lint(requirements):
|
||||
output = []
|
||||
for line in requirements:
|
||||
# comments and empty lines are untouched
|
||||
if line.startswith("#") or line == "":
|
||||
output.append(line)
|
||||
continue
|
||||
|
||||
# split comments
|
||||
parts = line.split('#', 1)
|
||||
if len(parts) > 1:
|
||||
base, comments = parts
|
||||
else:
|
||||
base, comments = parts[0], ""
|
||||
base, comments = base.strip(), comments.strip()
|
||||
# split extras specifiers
|
||||
parts = base.split(';', 1)
|
||||
if len(parts) > 1:
|
||||
base, extras = parts
|
||||
else:
|
||||
base, extras = parts[0], ""
|
||||
base, extras = base.strip(), extras.strip()
|
||||
|
||||
req = pkg_resources.Requirement.parse(base)
|
||||
name = req.key
|
||||
# FIXME: not py3 compliant
|
||||
specs = ["%s%s" % x for x in sorted(req.specs, cmp=cmp_specifier)]
|
||||
name += ','.join(specs)
|
||||
if extras != "":
|
||||
name += ";%s" % extras
|
||||
if comments != "":
|
||||
name += " #%s" % comments
|
||||
output.append(name)
|
||||
return output
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Normalize requirements files")
|
||||
parser.add_argument('requirements',
|
||||
help=['requirements file input'])
|
||||
args = parser.parse_args()
|
||||
with open(args.requirements) as f:
|
||||
requirements = [line.strip() for line in f.readlines()]
|
||||
|
||||
for line in lint(requirements):
|
||||
print(line)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
37
openstack_requirements/cmds/normalize_requirements.py
Normal file
37
openstack_requirements/cmds/normalize_requirements.py
Normal file
@ -0,0 +1,37 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# 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.
|
||||
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import argparse
|
||||
from openstack_requirements import requirement
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Normalize requirements files")
|
||||
parser.add_argument('requirements', help='requirements file input')
|
||||
args = parser.parse_args()
|
||||
with open(args.requirements) as f:
|
||||
requirements = [line.strip() for line in f.readlines()]
|
||||
|
||||
for line in requirements:
|
||||
req = requirement.parse_line(line)
|
||||
print(req.to_line(comment_prefix=' ',
|
||||
sort_specifiers=True), end='')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -15,9 +15,10 @@
|
||||
# This module has no IO at all, and none should be added.
|
||||
|
||||
import collections
|
||||
import re
|
||||
|
||||
import distutils.version
|
||||
import packaging.specifiers
|
||||
import pkg_resources
|
||||
import re
|
||||
|
||||
|
||||
# A header for the requirements file(s).
|
||||
@ -31,6 +32,21 @@ _REQS_HEADER = [
|
||||
]
|
||||
|
||||
|
||||
def cmp_specifier(a, b):
|
||||
weight = {'>=': 0, '>': 0,
|
||||
'==': 1, '~=': 1, '!=': 1,
|
||||
'<': 2, '<=': 2}
|
||||
a = a._spec
|
||||
b = b._spec
|
||||
wa, wb = weight[a[0]], weight[b[0]]
|
||||
res = cmp(wa, wb)
|
||||
if res != 0:
|
||||
return res
|
||||
else:
|
||||
return cmp(distutils.version.LooseVersion(a[1]),
|
||||
distutils.version.LooseVersion(b[1]))
|
||||
|
||||
|
||||
class Requirement(collections.namedtuple('Requirement',
|
||||
['package', 'location', 'specifiers',
|
||||
'markers', 'comment', 'extras'])):
|
||||
@ -40,17 +56,24 @@ class Requirement(collections.namedtuple('Requirement',
|
||||
cls, package, location, specifiers, markers, comment,
|
||||
frozenset(extras or ()))
|
||||
|
||||
def to_line(self, marker_sep=';', line_prefix=''):
|
||||
comment_p = ' ' if self.package else ''
|
||||
def to_line(self, marker_sep=';', line_prefix='', comment_prefix=' ',
|
||||
sort_specifiers=False):
|
||||
comment_p = comment_prefix if self.package else ''
|
||||
comment = (comment_p + self.comment if self.comment else '')
|
||||
marker = marker_sep + self.markers if self.markers else ''
|
||||
package = line_prefix + self.package if self.package else ''
|
||||
location = self.location + '#egg=' if self.location else ''
|
||||
extras = '[%s]' % ",".join(sorted(self.extras)) if self.extras else ''
|
||||
specifiers = self.specifiers
|
||||
if sort_specifiers:
|
||||
_specifiers = packaging.specifiers.SpecifierSet(specifiers)
|
||||
_specifiers = ['%s' % s for s in sorted(_specifiers,
|
||||
cmp=cmp_specifier)]
|
||||
specifiers = ','.join(_specifiers)
|
||||
return '%s%s%s%s%s%s\n' % (location,
|
||||
package,
|
||||
extras,
|
||||
self.specifiers,
|
||||
specifiers,
|
||||
marker,
|
||||
comment)
|
||||
|
||||
|
@ -36,3 +36,4 @@ console_scripts =
|
||||
update-requirements = openstack_requirements.cmds.update:main
|
||||
validate-constraints = openstack_requirements.cmds.validate:main
|
||||
validate-projects = openstack_requirements.cmds.validate_projects:main
|
||||
normalize-requirements = openstack_requirements.cmds.normalize_requirements:main
|
||||
|
Loading…
Reference in New Issue
Block a user