From 8bda10541a67fc66c0b4da0ccc5bc8bacf741f25 Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Wed, 20 Feb 2019 17:00:59 +0200 Subject: [PATCH] Add stdin option for merge_requirements Add stdin and file path support to strip_hashes --- tools/merge_requirements.py | 43 ++++++++++++++++++++++++++----------- tools/pip_install.py | 3 ++- tools/strip_hashes.py | 39 ++++++++++++++++++++++++++++----- 3 files changed, 66 insertions(+), 19 deletions(-) diff --git a/tools/merge_requirements.py b/tools/merge_requirements.py index 4205e6bcf..521d28b8f 100755 --- a/tools/merge_requirements.py +++ b/tools/merge_requirements.py @@ -10,27 +10,36 @@ from __future__ import print_function import sys -def read_file(file_path): - """Reads in a Python requirements file. +def process_entries(entries): + """ Ignore empty lines, comments and editable requirements - :param str file_path: path to requirements file + :param list entries: List of entries :returns: mapping from a project to its pinned version :rtype: dict - """ data = {} - with open(file_path) as file_h: - for line in file_h: - line = line.strip() - if line and not line.startswith('#') and not line.startswith('-e'): - project, version = line.split('==') - if not version: - raise ValueError("Unexpected syntax '{0}'".format(line)) - data[project] = version + for e in entries: + e = e.strip() + if e and not e.startswith('#') and not e.startswith('-e'): + project, version = e.split('==') + if not version: + raise ValueError("Unexpected syntax '{0}'".format(e)) + data[project] = version return data +def read_file(file_path): + """Reads in a Python requirements file. + + :param str file_path: path to requirements file + + :returns: list of entries in the file + :rtype: list + + """ + with open(file_path) as file_h: + return file_h.readlines() def output_requirements(requirements): """Prepare print requirements to stdout. @@ -53,7 +62,15 @@ def main(*paths): """ data = {} for path in paths: - data.update(read_file(path)) + data.update(process_entries(read_file(path))) + + # Need to check if interactive to avoid blocking if nothing is piped + if not sys.stdin.isatty(): + stdin_data = [] + for line in sys.stdin: + stdin_data.append(line) + data.update(process_entries(stdin_data)) + return output_requirements(data) diff --git a/tools/pip_install.py b/tools/pip_install.py index 475799eb1..8f0437d9c 100755 --- a/tools/pip_install.py +++ b/tools/pip_install.py @@ -48,7 +48,8 @@ def certbot_normal_processing(tools_path, test_constraints): with open(certbot_requirements, 'r') as fd: data = fd.readlines() with open(test_constraints, 'w') as fd: - fd.write(strip_hashes.main(data)) + data = os.linesep.join(strip_hashes.process_entries(data)) + fd.write(data) def merge_requirements(tools_path, requirements, test_constraints, all_constraints): diff --git a/tools/strip_hashes.py b/tools/strip_hashes.py index c5591e2f4..7e7809458 100755 --- a/tools/strip_hashes.py +++ b/tools/strip_hashes.py @@ -1,16 +1,45 @@ #!/usr/bin/env python +"""Removes hash information from requirement files passed to it as file path +arguments or simply piped to stdin.""" import os import re import sys -def main(args): + +def process_entries(entries): + """Strips off hash strings from dependencies. + + :param list entries: List of entries + + :returns: list of dependencies without hashes + :rtype: list + """ out_lines = [] - for line in args: - search = re.search(r'^(\S*==\S*).*$', line) + for e in entries: + e = e.strip() + search = re.search(r'^(\S*==\S*).*$', e) if search: out_lines.append(search.group(1)) - return os.linesep.join(out_lines) + return out_lines + +def main(*paths): + """Reads dependency definitions from a (list of) file(s) or stdin and + removes hashes from returned entries""" + + deps = [] + for path in paths: + with open(path) as file_h: + deps += process_entries(file_h.readlines()) + + # Need to check if interactive to avoid blocking if nothing is piped + if not sys.stdin.isatty(): + stdin_data = [] + for line in sys.stdin: + stdin_data.append(line) + deps += process_entries(stdin_data) + + return os.linesep.join(deps) if __name__ == '__main__': - print(main(sys.argv[1:])) + print(main(*sys.argv[1:])) # pylint: disable=star-args