From 78bf02298b28008a746697a551f00e133dbbe158 Mon Sep 17 00:00:00 2001 From: Haikel Guemar Date: Wed, 22 Jun 2016 07:39:57 +0200 Subject: [PATCH] Add new normalize utility Purpose: cleanup requirements.txt in order to be more readable Implemented features: - comments are preceded by two spaces and separated from '#' by one space (PEP8 style) - specificiers are ordered Change-Id: Ic9a4c044b2740b1d0167c237b67822a9794356c8 --- cmds/normalize | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100755 cmds/normalize diff --git a/cmds/normalize b/cmds/normalize new file mode 100755 index 0000000000..40dd6c48d0 --- /dev/null +++ b/cmds/normalize @@ -0,0 +1,83 @@ +#! /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()