diff --git a/pipreqs/pipreqs.py b/pipreqs/pipreqs.py index bfb01fa..7a63556 100755 --- a/pipreqs/pipreqs.py +++ b/pipreqs/pipreqs.py @@ -3,90 +3,99 @@ """pipreqs - Generate pip requirements.txt file based on imports Usage: - pipreqs - pipreqs [options] + pipreqs + pipreqs [options] Options: --debug prints debug information. --savepath path to requirements.txt (Optional) """ from __future__ import print_function -import os, re, logging +import os +import sys +import re +import logging + from docopt import docopt import yarg from yarg.exceptions import HTTPError + REGEXP = [ - re.compile(r'^import (.+)$'), - re.compile(r'from (.*?) import (?:.*)') + re.compile(r'^import (.+)$'), + re.compile(r'from (.*?) import (?:.*)') ] + def get_all_imports(start_path): - imports = [] - packages = [] - logging.debug('Traversing tree, start: %s', start_path) - for root, dirs, files in os.walk(start_path): - path = root.split('/') - packages.append(os.path.basename(root)) - for file in files: - if file[-3:] != ".py": - continue - for rex in REGEXP: - with open(os.path.join(root,file), "r") as f: - lines = f.readlines() - for line in lines: - if line[0] == "#": - continue - if "(" in line: - break - s = rex.match(line) - if not s: - continue - for item in s.groups(): - if "," in item: - for match in item.split(","): - imports.append(match.strip()) - else: - to_append = item if "." not in item else item.split(".")[0] - imports.append(to_append.strip()) - third_party_packages = set(imports) - set(set(packages) & set(imports)) - logging.debug('Found third-party packages: %s', third_party_packages) - with open(os.path.join(os.path.dirname(__file__), "stdlib"), "r") as f: - data = [x.strip() for x in f.readlines()] - return list(set(third_party_packages) - set(data)) + imports = [] + packages = [] + logging.debug('Traversing tree, start: %s', start_path) + for root, dirs, files in os.walk(start_path): + packages.append(os.path.basename(root)) + for file_name in files: + if file_name[-3:] != ".py": + continue + + with open(os.path.join(root, file_name), "r") as file_object: + for line in file_object: + if line[0] == "#": + continue + if "(" in line: + break + for rex in REGEXP: + s = rex.match(line) + if not s: + continue + for item in s.groups(): + if "," in item: + for match in item.split(","): + imports.append(match.strip()) + else: + to_append = item if "." not in item else item.split(".")[0] + imports.append(to_append.strip()) + third_party_packages = set(imports) - set(set(packages) & set(imports)) + logging.debug('Found third-party packages: %s', third_party_packages) + with open(os.path.join(os.path.dirname(__file__), "stdlib"), "r") as f: + data = [x.strip() for x in f.readlines()] + return list(set(third_party_packages) - set(data)) + def generate_requirements_file(path, imports): - with open(path, "w") as ff: - logging.debug('Writing requirements to file %s', path) - for item in imports: - ff.write(item['name'] + "==" + item['version']) - ff.write("\n") + with open(path, "w") as ff: + logging.debug('Writing requirements to file %s', path) + for item in imports: + ff.write(item['name'] + "==" + item['version']) + ff.write("\n") + def get_imports_info(imports): - result = [] - for item in imports: - try: - data = yarg.get(item) - except HTTPError: - logging.debug('Package does not exist or network problems') - continue - if not data or len(data.release_ids) < 1: - continue - last_release = data.release_ids[-1] - result.append({'name':item,'version':last_release}) - return result + result = [] + for item in imports: + try: + data = yarg.get(item) + except HTTPError: + logging.debug('Package does not exist or network problems') + continue + if not data or len(data.release_ids) < 1: + continue + last_release = data.release_ids[-1] + result.append({'name': item, 'version': last_release}) + return result + def init(args): - print ("Looking for imports") - imports = get_all_imports(args['']) - print ("Getting latest version of packages information from PyPi") - imports_with_info = get_imports_info(imports) - print ("Found third-party imports: " + ", ".join(imports)) - path = args["--savepath"] if args["--savepath"] else os.path.join(args[''],"requirements.txt") - generate_requirements_file(path, imports_with_info) - print ("Successfuly saved requirements file in: " + path) + print("Looking for imports") + imports = get_all_imports(args['']) + print("Getting latest version of packages information from PyPi") + imports_with_info = get_imports_info(imports) + print("Found third-party imports: " + ", ".join(imports)) + path = args["--savepath"] if args["--savepath"] else os.path.join(args[''], "requirements.txt") + generate_requirements_file(path, imports_with_info) + print("Successfuly saved requirements file in: " + path) -def main(): # pragma: no cover + +def main(): # pragma: no cover args = docopt(__doc__, version='xstat 0.1') log_level = logging.WARNING if args['--debug']: @@ -98,5 +107,6 @@ def main(): # pragma: no cover except KeyboardInterrupt: sys.exit(0) + if __name__ == '__main__': - main() # pragma: no cover \ No newline at end of file + main() # pragma: no cover \ No newline at end of file diff --git a/tests/test_pipreqs.py b/tests/test_pipreqs.py index 73430d6..f6dc73e 100755 --- a/tests/test_pipreqs.py +++ b/tests/test_pipreqs.py @@ -14,43 +14,43 @@ from pipreqs import pipreqs class TestPipreqs(unittest.TestCase): - def setUp(self): - self.modules = ['flask', 'requests', 'sqlalchemy', 'docopt', 'nonexistendmodule'] - self.project = os.path.join(os.path.dirname(__file__),"_data") - self.requirements_path = os.path.join(self.project,"requirements.txt") + self.modules = ['flask', 'requests', 'sqlalchemy', 'docopt', 'nonexistendmodule'] + self.project = os.path.join(os.path.dirname(__file__), "_data") + self.requirements_path = os.path.join(self.project, "requirements.txt") def test_get_all_imports(self): - imports = pipreqs.get_all_imports(self.project) - self.assertEqual(len(imports),5, "Incorrect Imports array length") - for item in imports: - self.assertTrue(item in self.modules, "Import is missing") - self.assertFalse("time" in imports) - self.assertFalse("logging" in imports) - self.assertFalse("curses" in imports) - self.assertFalse("__future__" in imports) + imports = pipreqs.get_all_imports(self.project) + self.assertEqual(len(imports), 5, "Incorrect Imports array length") + for item in imports: + self.assertTrue(item in self.modules, "Import is missing") + self.assertFalse("time" in imports) + self.assertFalse("logging" in imports) + self.assertFalse("curses" in imports) + self.assertFalse("__future__" in imports) def test_get_imports_info(self): - imports = pipreqs.get_all_imports(self.project) - with_info = pipreqs.get_imports_info(imports) - # Should contain only 4 Elements without the "nonexistendmodule" - self.assertEqual(len(with_info),4, "Length of imports array with info is wrong") - for item in with_info: - self.assertTrue(item['name'] in self.modules, "Import item appears to be missing") + imports = pipreqs.get_all_imports(self.project) + with_info = pipreqs.get_imports_info(imports) + # Should contain only 4 Elements without the "nonexistendmodule" + self.assertEqual(len(with_info), 4, "Length of imports array with info is wrong") + for item in with_info: + self.assertTrue(item['name'] in self.modules, "Import item appears to be missing") def test_init(self): - pipreqs.init({'':self.project, '--savepath':None}) - assert os.path.exists(self.requirements_path) == 1 - with open(self.requirements_path, "r") as f: - data = f.read() - for item in self.modules[:-1]: - self.assertTrue(item in data) + pipreqs.init({'': self.project, '--savepath': None}) + assert os.path.exists(self.requirements_path) == 1 + with open(self.requirements_path, "r") as f: + data = f.read() + for item in self.modules[:-1]: + self.assertTrue(item in data) def tearDown(self): try: - os.remove(self.requirements_path) + os.remove(self.requirements_path) except OSError: - pass + pass + if __name__ == '__main__': unittest.main()