From a4bd5b552a7688075c3753ba546eb585394b619e Mon Sep 17 00:00:00 2001 From: Hari Sekhon Date: Tue, 18 Feb 2020 13:59:50 +0000 Subject: [PATCH 01/32] fixed MySQL + krbV mappings to be reversed --- pipreqs/mapping | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pipreqs/mapping b/pipreqs/mapping index 6359f8e..06fa00c 100644 --- a/pipreqs/mapping +++ b/pipreqs/mapping @@ -699,7 +699,7 @@ html:pies2overrides htmloutput:nosehtmloutput http:pies2overrides hvad:django_hvad -krbV:krbv +krbv:krbV i99fix:199Fix igraph:python_igraph imdb:IMDbPY @@ -793,7 +793,7 @@ msgpack:msgpack_python mutations:aino_mutations mws:amazon_mws mysql:mysql_connector_repackaged -MySQL-python:MySQLdb +MySQLdb:MySQL-python native_tags:django_native_tags ndg:ndg_httpsclient nereid:trytond_nereid From 2022f25ae96edc7e6a8cd71aaef2c6702fbaedf3 Mon Sep 17 00:00:00 2001 From: AlexPHorta Date: Thu, 27 Feb 2020 00:59:02 -0300 Subject: [PATCH 02/32] Working on issue #88 --- pipreqs/pipreqs.py | 5 +++++ tests/_data/test.py | 4 ++++ tests/test_pipreqs.py | 30 +++++++++++++++++++++++++++--- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/pipreqs/pipreqs.py b/pipreqs/pipreqs.py index 4b817c3..e280841 100755 --- a/pipreqs/pipreqs.py +++ b/pipreqs/pipreqs.py @@ -368,6 +368,11 @@ def diff(file_, imports): def clean(file_, imports): """Remove modules that aren't imported in project from file.""" modules_not_imported = compare_modules(file_, imports) + + if len(modules_not_imported) == 0: + logging.info("Nothing to clean in " + file_) + return + re_remove = re.compile("|".join(modules_not_imported)) to_write = [] diff --git a/tests/_data/test.py b/tests/_data/test.py index cfd039c..fdb6ec3 100644 --- a/tests/_data/test.py +++ b/tests/_data/test.py @@ -31,6 +31,10 @@ from pyflakes.test.test_imports import Test as TestImports # Nose from nose.importer import Importer, add_path, remove_path # loader.py +# see issue #88 +import analytics +import flask_seasurf + import atexit from __future__ import print_function from docopt import docopt diff --git a/tests/test_pipreqs.py b/tests/test_pipreqs.py index dcd75c5..acdac0b 100755 --- a/tests/test_pipreqs.py +++ b/tests/test_pipreqs.py @@ -19,7 +19,7 @@ class TestPipreqs(unittest.TestCase): def setUp(self): self.modules = ['flask', 'requests', 'sqlalchemy', - 'docopt', 'boto', 'ipython', 'pyflakes', 'nose', + 'docopt', 'boto', 'ipython', 'pyflakes', 'nose', 'analytics_python', 'flask_seasurf', 'peewee', 'ujson', 'nonexistendmodule', 'bs4', 'after_method_is_valid_even_if_not_pep8' ] self.modules2 = ['beautifulsoup4'] self.local = ["docopt", "requests", "nose", 'pyflakes'] @@ -33,7 +33,7 @@ class TestPipreqs(unittest.TestCase): def test_get_all_imports(self): imports = pipreqs.get_all_imports(self.project) - self.assertEqual(len(imports), 13) + self.assertEqual(len(imports), 15) # old value, 13 for item in imports: self.assertTrue( item.lower() in self.modules, "Import is missing: " + item) @@ -63,7 +63,7 @@ class TestPipreqs(unittest.TestCase): imports = pipreqs.get_all_imports(self.project) with_info = pipreqs.get_imports_info(imports) # Should contain 10 items without the "nonexistendmodule" and "after_method_is_valid_even_if_not_pep8" - self.assertEqual(len(with_info), 11) + self.assertEqual(len(with_info), 13) # old value, 11 for item in with_info: self.assertTrue( item['name'].lower() in self.modules, @@ -200,6 +200,30 @@ class TestPipreqs(unittest.TestCase): for item in ['beautifulsoup4==4.8.1', 'boto==2.49.0']: self.assertFalse(item.lower() in data) + def test_clean(self): + """ + Test --clean parameter + """ + pipreqs.init({'': self.project, '--savepath': None, '--print': False, + '--use-local': None, '--force': True, '--proxy': None, + '--pypi-server': None, '--diff': None, '--clean': None}) + assert os.path.exists(self.requirements_path) == 1 + # with open(self.requirements_path, "r") as f: + # print('A') + # for l in f: print(l) + pipreqs.init({'': self.project, '--savepath': None, '--print': False, + '--use-local': None, '--force': None, '--proxy': None, + '--pypi-server': None, '--diff': None, + '--clean': self.requirements_path, '--no-pin': True}) + # with open(self.requirements_path, "r") as f: + # print('B') + # for l in f: print(l) + with open(self.requirements_path, "r") as f: + data = f.read().lower() + print(data) + for item in self.modules[:-3]: # ['analytics_python', 'flask_seasurf']: + self.assertTrue(item.lower() in data) + def tearDown(self): """ Remove requiremnts.txt files that were written From 386e677d80e900f740528c8dae32e2a5918c7b18 Mon Sep 17 00:00:00 2001 From: AlexPHorta Date: Thu, 27 Feb 2020 07:54:44 -0300 Subject: [PATCH 03/32] More --clean tests. --- tests/_data_clean/test.py | 65 +++++++++++++++++++++++++++++++++++++++ tests/test_pipreqs.py | 29 ++++++++++++----- 2 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 tests/_data_clean/test.py diff --git a/tests/_data_clean/test.py b/tests/_data_clean/test.py new file mode 100644 index 0000000..8cffb51 --- /dev/null +++ b/tests/_data_clean/test.py @@ -0,0 +1,65 @@ +"""unused import""" +# pylint: disable=undefined-all-variable, import-error, no-absolute-import, too-few-public-methods, missing-docstring +import xml.etree # [unused-import] +import xml.sax # [unused-import] +import os.path as test # [unused-import] +from sys import argv as test2 # [unused-import] +from sys import flags # [unused-import] +# +1:[unused-import,unused-import] +from collections import deque, OrderedDict, Counter +# All imports above should be ignored +import requests # [unused-import] + +# setuptools +import zipimport # command/easy_install.py + +# twisted +from importlib import invalidate_caches # python/test/test_deprecate.py + +# astroid +import zipimport # manager.py +# IPython +from importlib.machinery import all_suffixes # core/completerlib.py +import importlib # html/notebookapp.py + +from IPython.utils.importstring import import_item # Many files + +# pyflakes +# test/test_doctests.py +from pyflakes.test.test_imports import Test as TestImports + +# Nose +from nose.importer import Importer, add_path, remove_path # loader.py + +# see issue #88 +import analytics +import flask_seasurf + +import atexit +from __future__ import print_function +from docopt import docopt +import curses, logging, sqlite3 +import logging +import os +import sqlite3 +import time +import sys +import signal +import bs4 +import nonexistendmodule +import boto as b, peewee as p +# import django +import flask.ext.somext # # # +# from sqlalchemy import model +try: + import ujson as json +except ImportError: + import json + +import models + + +def main(): + pass + +import after_method_is_valid_even_if_not_pep8 diff --git a/tests/test_pipreqs.py b/tests/test_pipreqs.py index acdac0b..849d5a7 100755 --- a/tests/test_pipreqs.py +++ b/tests/test_pipreqs.py @@ -19,11 +19,12 @@ class TestPipreqs(unittest.TestCase): def setUp(self): self.modules = ['flask', 'requests', 'sqlalchemy', - 'docopt', 'boto', 'ipython', 'pyflakes', 'nose', 'analytics_python', 'flask_seasurf', + 'docopt', 'boto', 'ipython', 'pyflakes', 'nose', 'analytics', 'flask_seasurf', 'peewee', 'ujson', 'nonexistendmodule', 'bs4', 'after_method_is_valid_even_if_not_pep8' ] self.modules2 = ['beautifulsoup4'] self.local = ["docopt", "requests", "nose", 'pyflakes'] self.project = os.path.join(os.path.dirname(__file__), "_data") + self.project_clean = os.path.join(os.path.dirname(__file__), "_data_clean") self.project_invalid = os.path.join(os.path.dirname(__file__), "_invalid_data") self.project_with_ignore_directory = os.path.join(os.path.dirname(__file__), "_data_ignore") self.project_with_duplicated_deps = os.path.join(os.path.dirname(__file__), "_data_duplicated_deps") @@ -33,6 +34,7 @@ class TestPipreqs(unittest.TestCase): def test_get_all_imports(self): imports = pipreqs.get_all_imports(self.project) + print(imports) self.assertEqual(len(imports), 15) # old value, 13 for item in imports: self.assertTrue( @@ -208,16 +210,29 @@ class TestPipreqs(unittest.TestCase): '--use-local': None, '--force': True, '--proxy': None, '--pypi-server': None, '--diff': None, '--clean': None}) assert os.path.exists(self.requirements_path) == 1 - # with open(self.requirements_path, "r") as f: - # print('A') - # for l in f: print(l) pipreqs.init({'': self.project, '--savepath': None, '--print': False, '--use-local': None, '--force': None, '--proxy': None, '--pypi-server': None, '--diff': None, '--clean': self.requirements_path, '--no-pin': True}) - # with open(self.requirements_path, "r") as f: - # print('B') - # for l in f: print(l) + with open(self.requirements_path, "r") as f: + data = f.read().lower() + print(data) + for item in self.modules[:-3]: # ['analytics_python', 'flask_seasurf']: + self.assertTrue(item.lower() in data) + + def test_clean_with_extras(self): + """ + Test --clean parameter when there are imports to clean + """ + pipreqs.init({'': self.project, '--savepath': None, '--print': False, + '--use-local': None, '--force': True, '--proxy': None, + '--pypi-server': None, '--diff': None, '--clean': None}) + assert os.path.exists(self.requirements_path) == 1 + # Continua... + pipreqs.init({'': self.project, '--savepath': None, '--print': False, + '--use-local': None, '--force': None, '--proxy': None, + '--pypi-server': None, '--diff': None, + '--clean': self.requirements_path, '--no-pin': True}) with open(self.requirements_path, "r") as f: data = f.read().lower() print(data) From 21d3907e960140f9ac45030af63e8c1721cb1cd8 Mon Sep 17 00:00:00 2001 From: AlexPHorta Date: Thu, 27 Feb 2020 21:24:31 -0300 Subject: [PATCH 04/32] Fixed #88 --- tests/test_pipreqs.py | 200 ++++++++++++++++++++++++++---------------- 1 file changed, 123 insertions(+), 77 deletions(-) diff --git a/tests/test_pipreqs.py b/tests/test_pipreqs.py index 849d5a7..550b29b 100755 --- a/tests/test_pipreqs.py +++ b/tests/test_pipreqs.py @@ -18,24 +18,40 @@ from pipreqs import pipreqs class TestPipreqs(unittest.TestCase): def setUp(self): - self.modules = ['flask', 'requests', 'sqlalchemy', - 'docopt', 'boto', 'ipython', 'pyflakes', 'nose', 'analytics', 'flask_seasurf', - 'peewee', 'ujson', 'nonexistendmodule', 'bs4', 'after_method_is_valid_even_if_not_pep8' ] + self.modules = [ + 'flask', 'requests', 'sqlalchemy', 'docopt', 'boto', 'ipython', + 'pyflakes', 'nose', 'analytics', 'flask_seasurf', 'peewee', + 'ujson', 'nonexistendmodule', 'bs4', + 'after_method_is_valid_even_if_not_pep8' + ] self.modules2 = ['beautifulsoup4'] self.local = ["docopt", "requests", "nose", 'pyflakes'] self.project = os.path.join(os.path.dirname(__file__), "_data") - self.project_clean = os.path.join(os.path.dirname(__file__), "_data_clean") - self.project_invalid = os.path.join(os.path.dirname(__file__), "_invalid_data") - self.project_with_ignore_directory = os.path.join(os.path.dirname(__file__), "_data_ignore") - self.project_with_duplicated_deps = os.path.join(os.path.dirname(__file__), "_data_duplicated_deps") + self.project_clean = os.path.join( + os.path.dirname(__file__), + "_data_clean" + ) + self.project_invalid = os.path.join( + os.path.dirname(__file__), + "_invalid_data" + ) + self.project_with_ignore_directory = os.path.join( + os.path.dirname(__file__), + "_data_ignore" + ) + self.project_with_duplicated_deps = os.path.join( + os.path.dirname(__file__), + "_data_duplicated_deps" + ) self.requirements_path = os.path.join(self.project, "requirements.txt") self.alt_requirement_path = os.path.join( - self.project, "requirements2.txt") + self.project, + "requirements2.txt" + ) def test_get_all_imports(self): imports = pipreqs.get_all_imports(self.project) - print(imports) - self.assertEqual(len(imports), 15) # old value, 13 + self.assertEqual(len(imports), 15) for item in imports: self.assertTrue( item.lower() in self.modules, "Import is missing: " + item) @@ -56,7 +72,8 @@ class TestPipreqs(unittest.TestCase): """ Test that invalid python files cannot be imported. """ - self.assertRaises(SyntaxError, pipreqs.get_all_imports, self.project_invalid) + self.assertRaises( + SyntaxError, pipreqs.get_all_imports, self.project_invalid) def test_get_imports_info(self): """ @@ -64,8 +81,9 @@ class TestPipreqs(unittest.TestCase): """ imports = pipreqs.get_all_imports(self.project) with_info = pipreqs.get_imports_info(imports) - # Should contain 10 items without the "nonexistendmodule" and "after_method_is_valid_even_if_not_pep8" - self.assertEqual(len(with_info), 13) # old value, 11 + # Should contain 10 items without the "nonexistendmodule" and + # "after_method_is_valid_even_if_not_pep8" + self.assertEqual(len(with_info), 13) for item in with_info: self.assertTrue( item['name'].lower() in self.modules, @@ -79,10 +97,12 @@ class TestPipreqs(unittest.TestCase): def test_get_use_local_only(self): """ - Test without checking PyPI, check to see if names of local imports matches what we expect + Test without checking PyPI, check to see if names of local + imports matches what we expect - Note even though pyflakes isn't in requirements.txt, - It's added to locals since it is a development dependency for testing + It's added to locals since it is a development dependency + for testing """ # should find only docopt and requests imports_with_info = pipreqs.get_import_local(self.modules) @@ -91,11 +111,13 @@ class TestPipreqs(unittest.TestCase): def test_init(self): """ - Test that all modules we will test upon, are in requirements file + Test that all modules we will test upon are in requirements file """ - pipreqs.init({'': self.project, '--savepath': None, '--print': False, - '--use-local': None, '--force': True, '--proxy':None, '--pypi-server':None, - '--diff': None, '--clean': None}) + pipreqs.init( + {'': self.project, '--savepath': None, '--print': False, + '--use-local': None, '--force': True, '--proxy': None, + '--pypi-server': None, '--diff': None, '--clean': None} + ) assert os.path.exists(self.requirements_path) == 1 with open(self.requirements_path, "r") as f: data = f.read().lower() @@ -104,11 +126,14 @@ class TestPipreqs(unittest.TestCase): def test_init_local_only(self): """ - Test that items listed in requirements.text are the same as locals expected + Test that items listed in requirements.text are the same + as locals expected """ - pipreqs.init({'': self.project, '--savepath': None, '--print': False, - '--use-local': True, '--force': True, '--proxy':None, '--pypi-server':None, - '--diff': None, '--clean': None}) + pipreqs.init( + {'': self.project, '--savepath': None, '--print': False, + '--use-local': True, '--force': True, '--proxy': None, + '--pypi-server': None, '--diff': None, '--clean': None} + ) assert os.path.exists(self.requirements_path) == 1 with open(self.requirements_path, "r") as f: data = f.readlines() @@ -118,11 +143,14 @@ class TestPipreqs(unittest.TestCase): def test_init_savepath(self): """ - Test that we can save requiremnts.tt correctly to a different path + Test that we can save requirements.txt correctly + to a different path """ - pipreqs.init({'': self.project, '--savepath': - self.alt_requirement_path, '--use-local': None, '--proxy':None, '--pypi-server':None, '--print': False, - "--diff": None, "--clean": None}) + pipreqs.init( + {'': self.project, '--savepath': self.alt_requirement_path, + '--use-local': None, '--proxy': None, '--pypi-server': None, + '--print': False, "--diff": None, "--clean": None} + ) assert os.path.exists(self.alt_requirement_path) == 1 with open(self.alt_requirement_path, "r") as f: data = f.read().lower() @@ -133,13 +161,16 @@ class TestPipreqs(unittest.TestCase): def test_init_overwrite(self): """ - Test that if requiremnts.txt exists, it will not automatically be overwritten + Test that if requiremnts.txt exists, it will not be + automatically overwritten """ with open(self.requirements_path, "w") as f: f.write("should_not_be_overwritten") - pipreqs.init({'': self.project, '--savepath': None, - '--use-local': None, '--force': None, '--proxy':None, '--pypi-server':None, '--print': False, - "--diff": None, "--clean": None}) + pipreqs.init( + {'': self.project, '--savepath': None, '--use-local': None, + '--force': None, '--proxy': None, '--pypi-server': None, + '--print': False, '--diff': None, '--clean': None} + ) assert os.path.exists(self.requirements_path) == 1 with open(self.requirements_path, "r") as f: data = f.read().lower() @@ -147,38 +178,48 @@ class TestPipreqs(unittest.TestCase): def test_get_import_name_without_alias(self): """ - Test that function get_name_without_alias() will work on a string. - - Note: This isn't truly needed when pipreqs is walking the AST to find imports + Test that function get_name_without_alias() + will work on a string. + - Note: This isn't truly needed when pipreqs is walking + the AST to find imports """ import_name_with_alias = "requests as R" expected_import_name_without_alias = "requests" import_name_without_aliases = pipreqs.get_name_without_alias( import_name_with_alias) self.assertEqual( - import_name_without_aliases, expected_import_name_without_alias) + import_name_without_aliases, + expected_import_name_without_alias + ) def test_custom_pypi_server(self): """ Test that trying to get a custom pypi sever fails correctly """ - self.assertRaises(requests.exceptions.MissingSchema, pipreqs.init, {'': self.project, '--savepath': None, '--print': False, - '--use-local': None, '--force': True, '--proxy': None, '--pypi-server': 'nonexistent'}) + self.assertRaises( + requests.exceptions.MissingSchema, pipreqs.init, + {'': self.project, '--savepath': None, '--print': False, + '--use-local': None, '--force': True, '--proxy': None, + '--pypi-server': 'nonexistent'} + ) def test_ignored_directory(self): """ Test --ignore parameter """ pipreqs.init( - {'': self.project_with_ignore_directory, '--savepath': None, '--print': False, - '--use-local': None, '--force': True, - '--proxy':None, - '--pypi-server':None, - '--ignore':'.ignored_dir,.ignore_second', - '--diff': None, - '--clean': None - } - ) - with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: + {'': self.project_with_ignore_directory, '--savepath': None, + '--print': False, '--use-local': None, '--force': True, + '--proxy': None, '--pypi-server': None, + '--ignore': '.ignored_dir,.ignore_second', '--diff': None, + '--clean': None} + ) + with open( + os.path.join( + self.project_with_ignore_directory, + "requirements.txt" + ), "r" + ) as f: data = f.read().lower() for item in ['click', 'getpass']: self.assertFalse(item.lower() in data) @@ -188,16 +229,15 @@ class TestPipreqs(unittest.TestCase): Test --no-pin parameter """ pipreqs.init( - {'': self.project_with_ignore_directory, '--savepath': None, '--print': False, - '--use-local': None, '--force': True, - '--proxy': None, - '--pypi-server': None, - '--diff': None, - '--clean': None, - '--no-pin': True - } - ) - with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: + {'': self.project_with_ignore_directory, '--savepath': None, + '--print': False, '--use-local': None, '--force': True, + '--proxy': None, '--pypi-server': None, '--diff': None, + '--clean': None, '--no-pin': True} + ) + with open(os.path.join( + self.project_with_ignore_directory, + "requirements.txt"), "r" + ) as f: data = f.read().lower() for item in ['beautifulsoup4==4.8.1', 'boto==2.49.0']: self.assertFalse(item.lower() in data) @@ -206,38 +246,44 @@ class TestPipreqs(unittest.TestCase): """ Test --clean parameter """ - pipreqs.init({'': self.project, '--savepath': None, '--print': False, - '--use-local': None, '--force': True, '--proxy': None, - '--pypi-server': None, '--diff': None, '--clean': None}) + pipreqs.init( + {'': self.project, '--savepath': None, '--print': False, + '--use-local': None, '--force': True, '--proxy': None, + '--pypi-server': None, '--diff': None, '--clean': None} + ) assert os.path.exists(self.requirements_path) == 1 - pipreqs.init({'': self.project, '--savepath': None, '--print': False, - '--use-local': None, '--force': None, '--proxy': None, - '--pypi-server': None, '--diff': None, - '--clean': self.requirements_path, '--no-pin': True}) + pipreqs.init( + {'': self.project, '--savepath': None, '--print': False, + '--use-local': None, '--force': None, '--proxy': None, + '--pypi-server': None, '--diff': None, + '--clean': self.requirements_path, '--no-pin': True} + ) with open(self.requirements_path, "r") as f: data = f.read().lower() - print(data) - for item in self.modules[:-3]: # ['analytics_python', 'flask_seasurf']: + for item in self.modules[:-3]: self.assertTrue(item.lower() in data) - def test_clean_with_extras(self): + def test_clean_with_imports_to_clean(self): """ Test --clean parameter when there are imports to clean """ - pipreqs.init({'': self.project, '--savepath': None, '--print': False, - '--use-local': None, '--force': True, '--proxy': None, - '--pypi-server': None, '--diff': None, '--clean': None}) + cleaned_module = 'sqlalchemy' + pipreqs.init( + {'': self.project, '--savepath': None, '--print': False, + '--use-local': None, '--force': True, '--proxy': None, + '--pypi-server': None, '--diff': None, '--clean': None} + ) assert os.path.exists(self.requirements_path) == 1 - # Continua... - pipreqs.init({'': self.project, '--savepath': None, '--print': False, - '--use-local': None, '--force': None, '--proxy': None, - '--pypi-server': None, '--diff': None, - '--clean': self.requirements_path, '--no-pin': True}) + modules_clean = [m for m in self.modules if m != cleaned_module] + pipreqs.init( + {'': self.project_clean, '--savepath': None, + '--print': False, '--use-local': None, '--force': None, + '--proxy': None, '--pypi-server': None, '--diff': None, + '--clean': self.requirements_path, '--no-pin': True} + ) with open(self.requirements_path, "r") as f: data = f.read().lower() - print(data) - for item in self.modules[:-3]: # ['analytics_python', 'flask_seasurf']: - self.assertTrue(item.lower() in data) + self.assertTrue(cleaned_module not in data) def tearDown(self): """ From 7b2b5e9e5880cde1922c0b9c7ac238247f3850f4 Mon Sep 17 00:00:00 2001 From: Pat Myron Date: Tue, 21 Apr 2020 11:17:49 -0700 Subject: [PATCH 05/32] mapping aws-sam-translator https://pypi.org/project/aws-sam-translator/ https://github.com/awslabs/serverless-application-model --- pipreqs/mapping | 1 + 1 file changed, 1 insertion(+) diff --git a/pipreqs/mapping b/pipreqs/mapping index 6f5a469..26b83cb 100644 --- a/pipreqs/mapping +++ b/pipreqs/mapping @@ -999,6 +999,7 @@ ruamel:ruamel.base s2repoze:pysaml2 saga:saga_python saml2:pysaml2 +samtranslator:aws-sam-translator sass:libsass sassc:libsass sasstests:libsass From fc720f18bb5e1689d05ae4f83f4bfef5d173e704 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Singh Date: Thu, 10 Oct 2019 18:34:59 +0530 Subject: [PATCH 06/32] Fixed#133 Sorted `imports` based on `lowercase` package's `name`, similar to `pip freeze`. --- pipreqs/pipreqs.py | 2 ++ tests/test_pipreqs.py | 3 +++ 2 files changed, 5 insertions(+) diff --git a/pipreqs/pipreqs.py b/pipreqs/pipreqs.py index 57147e2..42a4e45 100755 --- a/pipreqs/pipreqs.py +++ b/pipreqs/pipreqs.py @@ -430,6 +430,8 @@ def init(args): imports = local + get_imports_info(difference, proxy=proxy, pypi_server=pypi_server) + # sort imports based on lowercase name of package, similar to `pip freeze`. + imports = sorted(imports, key=lambda x: x['name'].lower()) path = (args["--savepath"] if args["--savepath"] else os.path.join(input_path, "requirements.txt")) diff --git a/tests/test_pipreqs.py b/tests/test_pipreqs.py index dcd75c5..68f7249 100755 --- a/tests/test_pipreqs.py +++ b/tests/test_pipreqs.py @@ -99,6 +99,9 @@ class TestPipreqs(unittest.TestCase): data = f.read().lower() for item in self.modules[:-3]: self.assertTrue(item.lower() in data) + # It should be sorted based on names. + data = data.strip().split('\n') + self.assertEqual(data, sorted(data)) def test_init_local_only(self): """ From bd88dd85cdfc647dcfa6ba1fb234ed80a03b5ded Mon Sep 17 00:00:00 2001 From: Ben Bodenmiller Date: Thu, 9 Jul 2020 16:11:56 -0700 Subject: [PATCH 07/32] Tweak formatting --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 139fa7d..2a33b60 100644 --- a/README.rst +++ b/README.rst @@ -70,5 +70,5 @@ Why not pip freeze? ------------------- - ``pip freeze`` only saves the packages that are installed with ``pip install`` in your environment. -- ``pip freeze`` saves all packages in the environment including those that you don't use in your current project. (if you don't have virtualenv) -- and sometimes you just need to create requirements.txt for a new project without installing modules. +- ``pip freeze`` saves all packages in the environment including those that you don't use in your current project (if you don't have ``virtualenv``). +- and sometimes you just need to create ``requirements.txt`` for a new project without installing modules. From 30d8fab76c41b79652b1b7632c7041fe60339c94 Mon Sep 17 00:00:00 2001 From: John Kruper <36000@users.noreply.github.com> Date: Tue, 10 Nov 2020 10:27:02 -0800 Subject: [PATCH 08/32] Add pyAFQ Mapping --- pipreqs/mapping | 1 + 1 file changed, 1 insertion(+) diff --git a/pipreqs/mapping b/pipreqs/mapping index 6f5a469..77c2ed0 100644 --- a/pipreqs/mapping +++ b/pipreqs/mapping @@ -1,3 +1,4 @@ +AFQ:pyAFQ AG_fft_tools:agpy ANSI:pexpect Adafruit:Adafruit_Libraries From 469baefc1e7219c02f1dfe343e5a3bfbc66603c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Kalemba?= <5924586+pkalemba@users.noreply.github.com> Date: Thu, 10 Dec 2020 10:04:17 +0100 Subject: [PATCH 09/32] Add discord mapping Map discord to discord.py --- pipreqs/mapping | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pipreqs/mapping b/pipreqs/mapping index 6f5a469..e4be845 100644 --- a/pipreqs/mapping +++ b/pipreqs/mapping @@ -22,6 +22,7 @@ Kittens:astro_kittens Levenshtein:python_Levenshtein Lifetime:Zope2 MethodObject:ExtensionClass +MySQL-python:MySQLdb OFS:Zope2 OpenGL:PyOpenGL OpenSSL:pyOpenSSL @@ -592,6 +593,7 @@ devtools:tg.devtools dgis:2gis dhtmlparser:pyDHTMLParser digitalocean:python_digitalocean +discord:discord.py distribute_setup:ez_setup distutils2:Distutils2 django:Django @@ -701,7 +703,6 @@ html:pies2overrides htmloutput:nosehtmloutput http:pies2overrides hvad:django_hvad -krbV:krbv i99fix:199Fix igraph:python_igraph imdb:IMDbPY @@ -727,6 +728,7 @@ keyczar:python_keyczar keyedcache:django_keyedcache keystoneclient:python_keystoneclient kickstarter:kickstart +krbV:krbv kss:kss.core kuyruk:Kuyruk langconv:AdvancedLangConv @@ -798,7 +800,6 @@ msgpack:msgpack_python mutations:aino_mutations mws:amazon_mws mysql:mysql_connector_repackaged -MySQL-python:MySQLdb native_tags:django_native_tags ndg:ndg_httpsclient nereid:trytond_nereid From bcd0be47d0f90e9cf47ed8d19392e56817fc220f Mon Sep 17 00:00:00 2001 From: SwiftWinds <12981958+SwiftWinds@users.noreply.github.com> Date: Sat, 13 Mar 2021 14:46:02 -0800 Subject: [PATCH 10/32] Add PyFunctional mapping Maps `functional` to `pyfunctional`. Fixes #232. --- pipreqs/mapping | 1 + 1 file changed, 1 insertion(+) diff --git a/pipreqs/mapping b/pipreqs/mapping index 6f5a469..7eb67dc 100644 --- a/pipreqs/mapping +++ b/pipreqs/mapping @@ -13,6 +13,7 @@ Crypto:pycryptodome Cryptodome:pycryptodomex FSM:pexpect FiftyOneDegrees:51degrees_mobile_detector_v3_wrapper +functional:pyfunctional GeoBaseMain:GeoBasesDev GeoBases:GeoBasesDev Globals:Zope2 From 7b69881e76934167a3a012796376895ccebe796f Mon Sep 17 00:00:00 2001 From: alan-barzilay Date: Wed, 24 Mar 2021 16:21:56 -0300 Subject: [PATCH 11/32] Upgrade pip before running tests on travis This should ensure that all tests use the same version of pip and this should hopefully fix the pypy build that is using pip 19 --- .travis.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 324b044..bfe9a9d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,8 +17,12 @@ matrix: - python: 3.6 env: TOX_ENV=flake8 +# This should ensure that all tests use the same pip version +before_install: + - python -m pip install --upgrade pip + # Use tox to run tests on Travis-CI to keep one unified method of running tests in any environment -install: +install: - pip install coverage coveralls tox # Command to run tests, e.g. python setup.py test From b1725c7409f98cc7a97b3440bb64160cc266a200 Mon Sep 17 00:00:00 2001 From: alan-barzilay Date: Wed, 24 Mar 2021 18:33:15 -0300 Subject: [PATCH 12/32] Upgrading pypy to pypy3 Maybe forcing pypy to use python 3 will solve the issue (although it works fine with python 2.7 at the moment) --- .travis.yml | 4 ++-- tox.ini | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index bfe9a9d..5772134 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,8 +12,8 @@ matrix: env: TOX_ENV=py34 - python: 2.7 env: TOX_ENV=py27 - - python: pypy - env: TOX_ENV=pypy + - python: pypy3 + env: TOX_ENV=pypy3 - python: 3.6 env: TOX_ENV=flake8 diff --git a/tox.ini b/tox.ini index 28a1dfa..554b3c1 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py27, py34, py35, py36, pypy, flake8 +envlist = py27, py34, py35, py36, pypy3, flake8 [testenv] setenv = From b7e061f73a534dddc6d6de974c52dd58dedbcea2 Mon Sep 17 00:00:00 2001 From: alan-barzilay Date: Wed, 24 Mar 2021 18:40:30 -0300 Subject: [PATCH 13/32] Remove unecessary pip upgrade step --- .travis.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5772134..7988659 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,10 +17,6 @@ matrix: - python: 3.6 env: TOX_ENV=flake8 -# This should ensure that all tests use the same pip version -before_install: - - python -m pip install --upgrade pip - # Use tox to run tests on Travis-CI to keep one unified method of running tests in any environment install: - pip install coverage coveralls tox From 4eae4794a0548710099ae22ce5b9fcfd2a8845b7 Mon Sep 17 00:00:00 2001 From: Jake Teo Date: Thu, 25 Mar 2021 17:37:00 +0800 Subject: [PATCH 14/32] New Option for Dynamic Versioning (#1) * added new option for dynamic versioning * added quotes for dynamic options Co-authored-by: Siyang --- AUTHORS.rst | 3 ++- README.rst | 2 +- pipreqs/pipreqs.py | 34 +++++++++++++++++++++--- tests/test_pipreqs.py | 61 ++++++++++++++++++++++++++++++++++++------- 4 files changed, 85 insertions(+), 15 deletions(-) mode change 100755 => 100644 pipreqs/pipreqs.py mode change 100755 => 100644 tests/test_pipreqs.py diff --git a/AUTHORS.rst b/AUTHORS.rst index eaa038a..2f31bac 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -10,4 +10,5 @@ Development Lead Contributors ------------ -None yet. Why not be the first? +* Jake Teo +* Jerome Chan diff --git a/README.rst b/README.rst index 139fa7d..93b1735 100644 --- a/README.rst +++ b/README.rst @@ -49,7 +49,7 @@ Usage --force Overwrite existing requirements.txt --diff Compare modules in requirements.txt to project imports. --clean Clean up requirements.txt by removing modules that are not imported in project. - --no-pin Omit version of output packages. + --dynamic Enables dynamic version updates by 'minor', 'micro' or 'all' schemes. Example ------- diff --git a/pipreqs/pipreqs.py b/pipreqs/pipreqs.py old mode 100755 new mode 100644 index 57147e2..069c28a --- a/pipreqs/pipreqs.py +++ b/pipreqs/pipreqs.py @@ -31,7 +31,8 @@ Options: imports. --clean Clean up requirements.txt by removing modules that are not imported in project. - --no-pin Omit version of output packages. + --dynamic Enables dynamic version updates by 'minor', + 'micro' or 'all' schemes. """ from __future__ import print_function, absolute_import from contextlib import contextmanager @@ -392,6 +393,28 @@ def clean(file_, imports): logging.info("Successfully cleaned up requirements in " + file_) +def dynamic_versioning(scheme, imports): + """Enables dynamic versioning by minor, micro or all scheme.""" + if scheme == "all": + imports = [{"name": item["name"], "version": ""} for item in imports] + else: + for item in imports: + version = item["version"] + arr = version.split(".") + length = len(arr) + if length != 1: + if scheme == "minor": + arr = arr[0] + + elif scheme == "micro" and length >= 2: + arr = arr[:2] + arr = ".".join(arr) + + arr = arr + ".*" + item["version"] = arr + return imports + + def init(args): encoding = args.get('--encoding') extra_ignore_dirs = args.get('--ignore') @@ -450,8 +473,13 @@ def init(args): "use --force to overwrite it") return - if args.get('--no-pin'): - imports = [{'name': item["name"], 'version': ''} for item in imports] + if args["--dynamic"]: + scheme = args.get("--dynamic") + if scheme in ["minor", "micro", "all"]: + imports = dynamic_versioning(scheme, imports) + else: + raise ValueError("Invalid argument for dynamic scheme, " + "use 'minor', 'micro' or 'all' instead") if args["--print"]: output_requirements(imports) diff --git a/tests/test_pipreqs.py b/tests/test_pipreqs.py old mode 100755 new mode 100644 index dcd75c5..b150c9a --- a/tests/test_pipreqs.py +++ b/tests/test_pipreqs.py @@ -93,7 +93,7 @@ class TestPipreqs(unittest.TestCase): """ pipreqs.init({'': self.project, '--savepath': None, '--print': False, '--use-local': None, '--force': True, '--proxy':None, '--pypi-server':None, - '--diff': None, '--clean': None}) + '--diff': None, '--clean': None, '--dynamic': None}) assert os.path.exists(self.requirements_path) == 1 with open(self.requirements_path, "r") as f: data = f.read().lower() @@ -106,7 +106,7 @@ class TestPipreqs(unittest.TestCase): """ pipreqs.init({'': self.project, '--savepath': None, '--print': False, '--use-local': True, '--force': True, '--proxy':None, '--pypi-server':None, - '--diff': None, '--clean': None}) + '--diff': None, '--clean': None, '--dynamic': None}) assert os.path.exists(self.requirements_path) == 1 with open(self.requirements_path, "r") as f: data = f.readlines() @@ -120,7 +120,7 @@ class TestPipreqs(unittest.TestCase): """ pipreqs.init({'': self.project, '--savepath': self.alt_requirement_path, '--use-local': None, '--proxy':None, '--pypi-server':None, '--print': False, - "--diff": None, "--clean": None}) + "--diff": None, "--clean": None, '--dynamic': None}) assert os.path.exists(self.alt_requirement_path) == 1 with open(self.alt_requirement_path, "r") as f: data = f.read().lower() @@ -137,7 +137,7 @@ class TestPipreqs(unittest.TestCase): f.write("should_not_be_overwritten") pipreqs.init({'': self.project, '--savepath': None, '--use-local': None, '--force': None, '--proxy':None, '--pypi-server':None, '--print': False, - "--diff": None, "--clean": None}) + "--diff": None, "--clean": None, '--dynamic': None}) assert os.path.exists(self.requirements_path) == 1 with open(self.requirements_path, "r") as f: data = f.read().lower() @@ -173,7 +173,8 @@ class TestPipreqs(unittest.TestCase): '--pypi-server':None, '--ignore':'.ignored_dir,.ignore_second', '--diff': None, - '--clean': None + '--clean': None, + '--dynamic': None } ) with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: @@ -181,9 +182,9 @@ class TestPipreqs(unittest.TestCase): for item in ['click', 'getpass']: self.assertFalse(item.lower() in data) - def test_omit_version(self): + def test_dynamic_version_all_scheme(self): """ - Test --no-pin parameter + Test --dynamic=all """ pipreqs.init( {'': self.project_with_ignore_directory, '--savepath': None, '--print': False, @@ -192,13 +193,53 @@ class TestPipreqs(unittest.TestCase): '--pypi-server': None, '--diff': None, '--clean': None, - '--no-pin': True + '--dynamic': 'all' } ) with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: data = f.read().lower() - for item in ['beautifulsoup4==4.8.1', 'boto==2.49.0']: - self.assertFalse(item.lower() in data) + for item in ['beautifulsoup4', 'boto']: + self.assertTrue(item.lower() in data) + + def test_dynamic_version_micro_scheme(self): + """ + Test --dynamic=micro + """ + pipreqs.init( + {'': self.project_with_ignore_directory, '--savepath': None, '--print': False, + '--use-local': None, '--force': True, + '--proxy': None, + '--pypi-server': None, + '--diff': None, + '--clean': None, + '--dynamic': 'micro' + } + ) + with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: + data = f.readlines() + for item in data: + asterisk = item.strip().split(".")[2] + self.assertEqual(asterisk, "*",) + + def test_dynamic_version_minor_scheme(self): + """ + Test --dynamic=minor + """ + pipreqs.init( + {'': self.project_with_ignore_directory, '--savepath': None, '--print': False, + '--use-local': None, '--force': True, + '--proxy': None, + '--pypi-server': None, + '--diff': None, + '--clean': None, + '--dynamic': 'minor' + } + ) + with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: + data = f.readlines() + for item in data: + asterisk = item.strip().split(".")[1] + self.assertEqual(asterisk, "*",) def tearDown(self): """ From c7c91fcabe66a4550ef5513d8a411ae544b16bc9 Mon Sep 17 00:00:00 2001 From: ryan-rozario Date: Fri, 26 Mar 2021 23:56:20 +0400 Subject: [PATCH 15/32] Mapping for github3 --- pipreqs/mapping | 1 + 1 file changed, 1 insertion(+) diff --git a/pipreqs/mapping b/pipreqs/mapping index cf90aa5..73173b4 100644 --- a/pipreqs/mapping +++ b/pipreqs/mapping @@ -679,6 +679,7 @@ geventwebsocket:gevent_websocket gflags:python_gflags git:GitPython github:PyGithub +github3:github3.py gitpy:git_py globusonline:globusonline_transfer_api_client google:protobuf From 69a884a4c4980e0914d1de0056c2a3df496dd563 Mon Sep 17 00:00:00 2001 From: Siyang Date: Mon, 29 Mar 2021 21:35:34 +0800 Subject: [PATCH 16/32] changes based on discussions w maintainer --- pipreqs/pipreqs.py | 59 ++++++++++++++++++++----------------------- tests/test_pipreqs.py | 38 +++++++++++++++------------- 2 files changed, 48 insertions(+), 49 deletions(-) diff --git a/pipreqs/pipreqs.py b/pipreqs/pipreqs.py index 069c28a..05ce0be 100644 --- a/pipreqs/pipreqs.py +++ b/pipreqs/pipreqs.py @@ -31,8 +31,11 @@ Options: imports. --clean Clean up requirements.txt by removing modules that are not imported in project. - --dynamic Enables dynamic version updates by 'minor', - 'micro' or 'all' schemes. + --mode Enables dynamic versioning with , + or schemes. + | e.g. Flask~=1.1.2 + | e.g. Flask>=1.1.2 + | e.g. Flask """ from __future__ import print_function, absolute_import from contextlib import contextmanager @@ -162,21 +165,21 @@ def filter_line(line): return len(line) > 0 and line[0] != "#" -def generate_requirements_file(path, imports): +def generate_requirements_file(path, imports, symbol): with _open(path, "w") as out_file: logging.debug('Writing {num} requirements: {imports} to {file}'.format( num=len(imports), file=path, imports=", ".join([x['name'] for x in imports]) )) - fmt = '{name}=={version}' + fmt = '{name}' + symbol + '{version}' out_file.write('\n'.join( fmt.format(**item) if item['version'] else '{name}'.format(**item) for item in imports) + '\n') -def output_requirements(imports): - generate_requirements_file('-', imports) +def output_requirements(imports, symbol): + generate_requirements_file('-', imports, symbol) def get_imports_info( @@ -394,25 +397,17 @@ def clean(file_, imports): def dynamic_versioning(scheme, imports): - """Enables dynamic versioning by minor, micro or all scheme.""" - if scheme == "all": + """Enables dynamic versioning with , or schemes.""" + if scheme == "no-pin": imports = [{"name": item["name"], "version": ""} for item in imports] + symbol = "" + elif scheme == "gt": + symbol = ">=" + elif scheme == "compat": + symbol = "~=" else: - for item in imports: - version = item["version"] - arr = version.split(".") - length = len(arr) - if length != 1: - if scheme == "minor": - arr = arr[0] - - elif scheme == "micro" and length >= 2: - arr = arr[:2] - arr = ".".join(arr) - - arr = arr + ".*" - item["version"] = arr - return imports + symbol = "==" + return imports, symbol def init(args): @@ -473,19 +468,21 @@ def init(args): "use --force to overwrite it") return - if args["--dynamic"]: - scheme = args.get("--dynamic") - if scheme in ["minor", "micro", "all"]: - imports = dynamic_versioning(scheme, imports) + if args["--mode"]: + scheme = args.get("--mode") + if scheme in ["compat", "gt", "no-pin"]: + imports, symbol = dynamic_versioning(scheme, imports) else: - raise ValueError("Invalid argument for dynamic scheme, " - "use 'minor', 'micro' or 'all' instead") + raise ValueError("Invalid argument for mode flag, " + "use 'compat', 'gt' or 'no-pin' instead") + else: + symbol = "==" if args["--print"]: - output_requirements(imports) + output_requirements(imports, symbol) logging.info("Successfully output requirements") else: - generate_requirements_file(path, imports) + generate_requirements_file(path, imports, symbol) logging.info("Successfully saved requirements file in " + path) diff --git a/tests/test_pipreqs.py b/tests/test_pipreqs.py index b150c9a..1270058 100644 --- a/tests/test_pipreqs.py +++ b/tests/test_pipreqs.py @@ -93,7 +93,7 @@ class TestPipreqs(unittest.TestCase): """ pipreqs.init({'': self.project, '--savepath': None, '--print': False, '--use-local': None, '--force': True, '--proxy':None, '--pypi-server':None, - '--diff': None, '--clean': None, '--dynamic': None}) + '--diff': None, '--clean': None, '--mode': None}) assert os.path.exists(self.requirements_path) == 1 with open(self.requirements_path, "r") as f: data = f.read().lower() @@ -106,7 +106,7 @@ class TestPipreqs(unittest.TestCase): """ pipreqs.init({'': self.project, '--savepath': None, '--print': False, '--use-local': True, '--force': True, '--proxy':None, '--pypi-server':None, - '--diff': None, '--clean': None, '--dynamic': None}) + '--diff': None, '--clean': None, '--mode': None}) assert os.path.exists(self.requirements_path) == 1 with open(self.requirements_path, "r") as f: data = f.readlines() @@ -120,7 +120,7 @@ class TestPipreqs(unittest.TestCase): """ pipreqs.init({'': self.project, '--savepath': self.alt_requirement_path, '--use-local': None, '--proxy':None, '--pypi-server':None, '--print': False, - "--diff": None, "--clean": None, '--dynamic': None}) + "--diff": None, "--clean": None, '--mode': None}) assert os.path.exists(self.alt_requirement_path) == 1 with open(self.alt_requirement_path, "r") as f: data = f.read().lower() @@ -137,7 +137,7 @@ class TestPipreqs(unittest.TestCase): f.write("should_not_be_overwritten") pipreqs.init({'': self.project, '--savepath': None, '--use-local': None, '--force': None, '--proxy':None, '--pypi-server':None, '--print': False, - "--diff": None, "--clean": None, '--dynamic': None}) + "--diff": None, "--clean": None, '--mode': None}) assert os.path.exists(self.requirements_path) == 1 with open(self.requirements_path, "r") as f: data = f.read().lower() @@ -174,7 +174,7 @@ class TestPipreqs(unittest.TestCase): '--ignore':'.ignored_dir,.ignore_second', '--diff': None, '--clean': None, - '--dynamic': None + '--mode': None } ) with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: @@ -182,9 +182,9 @@ class TestPipreqs(unittest.TestCase): for item in ['click', 'getpass']: self.assertFalse(item.lower() in data) - def test_dynamic_version_all_scheme(self): + def test_dynamic_version_no_pin_scheme(self): """ - Test --dynamic=all + Test --mode=no-pin """ pipreqs.init( {'': self.project_with_ignore_directory, '--savepath': None, '--print': False, @@ -193,7 +193,7 @@ class TestPipreqs(unittest.TestCase): '--pypi-server': None, '--diff': None, '--clean': None, - '--dynamic': 'all' + '--mode': 'no-pin' } ) with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: @@ -201,9 +201,9 @@ class TestPipreqs(unittest.TestCase): for item in ['beautifulsoup4', 'boto']: self.assertTrue(item.lower() in data) - def test_dynamic_version_micro_scheme(self): + def test_dynamic_version_gt_scheme(self): """ - Test --dynamic=micro + Test --mode=gt """ pipreqs.init( {'': self.project_with_ignore_directory, '--savepath': None, '--print': False, @@ -212,18 +212,19 @@ class TestPipreqs(unittest.TestCase): '--pypi-server': None, '--diff': None, '--clean': None, - '--dynamic': 'micro' + '--mode': 'gt' } ) with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: data = f.readlines() for item in data: - asterisk = item.strip().split(".")[2] - self.assertEqual(asterisk, "*",) + symbol = '>=' + message = 'symbol is not in item' + self.assertIn(symbol, item, message) - def test_dynamic_version_minor_scheme(self): + def test_dynamic_version_compat_scheme(self): """ - Test --dynamic=minor + Test --mode=compat """ pipreqs.init( {'': self.project_with_ignore_directory, '--savepath': None, '--print': False, @@ -232,14 +233,15 @@ class TestPipreqs(unittest.TestCase): '--pypi-server': None, '--diff': None, '--clean': None, - '--dynamic': 'minor' + '--mode': 'compat' } ) with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: data = f.readlines() for item in data: - asterisk = item.strip().split(".")[1] - self.assertEqual(asterisk, "*",) + symbol = '~=' + message = 'symbol is not in item' + self.assertIn(symbol, item, message) def tearDown(self): """ From 5dc02aa2facbb0e9fdc4d9f42ed538adeefbae94 Mon Sep 17 00:00:00 2001 From: Jake Date: Mon, 29 Mar 2021 22:16:45 +0800 Subject: [PATCH 17/32] remove obsolete '==' --- pipreqs/pipreqs.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pipreqs/pipreqs.py b/pipreqs/pipreqs.py index 04d9f47..20aae68 100644 --- a/pipreqs/pipreqs.py +++ b/pipreqs/pipreqs.py @@ -410,8 +410,6 @@ def dynamic_versioning(scheme, imports): symbol = ">=" elif scheme == "compat": symbol = "~=" - else: - symbol = "==" return imports, symbol From bab012b49172c5b0b88495f8bd4f72f5183d3648 Mon Sep 17 00:00:00 2001 From: Johannes Thomsen Date: Tue, 20 Apr 2021 16:32:54 +0200 Subject: [PATCH 18/32] Update stdlib with dataclasses Part of the standard lib since 3.7: https://docs.python.org/3.7/library/dataclasses.html --- pipreqs/stdlib | 1 + 1 file changed, 1 insertion(+) diff --git a/pipreqs/stdlib b/pipreqs/stdlib index 470fd5c..e2c3ca3 100644 --- a/pipreqs/stdlib +++ b/pipreqs/stdlib @@ -133,6 +133,7 @@ curses curses.ascii curses.panel curses.textpad +dataclasses datetime dbhash dbm From 537458f2dfb86eb4e77c989ebb488a5a9359fb83 Mon Sep 17 00:00:00 2001 From: Simon Ondracek Date: Wed, 21 Apr 2021 13:16:20 +0200 Subject: [PATCH 19/32] Add hydra-core mapping Maps `hydra` to `hydra-core`. Fixes #244. --- pipreqs/mapping | 1 + 1 file changed, 1 insertion(+) diff --git a/pipreqs/mapping b/pipreqs/mapping index 73173b4..c1729eb 100644 --- a/pipreqs/mapping +++ b/pipreqs/mapping @@ -706,6 +706,7 @@ html:pies2overrides htmloutput:nosehtmloutput http:pies2overrides hvad:django_hvad +hydra:hydra-core i99fix:199Fix igraph:python_igraph imdb:IMDbPY From b188c8ba8383754e5f3f8ec3cc0965498edaddd9 Mon Sep 17 00:00:00 2001 From: "Rahul M. Juliato" Date: Mon, 26 Apr 2021 12:05:41 -0300 Subject: [PATCH 20/32] Decaptalized file name in log msg When trying to generate requirements.txt and file is already existent, the user message produced asks for "Requirements.txt" instead of "requirements.txt". This may cause some trouble when used in case sensitive env, as well as in automated scripts. --- pipreqs/pipreqs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pipreqs/pipreqs.py b/pipreqs/pipreqs.py index 20aae68..6c936aa 100644 --- a/pipreqs/pipreqs.py +++ b/pipreqs/pipreqs.py @@ -469,7 +469,7 @@ def init(args): and not args["--savepath"] and not args["--force"] and os.path.exists(path)): - logging.warning("Requirements.txt already exists, " + logging.warning("requirements.txt already exists, " "use --force to overwrite it") return From 4dd2c0916d4228e130aff0736da69690c1c8d77b Mon Sep 17 00:00:00 2001 From: Paul Date: Tue, 27 Apr 2021 20:40:26 +0200 Subject: [PATCH 21/32] Added secrets to standard libraries file Is new in Python 3.6+ --- pipreqs/stdlib | 1 + 1 file changed, 1 insertion(+) diff --git a/pipreqs/stdlib b/pipreqs/stdlib index 470fd5c..13fc98a 100644 --- a/pipreqs/stdlib +++ b/pipreqs/stdlib @@ -370,6 +370,7 @@ robotparser runpy sched ScrolledText +secrets select selectors sets From 90102acdbb23c09574d27df8bd1f568d34e0cfd3 Mon Sep 17 00:00:00 2001 From: alan-barzilay Date: Tue, 4 May 2021 20:39:47 -0300 Subject: [PATCH 22/32] Revert all commits since last release By reverting all commits done since release v0.4.10 we will have the master branch synchronized with the latest release available in pipy. All commits done since the latest release will be moved to another branch called `next` where we will centralize development. Once we are ready for a new release of pipreqs, the `next` branch will be merged back on to master and a new release will be made. This change will make development more organized and will avoid new issues from users complaining about features only present in master not working on their installation of pipreqs. I would also like to thank @pedroteosousa for his help on reverting and squashing all commits --- .travis.yml | 6 +- AUTHORS.rst | 3 +- HISTORY.rst | 5 - README.rst | 9 +- pipreqs/mapping | 10 +- pipreqs/pipreqs.py | 54 +++------- pipreqs/stdlib | 2 - tests/_data/test.py | 4 - tests/_data_clean/test.py | 65 ------------ tests/test_pipreqs.py | 202 ++++++++------------------------------ tox.ini | 2 +- 11 files changed, 62 insertions(+), 300 deletions(-) mode change 100644 => 100755 pipreqs/pipreqs.py delete mode 100644 tests/_data_clean/test.py mode change 100644 => 100755 tests/test_pipreqs.py diff --git a/.travis.yml b/.travis.yml index 7988659..324b044 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,13 +12,13 @@ matrix: env: TOX_ENV=py34 - python: 2.7 env: TOX_ENV=py27 - - python: pypy3 - env: TOX_ENV=pypy3 + - python: pypy + env: TOX_ENV=pypy - python: 3.6 env: TOX_ENV=flake8 # Use tox to run tests on Travis-CI to keep one unified method of running tests in any environment -install: +install: - pip install coverage coveralls tox # Command to run tests, e.g. python setup.py test diff --git a/AUTHORS.rst b/AUTHORS.rst index 2f31bac..eaa038a 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -10,5 +10,4 @@ Development Lead Contributors ------------ -* Jake Teo -* Jerome Chan +None yet. Why not be the first? diff --git a/HISTORY.rst b/HISTORY.rst index cb4d47b..b9d17e7 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -3,11 +3,6 @@ History ------- -0.4.11 (2020-03-29) --------------------- - -* Implement '--mode' (Jake Teo, Jerome Chan) - 0.4.8 (2017-06-30) -------------------- diff --git a/README.rst b/README.rst index 07fee33..139fa7d 100644 --- a/README.rst +++ b/README.rst @@ -49,10 +49,7 @@ Usage --force Overwrite existing requirements.txt --diff Compare modules in requirements.txt to project imports. --clean Clean up requirements.txt by removing modules that are not imported in project. - --mode Enables dynamic versioning with , or schemes. - | e.g. Flask~=1.1.2 - | e.g. Flask>=1.1.2 - | e.g. Flask + --no-pin Omit version of output packages. Example ------- @@ -73,5 +70,5 @@ Why not pip freeze? ------------------- - ``pip freeze`` only saves the packages that are installed with ``pip install`` in your environment. -- ``pip freeze`` saves all packages in the environment including those that you don't use in your current project (if you don't have ``virtualenv``). -- and sometimes you just need to create ``requirements.txt`` for a new project without installing modules. +- ``pip freeze`` saves all packages in the environment including those that you don't use in your current project. (if you don't have virtualenv) +- and sometimes you just need to create requirements.txt for a new project without installing modules. diff --git a/pipreqs/mapping b/pipreqs/mapping index c1729eb..6f5a469 100644 --- a/pipreqs/mapping +++ b/pipreqs/mapping @@ -1,4 +1,3 @@ -AFQ:pyAFQ AG_fft_tools:agpy ANSI:pexpect Adafruit:Adafruit_Libraries @@ -14,7 +13,6 @@ Crypto:pycryptodome Cryptodome:pycryptodomex FSM:pexpect FiftyOneDegrees:51degrees_mobile_detector_v3_wrapper -functional:pyfunctional GeoBaseMain:GeoBasesDev GeoBases:GeoBasesDev Globals:Zope2 @@ -24,7 +22,6 @@ Kittens:astro_kittens Levenshtein:python_Levenshtein Lifetime:Zope2 MethodObject:ExtensionClass -MySQLdb:MySQL-python OFS:Zope2 OpenGL:PyOpenGL OpenSSL:pyOpenSSL @@ -595,7 +592,6 @@ devtools:tg.devtools dgis:2gis dhtmlparser:pyDHTMLParser digitalocean:python_digitalocean -discord:discord.py distribute_setup:ez_setup distutils2:Distutils2 django:Django @@ -679,7 +675,6 @@ geventwebsocket:gevent_websocket gflags:python_gflags git:GitPython github:PyGithub -github3:github3.py gitpy:git_py globusonline:globusonline_transfer_api_client google:protobuf @@ -706,7 +701,7 @@ html:pies2overrides htmloutput:nosehtmloutput http:pies2overrides hvad:django_hvad -hydra:hydra-core +krbV:krbv i99fix:199Fix igraph:python_igraph imdb:IMDbPY @@ -732,7 +727,6 @@ keyczar:python_keyczar keyedcache:django_keyedcache keystoneclient:python_keystoneclient kickstarter:kickstart -krbv:krbV kss:kss.core kuyruk:Kuyruk langconv:AdvancedLangConv @@ -804,6 +798,7 @@ msgpack:msgpack_python mutations:aino_mutations mws:amazon_mws mysql:mysql_connector_repackaged +MySQL-python:MySQLdb native_tags:django_native_tags ndg:ndg_httpsclient nereid:trytond_nereid @@ -1004,7 +999,6 @@ ruamel:ruamel.base s2repoze:pysaml2 saga:saga_python saml2:pysaml2 -samtranslator:aws-sam-translator sass:libsass sassc:libsass sasstests:libsass diff --git a/pipreqs/pipreqs.py b/pipreqs/pipreqs.py old mode 100644 new mode 100755 index 6c936aa..4b817c3 --- a/pipreqs/pipreqs.py +++ b/pipreqs/pipreqs.py @@ -31,11 +31,7 @@ Options: imports. --clean Clean up requirements.txt by removing modules that are not imported in project. - --mode Enables dynamic versioning with , - or schemes. - | e.g. Flask~=1.1.2 - | e.g. Flask>=1.1.2 - | e.g. Flask + --no-pin Omit version of output packages. """ from __future__ import print_function, absolute_import from contextlib import contextmanager @@ -161,25 +157,25 @@ def get_all_imports( return list(packages - data) -def filter_line(line): - return len(line) > 0 and line[0] != "#" +def filter_line(l): + return len(l) > 0 and l[0] != "#" -def generate_requirements_file(path, imports, symbol): +def generate_requirements_file(path, imports): with _open(path, "w") as out_file: logging.debug('Writing {num} requirements: {imports} to {file}'.format( num=len(imports), file=path, imports=", ".join([x['name'] for x in imports]) )) - fmt = '{name}' + symbol + '{version}' + fmt = '{name}=={version}' out_file.write('\n'.join( fmt.format(**item) if item['version'] else '{name}'.format(**item) for item in imports) + '\n') -def output_requirements(imports, symbol): - generate_requirements_file('-', imports, symbol) +def output_requirements(imports): + generate_requirements_file('-', imports) def get_imports_info( @@ -372,11 +368,6 @@ def diff(file_, imports): def clean(file_, imports): """Remove modules that aren't imported in project from file.""" modules_not_imported = compare_modules(file_, imports) - - if len(modules_not_imported) == 0: - logging.info("Nothing to clean in " + file_) - return - re_remove = re.compile("|".join(modules_not_imported)) to_write = [] @@ -401,18 +392,6 @@ def clean(file_, imports): logging.info("Successfully cleaned up requirements in " + file_) -def dynamic_versioning(scheme, imports): - """Enables dynamic versioning with , or schemes.""" - if scheme == "no-pin": - imports = [{"name": item["name"], "version": ""} for item in imports] - symbol = "" - elif scheme == "gt": - symbol = ">=" - elif scheme == "compat": - symbol = "~=" - return imports, symbol - - def init(args): encoding = args.get('--encoding') extra_ignore_dirs = args.get('--ignore') @@ -451,8 +430,6 @@ def init(args): imports = local + get_imports_info(difference, proxy=proxy, pypi_server=pypi_server) - # sort imports based on lowercase name of package, similar to `pip freeze`. - imports = sorted(imports, key=lambda x: x['name'].lower()) path = (args["--savepath"] if args["--savepath"] else os.path.join(input_path, "requirements.txt")) @@ -469,25 +446,18 @@ def init(args): and not args["--savepath"] and not args["--force"] and os.path.exists(path)): - logging.warning("requirements.txt already exists, " + logging.warning("Requirements.txt already exists, " "use --force to overwrite it") return - if args["--mode"]: - scheme = args.get("--mode") - if scheme in ["compat", "gt", "no-pin"]: - imports, symbol = dynamic_versioning(scheme, imports) - else: - raise ValueError("Invalid argument for mode flag, " - "use 'compat', 'gt' or 'no-pin' instead") - else: - symbol = "==" + if args.get('--no-pin'): + imports = [{'name': item["name"], 'version': ''} for item in imports] if args["--print"]: - output_requirements(imports, symbol) + output_requirements(imports) logging.info("Successfully output requirements") else: - generate_requirements_file(path, imports, symbol) + generate_requirements_file(path, imports) logging.info("Successfully saved requirements file in " + path) diff --git a/pipreqs/stdlib b/pipreqs/stdlib index c2c1fdd..470fd5c 100644 --- a/pipreqs/stdlib +++ b/pipreqs/stdlib @@ -133,7 +133,6 @@ curses curses.ascii curses.panel curses.textpad -dataclasses datetime dbhash dbm @@ -371,7 +370,6 @@ robotparser runpy sched ScrolledText -secrets select selectors sets diff --git a/tests/_data/test.py b/tests/_data/test.py index fdb6ec3..cfd039c 100644 --- a/tests/_data/test.py +++ b/tests/_data/test.py @@ -31,10 +31,6 @@ from pyflakes.test.test_imports import Test as TestImports # Nose from nose.importer import Importer, add_path, remove_path # loader.py -# see issue #88 -import analytics -import flask_seasurf - import atexit from __future__ import print_function from docopt import docopt diff --git a/tests/_data_clean/test.py b/tests/_data_clean/test.py deleted file mode 100644 index 8cffb51..0000000 --- a/tests/_data_clean/test.py +++ /dev/null @@ -1,65 +0,0 @@ -"""unused import""" -# pylint: disable=undefined-all-variable, import-error, no-absolute-import, too-few-public-methods, missing-docstring -import xml.etree # [unused-import] -import xml.sax # [unused-import] -import os.path as test # [unused-import] -from sys import argv as test2 # [unused-import] -from sys import flags # [unused-import] -# +1:[unused-import,unused-import] -from collections import deque, OrderedDict, Counter -# All imports above should be ignored -import requests # [unused-import] - -# setuptools -import zipimport # command/easy_install.py - -# twisted -from importlib import invalidate_caches # python/test/test_deprecate.py - -# astroid -import zipimport # manager.py -# IPython -from importlib.machinery import all_suffixes # core/completerlib.py -import importlib # html/notebookapp.py - -from IPython.utils.importstring import import_item # Many files - -# pyflakes -# test/test_doctests.py -from pyflakes.test.test_imports import Test as TestImports - -# Nose -from nose.importer import Importer, add_path, remove_path # loader.py - -# see issue #88 -import analytics -import flask_seasurf - -import atexit -from __future__ import print_function -from docopt import docopt -import curses, logging, sqlite3 -import logging -import os -import sqlite3 -import time -import sys -import signal -import bs4 -import nonexistendmodule -import boto as b, peewee as p -# import django -import flask.ext.somext # # # -# from sqlalchemy import model -try: - import ujson as json -except ImportError: - import json - -import models - - -def main(): - pass - -import after_method_is_valid_even_if_not_pep8 diff --git a/tests/test_pipreqs.py b/tests/test_pipreqs.py old mode 100644 new mode 100755 index f82d3db..dcd75c5 --- a/tests/test_pipreqs.py +++ b/tests/test_pipreqs.py @@ -18,40 +18,22 @@ from pipreqs import pipreqs class TestPipreqs(unittest.TestCase): def setUp(self): - self.modules = [ - 'flask', 'requests', 'sqlalchemy', 'docopt', 'boto', 'ipython', - 'pyflakes', 'nose', 'analytics', 'flask_seasurf', 'peewee', - 'ujson', 'nonexistendmodule', 'bs4', - 'after_method_is_valid_even_if_not_pep8' - ] + self.modules = ['flask', 'requests', 'sqlalchemy', + 'docopt', 'boto', 'ipython', 'pyflakes', 'nose', + 'peewee', 'ujson', 'nonexistendmodule', 'bs4', 'after_method_is_valid_even_if_not_pep8' ] self.modules2 = ['beautifulsoup4'] self.local = ["docopt", "requests", "nose", 'pyflakes'] self.project = os.path.join(os.path.dirname(__file__), "_data") - self.project_clean = os.path.join( - os.path.dirname(__file__), - "_data_clean" - ) - self.project_invalid = os.path.join( - os.path.dirname(__file__), - "_invalid_data" - ) - self.project_with_ignore_directory = os.path.join( - os.path.dirname(__file__), - "_data_ignore" - ) - self.project_with_duplicated_deps = os.path.join( - os.path.dirname(__file__), - "_data_duplicated_deps" - ) + self.project_invalid = os.path.join(os.path.dirname(__file__), "_invalid_data") + self.project_with_ignore_directory = os.path.join(os.path.dirname(__file__), "_data_ignore") + self.project_with_duplicated_deps = os.path.join(os.path.dirname(__file__), "_data_duplicated_deps") self.requirements_path = os.path.join(self.project, "requirements.txt") self.alt_requirement_path = os.path.join( - self.project, - "requirements2.txt" - ) + self.project, "requirements2.txt") def test_get_all_imports(self): imports = pipreqs.get_all_imports(self.project) - self.assertEqual(len(imports), 15) + self.assertEqual(len(imports), 13) for item in imports: self.assertTrue( item.lower() in self.modules, "Import is missing: " + item) @@ -72,8 +54,7 @@ class TestPipreqs(unittest.TestCase): """ Test that invalid python files cannot be imported. """ - self.assertRaises( - SyntaxError, pipreqs.get_all_imports, self.project_invalid) + self.assertRaises(SyntaxError, pipreqs.get_all_imports, self.project_invalid) def test_get_imports_info(self): """ @@ -81,9 +62,8 @@ class TestPipreqs(unittest.TestCase): """ imports = pipreqs.get_all_imports(self.project) with_info = pipreqs.get_imports_info(imports) - # Should contain 10 items without the "nonexistendmodule" and - # "after_method_is_valid_even_if_not_pep8" - self.assertEqual(len(with_info), 13) + # Should contain 10 items without the "nonexistendmodule" and "after_method_is_valid_even_if_not_pep8" + self.assertEqual(len(with_info), 11) for item in with_info: self.assertTrue( item['name'].lower() in self.modules, @@ -97,12 +77,10 @@ class TestPipreqs(unittest.TestCase): def test_get_use_local_only(self): """ - Test without checking PyPI, check to see if names of local - imports matches what we expect + Test without checking PyPI, check to see if names of local imports matches what we expect - Note even though pyflakes isn't in requirements.txt, - It's added to locals since it is a development dependency - for testing + It's added to locals since it is a development dependency for testing """ # should find only docopt and requests imports_with_info = pipreqs.get_import_local(self.modules) @@ -111,28 +89,24 @@ class TestPipreqs(unittest.TestCase): def test_init(self): """ - Test that all modules we will test upon are in requirements file + Test that all modules we will test upon, are in requirements file """ pipreqs.init({'': self.project, '--savepath': None, '--print': False, '--use-local': None, '--force': True, '--proxy':None, '--pypi-server':None, - '--diff': None, '--clean': None, '--mode': None}) + '--diff': None, '--clean': None}) assert os.path.exists(self.requirements_path) == 1 with open(self.requirements_path, "r") as f: data = f.read().lower() for item in self.modules[:-3]: self.assertTrue(item.lower() in data) - # It should be sorted based on names. - data = data.strip().split('\n') - self.assertEqual(data, sorted(data)) def test_init_local_only(self): """ - Test that items listed in requirements.text are the same - as locals expected + Test that items listed in requirements.text are the same as locals expected """ pipreqs.init({'': self.project, '--savepath': None, '--print': False, '--use-local': True, '--force': True, '--proxy':None, '--pypi-server':None, - '--diff': None, '--clean': None, '--mode': None}) + '--diff': None, '--clean': None}) assert os.path.exists(self.requirements_path) == 1 with open(self.requirements_path, "r") as f: data = f.readlines() @@ -142,12 +116,11 @@ class TestPipreqs(unittest.TestCase): def test_init_savepath(self): """ - Test that we can save requirements.txt correctly - to a different path + Test that we can save requiremnts.tt correctly to a different path """ - pipreqs.init({'': self.project, '--savepath': self.alt_requirement_path, - '--use-local': None, '--proxy':None, '--pypi-server':None, '--print': False, - '--diff': None, '--clean': None, '--mode': None}) + pipreqs.init({'': self.project, '--savepath': + self.alt_requirement_path, '--use-local': None, '--proxy':None, '--pypi-server':None, '--print': False, + "--diff": None, "--clean": None}) assert os.path.exists(self.alt_requirement_path) == 1 with open(self.alt_requirement_path, "r") as f: data = f.read().lower() @@ -158,14 +131,13 @@ class TestPipreqs(unittest.TestCase): def test_init_overwrite(self): """ - Test that if requiremnts.txt exists, it will not be - automatically overwritten + Test that if requiremnts.txt exists, it will not automatically be overwritten """ with open(self.requirements_path, "w") as f: f.write("should_not_be_overwritten") - pipreqs.init({'': self.project, '--savepath': None, '--use-local': None, - '--force': None, '--proxy':None, '--pypi-server':None, '--print': False, - '--diff': None, '--clean': None, '--mode': None}) + pipreqs.init({'': self.project, '--savepath': None, + '--use-local': None, '--force': None, '--proxy':None, '--pypi-server':None, '--print': False, + "--diff": None, "--clean": None}) assert os.path.exists(self.requirements_path) == 1 with open(self.requirements_path, "r") as f: data = f.read().lower() @@ -173,43 +145,35 @@ class TestPipreqs(unittest.TestCase): def test_get_import_name_without_alias(self): """ - Test that function get_name_without_alias() - will work on a string. - - Note: This isn't truly needed when pipreqs is walking - the AST to find imports + Test that function get_name_without_alias() will work on a string. + - Note: This isn't truly needed when pipreqs is walking the AST to find imports """ import_name_with_alias = "requests as R" expected_import_name_without_alias = "requests" import_name_without_aliases = pipreqs.get_name_without_alias( import_name_with_alias) self.assertEqual( - import_name_without_aliases, - expected_import_name_without_alias - ) + import_name_without_aliases, expected_import_name_without_alias) def test_custom_pypi_server(self): """ Test that trying to get a custom pypi sever fails correctly """ - self.assertRaises( - requests.exceptions.MissingSchema, pipreqs.init, - {'': self.project, '--savepath': None, '--print': False, - '--use-local': None, '--force': True, '--proxy': None, - '--pypi-server': 'nonexistent'} - ) + self.assertRaises(requests.exceptions.MissingSchema, pipreqs.init, {'': self.project, '--savepath': None, '--print': False, + '--use-local': None, '--force': True, '--proxy': None, '--pypi-server': 'nonexistent'}) def test_ignored_directory(self): """ Test --ignore parameter """ pipreqs.init( - {'': self.project_with_ignore_directory, '--savepath': None, - '--print': False, '--use-local': None, '--force': True, - '--proxy':None, '--pypi-server':None, + {'': self.project_with_ignore_directory, '--savepath': None, '--print': False, + '--use-local': None, '--force': True, + '--proxy':None, + '--pypi-server':None, '--ignore':'.ignored_dir,.ignore_second', '--diff': None, - '--clean': None, - '--mode': None + '--clean': None } ) with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: @@ -217,27 +181,9 @@ class TestPipreqs(unittest.TestCase): for item in ['click', 'getpass']: self.assertFalse(item.lower() in data) - def test_dynamic_version_no_pin_scheme(self): + def test_omit_version(self): """ - Test --mode=no-pin - """ - pipreqs.init( - {'': self.project_with_ignore_directory, '--savepath': None, - '--print': False, '--use-local': None, '--force': True, - '--proxy': None, '--pypi-server': None, - '--diff': None, - '--clean': None, - '--mode': 'no-pin' - } - ) - with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: - data = f.read().lower() - for item in ['beautifulsoup4', 'boto']: - self.assertTrue(item.lower() in data) - - def test_dynamic_version_gt_scheme(self): - """ - Test --mode=gt + Test --no-pin parameter """ pipreqs.init( {'': self.project_with_ignore_directory, '--savepath': None, '--print': False, @@ -246,81 +192,13 @@ class TestPipreqs(unittest.TestCase): '--pypi-server': None, '--diff': None, '--clean': None, - '--mode': 'gt' + '--no-pin': True } ) with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: - data = f.readlines() - for item in data: - symbol = '>=' - message = 'symbol is not in item' - self.assertIn(symbol, item, message) - - def test_dynamic_version_compat_scheme(self): - """ - Test --mode=compat - """ - pipreqs.init( - {'': self.project_with_ignore_directory, '--savepath': None, '--print': False, - '--use-local': None, '--force': True, - '--proxy': None, - '--pypi-server': None, - '--diff': None, - '--clean': None, - '--mode': 'compat' - } - ) - with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: - data = f.readlines() - for item in data: - symbol = '~=' - message = 'symbol is not in item' - self.assertIn(symbol, item, message) - - def test_clean(self): - """ - Test --clean parameter - """ - pipreqs.init( - {'': self.project, '--savepath': None, '--print': False, - '--use-local': None, '--force': True, '--proxy': None, - '--pypi-server': None, '--diff': None, '--clean': None, - '--mode': None} - ) - assert os.path.exists(self.requirements_path) == 1 - pipreqs.init( - {'': self.project, '--savepath': None, '--print': False, - '--use-local': None, '--force': None, '--proxy': None, - '--pypi-server': None, '--diff': None, - '--clean': self.requirements_path, '--mode': 'non-pin'} - ) - with open(self.requirements_path, "r") as f: data = f.read().lower() - for item in self.modules[:-3]: - self.assertTrue(item.lower() in data) - - def test_clean_with_imports_to_clean(self): - """ - Test --clean parameter when there are imports to clean - """ - cleaned_module = 'sqlalchemy' - pipreqs.init( - {'': self.project, '--savepath': None, '--print': False, - '--use-local': None, '--force': True, '--proxy': None, - '--pypi-server': None, '--diff': None, '--clean': None, - '--mode': None} - ) - assert os.path.exists(self.requirements_path) == 1 - modules_clean = [m for m in self.modules if m != cleaned_module] - pipreqs.init( - {'': self.project_clean, '--savepath': None, - '--print': False, '--use-local': None, '--force': None, - '--proxy': None, '--pypi-server': None, '--diff': None, - '--clean': self.requirements_path, '--mode': 'non-pin'} - ) - with open(self.requirements_path, "r") as f: - data = f.read().lower() - self.assertTrue(cleaned_module not in data) + for item in ['beautifulsoup4==4.8.1', 'boto==2.49.0']: + self.assertFalse(item.lower() in data) def tearDown(self): """ diff --git a/tox.ini b/tox.ini index 554b3c1..28a1dfa 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py27, py34, py35, py36, pypy3, flake8 +envlist = py27, py34, py35, py36, pypy, flake8 [testenv] setenv = From 8001001e9c53fd05b69ddcf71721da61515dfe61 Mon Sep 17 00:00:00 2001 From: Alan Barzilay Date: Sat, 4 Sep 2021 15:12:27 -0300 Subject: [PATCH 23/32] Revert "Revert all commits since last release" This reverts commit 90102acdbb23c09574d27df8bd1f568d34e0cfd3. Now that we are ready to make a new release we can revert the revert and hopefuly never have to solve a mess like this again to keep master synchronized with the latest release --- .travis.yml | 6 +- AUTHORS.rst | 3 +- HISTORY.rst | 5 + README.rst | 9 +- pipreqs/mapping | 10 +- pipreqs/pipreqs.py | 54 +++++++--- pipreqs/stdlib | 2 + tests/_data/test.py | 4 + tests/_data_clean/test.py | 65 ++++++++++++ tests/test_pipreqs.py | 202 ++++++++++++++++++++++++++++++-------- tox.ini | 2 +- 11 files changed, 300 insertions(+), 62 deletions(-) mode change 100755 => 100644 pipreqs/pipreqs.py create mode 100644 tests/_data_clean/test.py mode change 100755 => 100644 tests/test_pipreqs.py diff --git a/.travis.yml b/.travis.yml index 324b044..7988659 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,13 +12,13 @@ matrix: env: TOX_ENV=py34 - python: 2.7 env: TOX_ENV=py27 - - python: pypy - env: TOX_ENV=pypy + - python: pypy3 + env: TOX_ENV=pypy3 - python: 3.6 env: TOX_ENV=flake8 # Use tox to run tests on Travis-CI to keep one unified method of running tests in any environment -install: +install: - pip install coverage coveralls tox # Command to run tests, e.g. python setup.py test diff --git a/AUTHORS.rst b/AUTHORS.rst index eaa038a..2f31bac 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -10,4 +10,5 @@ Development Lead Contributors ------------ -None yet. Why not be the first? +* Jake Teo +* Jerome Chan diff --git a/HISTORY.rst b/HISTORY.rst index b9d17e7..cb4d47b 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -3,6 +3,11 @@ History ------- +0.4.11 (2020-03-29) +-------------------- + +* Implement '--mode' (Jake Teo, Jerome Chan) + 0.4.8 (2017-06-30) -------------------- diff --git a/README.rst b/README.rst index 139fa7d..07fee33 100644 --- a/README.rst +++ b/README.rst @@ -49,7 +49,10 @@ Usage --force Overwrite existing requirements.txt --diff Compare modules in requirements.txt to project imports. --clean Clean up requirements.txt by removing modules that are not imported in project. - --no-pin Omit version of output packages. + --mode Enables dynamic versioning with , or schemes. + | e.g. Flask~=1.1.2 + | e.g. Flask>=1.1.2 + | e.g. Flask Example ------- @@ -70,5 +73,5 @@ Why not pip freeze? ------------------- - ``pip freeze`` only saves the packages that are installed with ``pip install`` in your environment. -- ``pip freeze`` saves all packages in the environment including those that you don't use in your current project. (if you don't have virtualenv) -- and sometimes you just need to create requirements.txt for a new project without installing modules. +- ``pip freeze`` saves all packages in the environment including those that you don't use in your current project (if you don't have ``virtualenv``). +- and sometimes you just need to create ``requirements.txt`` for a new project without installing modules. diff --git a/pipreqs/mapping b/pipreqs/mapping index 6f5a469..c1729eb 100644 --- a/pipreqs/mapping +++ b/pipreqs/mapping @@ -1,3 +1,4 @@ +AFQ:pyAFQ AG_fft_tools:agpy ANSI:pexpect Adafruit:Adafruit_Libraries @@ -13,6 +14,7 @@ Crypto:pycryptodome Cryptodome:pycryptodomex FSM:pexpect FiftyOneDegrees:51degrees_mobile_detector_v3_wrapper +functional:pyfunctional GeoBaseMain:GeoBasesDev GeoBases:GeoBasesDev Globals:Zope2 @@ -22,6 +24,7 @@ Kittens:astro_kittens Levenshtein:python_Levenshtein Lifetime:Zope2 MethodObject:ExtensionClass +MySQLdb:MySQL-python OFS:Zope2 OpenGL:PyOpenGL OpenSSL:pyOpenSSL @@ -592,6 +595,7 @@ devtools:tg.devtools dgis:2gis dhtmlparser:pyDHTMLParser digitalocean:python_digitalocean +discord:discord.py distribute_setup:ez_setup distutils2:Distutils2 django:Django @@ -675,6 +679,7 @@ geventwebsocket:gevent_websocket gflags:python_gflags git:GitPython github:PyGithub +github3:github3.py gitpy:git_py globusonline:globusonline_transfer_api_client google:protobuf @@ -701,7 +706,7 @@ html:pies2overrides htmloutput:nosehtmloutput http:pies2overrides hvad:django_hvad -krbV:krbv +hydra:hydra-core i99fix:199Fix igraph:python_igraph imdb:IMDbPY @@ -727,6 +732,7 @@ keyczar:python_keyczar keyedcache:django_keyedcache keystoneclient:python_keystoneclient kickstarter:kickstart +krbv:krbV kss:kss.core kuyruk:Kuyruk langconv:AdvancedLangConv @@ -798,7 +804,6 @@ msgpack:msgpack_python mutations:aino_mutations mws:amazon_mws mysql:mysql_connector_repackaged -MySQL-python:MySQLdb native_tags:django_native_tags ndg:ndg_httpsclient nereid:trytond_nereid @@ -999,6 +1004,7 @@ ruamel:ruamel.base s2repoze:pysaml2 saga:saga_python saml2:pysaml2 +samtranslator:aws-sam-translator sass:libsass sassc:libsass sasstests:libsass diff --git a/pipreqs/pipreqs.py b/pipreqs/pipreqs.py old mode 100755 new mode 100644 index 4b817c3..6c936aa --- a/pipreqs/pipreqs.py +++ b/pipreqs/pipreqs.py @@ -31,7 +31,11 @@ Options: imports. --clean Clean up requirements.txt by removing modules that are not imported in project. - --no-pin Omit version of output packages. + --mode Enables dynamic versioning with , + or schemes. + | e.g. Flask~=1.1.2 + | e.g. Flask>=1.1.2 + | e.g. Flask """ from __future__ import print_function, absolute_import from contextlib import contextmanager @@ -157,25 +161,25 @@ def get_all_imports( return list(packages - data) -def filter_line(l): - return len(l) > 0 and l[0] != "#" +def filter_line(line): + return len(line) > 0 and line[0] != "#" -def generate_requirements_file(path, imports): +def generate_requirements_file(path, imports, symbol): with _open(path, "w") as out_file: logging.debug('Writing {num} requirements: {imports} to {file}'.format( num=len(imports), file=path, imports=", ".join([x['name'] for x in imports]) )) - fmt = '{name}=={version}' + fmt = '{name}' + symbol + '{version}' out_file.write('\n'.join( fmt.format(**item) if item['version'] else '{name}'.format(**item) for item in imports) + '\n') -def output_requirements(imports): - generate_requirements_file('-', imports) +def output_requirements(imports, symbol): + generate_requirements_file('-', imports, symbol) def get_imports_info( @@ -368,6 +372,11 @@ def diff(file_, imports): def clean(file_, imports): """Remove modules that aren't imported in project from file.""" modules_not_imported = compare_modules(file_, imports) + + if len(modules_not_imported) == 0: + logging.info("Nothing to clean in " + file_) + return + re_remove = re.compile("|".join(modules_not_imported)) to_write = [] @@ -392,6 +401,18 @@ def clean(file_, imports): logging.info("Successfully cleaned up requirements in " + file_) +def dynamic_versioning(scheme, imports): + """Enables dynamic versioning with , or schemes.""" + if scheme == "no-pin": + imports = [{"name": item["name"], "version": ""} for item in imports] + symbol = "" + elif scheme == "gt": + symbol = ">=" + elif scheme == "compat": + symbol = "~=" + return imports, symbol + + def init(args): encoding = args.get('--encoding') extra_ignore_dirs = args.get('--ignore') @@ -430,6 +451,8 @@ def init(args): imports = local + get_imports_info(difference, proxy=proxy, pypi_server=pypi_server) + # sort imports based on lowercase name of package, similar to `pip freeze`. + imports = sorted(imports, key=lambda x: x['name'].lower()) path = (args["--savepath"] if args["--savepath"] else os.path.join(input_path, "requirements.txt")) @@ -446,18 +469,25 @@ def init(args): and not args["--savepath"] and not args["--force"] and os.path.exists(path)): - logging.warning("Requirements.txt already exists, " + logging.warning("requirements.txt already exists, " "use --force to overwrite it") return - if args.get('--no-pin'): - imports = [{'name': item["name"], 'version': ''} for item in imports] + if args["--mode"]: + scheme = args.get("--mode") + if scheme in ["compat", "gt", "no-pin"]: + imports, symbol = dynamic_versioning(scheme, imports) + else: + raise ValueError("Invalid argument for mode flag, " + "use 'compat', 'gt' or 'no-pin' instead") + else: + symbol = "==" if args["--print"]: - output_requirements(imports) + output_requirements(imports, symbol) logging.info("Successfully output requirements") else: - generate_requirements_file(path, imports) + generate_requirements_file(path, imports, symbol) logging.info("Successfully saved requirements file in " + path) diff --git a/pipreqs/stdlib b/pipreqs/stdlib index 470fd5c..c2c1fdd 100644 --- a/pipreqs/stdlib +++ b/pipreqs/stdlib @@ -133,6 +133,7 @@ curses curses.ascii curses.panel curses.textpad +dataclasses datetime dbhash dbm @@ -370,6 +371,7 @@ robotparser runpy sched ScrolledText +secrets select selectors sets diff --git a/tests/_data/test.py b/tests/_data/test.py index cfd039c..fdb6ec3 100644 --- a/tests/_data/test.py +++ b/tests/_data/test.py @@ -31,6 +31,10 @@ from pyflakes.test.test_imports import Test as TestImports # Nose from nose.importer import Importer, add_path, remove_path # loader.py +# see issue #88 +import analytics +import flask_seasurf + import atexit from __future__ import print_function from docopt import docopt diff --git a/tests/_data_clean/test.py b/tests/_data_clean/test.py new file mode 100644 index 0000000..8cffb51 --- /dev/null +++ b/tests/_data_clean/test.py @@ -0,0 +1,65 @@ +"""unused import""" +# pylint: disable=undefined-all-variable, import-error, no-absolute-import, too-few-public-methods, missing-docstring +import xml.etree # [unused-import] +import xml.sax # [unused-import] +import os.path as test # [unused-import] +from sys import argv as test2 # [unused-import] +from sys import flags # [unused-import] +# +1:[unused-import,unused-import] +from collections import deque, OrderedDict, Counter +# All imports above should be ignored +import requests # [unused-import] + +# setuptools +import zipimport # command/easy_install.py + +# twisted +from importlib import invalidate_caches # python/test/test_deprecate.py + +# astroid +import zipimport # manager.py +# IPython +from importlib.machinery import all_suffixes # core/completerlib.py +import importlib # html/notebookapp.py + +from IPython.utils.importstring import import_item # Many files + +# pyflakes +# test/test_doctests.py +from pyflakes.test.test_imports import Test as TestImports + +# Nose +from nose.importer import Importer, add_path, remove_path # loader.py + +# see issue #88 +import analytics +import flask_seasurf + +import atexit +from __future__ import print_function +from docopt import docopt +import curses, logging, sqlite3 +import logging +import os +import sqlite3 +import time +import sys +import signal +import bs4 +import nonexistendmodule +import boto as b, peewee as p +# import django +import flask.ext.somext # # # +# from sqlalchemy import model +try: + import ujson as json +except ImportError: + import json + +import models + + +def main(): + pass + +import after_method_is_valid_even_if_not_pep8 diff --git a/tests/test_pipreqs.py b/tests/test_pipreqs.py old mode 100755 new mode 100644 index dcd75c5..f82d3db --- a/tests/test_pipreqs.py +++ b/tests/test_pipreqs.py @@ -18,22 +18,40 @@ from pipreqs import pipreqs class TestPipreqs(unittest.TestCase): def setUp(self): - self.modules = ['flask', 'requests', 'sqlalchemy', - 'docopt', 'boto', 'ipython', 'pyflakes', 'nose', - 'peewee', 'ujson', 'nonexistendmodule', 'bs4', 'after_method_is_valid_even_if_not_pep8' ] + self.modules = [ + 'flask', 'requests', 'sqlalchemy', 'docopt', 'boto', 'ipython', + 'pyflakes', 'nose', 'analytics', 'flask_seasurf', 'peewee', + 'ujson', 'nonexistendmodule', 'bs4', + 'after_method_is_valid_even_if_not_pep8' + ] self.modules2 = ['beautifulsoup4'] self.local = ["docopt", "requests", "nose", 'pyflakes'] self.project = os.path.join(os.path.dirname(__file__), "_data") - self.project_invalid = os.path.join(os.path.dirname(__file__), "_invalid_data") - self.project_with_ignore_directory = os.path.join(os.path.dirname(__file__), "_data_ignore") - self.project_with_duplicated_deps = os.path.join(os.path.dirname(__file__), "_data_duplicated_deps") + self.project_clean = os.path.join( + os.path.dirname(__file__), + "_data_clean" + ) + self.project_invalid = os.path.join( + os.path.dirname(__file__), + "_invalid_data" + ) + self.project_with_ignore_directory = os.path.join( + os.path.dirname(__file__), + "_data_ignore" + ) + self.project_with_duplicated_deps = os.path.join( + os.path.dirname(__file__), + "_data_duplicated_deps" + ) self.requirements_path = os.path.join(self.project, "requirements.txt") self.alt_requirement_path = os.path.join( - self.project, "requirements2.txt") + self.project, + "requirements2.txt" + ) def test_get_all_imports(self): imports = pipreqs.get_all_imports(self.project) - self.assertEqual(len(imports), 13) + self.assertEqual(len(imports), 15) for item in imports: self.assertTrue( item.lower() in self.modules, "Import is missing: " + item) @@ -54,7 +72,8 @@ class TestPipreqs(unittest.TestCase): """ Test that invalid python files cannot be imported. """ - self.assertRaises(SyntaxError, pipreqs.get_all_imports, self.project_invalid) + self.assertRaises( + SyntaxError, pipreqs.get_all_imports, self.project_invalid) def test_get_imports_info(self): """ @@ -62,8 +81,9 @@ class TestPipreqs(unittest.TestCase): """ imports = pipreqs.get_all_imports(self.project) with_info = pipreqs.get_imports_info(imports) - # Should contain 10 items without the "nonexistendmodule" and "after_method_is_valid_even_if_not_pep8" - self.assertEqual(len(with_info), 11) + # Should contain 10 items without the "nonexistendmodule" and + # "after_method_is_valid_even_if_not_pep8" + self.assertEqual(len(with_info), 13) for item in with_info: self.assertTrue( item['name'].lower() in self.modules, @@ -77,10 +97,12 @@ class TestPipreqs(unittest.TestCase): def test_get_use_local_only(self): """ - Test without checking PyPI, check to see if names of local imports matches what we expect + Test without checking PyPI, check to see if names of local + imports matches what we expect - Note even though pyflakes isn't in requirements.txt, - It's added to locals since it is a development dependency for testing + It's added to locals since it is a development dependency + for testing """ # should find only docopt and requests imports_with_info = pipreqs.get_import_local(self.modules) @@ -89,24 +111,28 @@ class TestPipreqs(unittest.TestCase): def test_init(self): """ - Test that all modules we will test upon, are in requirements file + Test that all modules we will test upon are in requirements file """ pipreqs.init({'': self.project, '--savepath': None, '--print': False, '--use-local': None, '--force': True, '--proxy':None, '--pypi-server':None, - '--diff': None, '--clean': None}) + '--diff': None, '--clean': None, '--mode': None}) assert os.path.exists(self.requirements_path) == 1 with open(self.requirements_path, "r") as f: data = f.read().lower() for item in self.modules[:-3]: self.assertTrue(item.lower() in data) + # It should be sorted based on names. + data = data.strip().split('\n') + self.assertEqual(data, sorted(data)) def test_init_local_only(self): """ - Test that items listed in requirements.text are the same as locals expected + Test that items listed in requirements.text are the same + as locals expected """ pipreqs.init({'': self.project, '--savepath': None, '--print': False, '--use-local': True, '--force': True, '--proxy':None, '--pypi-server':None, - '--diff': None, '--clean': None}) + '--diff': None, '--clean': None, '--mode': None}) assert os.path.exists(self.requirements_path) == 1 with open(self.requirements_path, "r") as f: data = f.readlines() @@ -116,11 +142,12 @@ class TestPipreqs(unittest.TestCase): def test_init_savepath(self): """ - Test that we can save requiremnts.tt correctly to a different path + Test that we can save requirements.txt correctly + to a different path """ - pipreqs.init({'': self.project, '--savepath': - self.alt_requirement_path, '--use-local': None, '--proxy':None, '--pypi-server':None, '--print': False, - "--diff": None, "--clean": None}) + pipreqs.init({'': self.project, '--savepath': self.alt_requirement_path, + '--use-local': None, '--proxy':None, '--pypi-server':None, '--print': False, + '--diff': None, '--clean': None, '--mode': None}) assert os.path.exists(self.alt_requirement_path) == 1 with open(self.alt_requirement_path, "r") as f: data = f.read().lower() @@ -131,13 +158,14 @@ class TestPipreqs(unittest.TestCase): def test_init_overwrite(self): """ - Test that if requiremnts.txt exists, it will not automatically be overwritten + Test that if requiremnts.txt exists, it will not be + automatically overwritten """ with open(self.requirements_path, "w") as f: f.write("should_not_be_overwritten") - pipreqs.init({'': self.project, '--savepath': None, - '--use-local': None, '--force': None, '--proxy':None, '--pypi-server':None, '--print': False, - "--diff": None, "--clean": None}) + pipreqs.init({'': self.project, '--savepath': None, '--use-local': None, + '--force': None, '--proxy':None, '--pypi-server':None, '--print': False, + '--diff': None, '--clean': None, '--mode': None}) assert os.path.exists(self.requirements_path) == 1 with open(self.requirements_path, "r") as f: data = f.read().lower() @@ -145,35 +173,43 @@ class TestPipreqs(unittest.TestCase): def test_get_import_name_without_alias(self): """ - Test that function get_name_without_alias() will work on a string. - - Note: This isn't truly needed when pipreqs is walking the AST to find imports + Test that function get_name_without_alias() + will work on a string. + - Note: This isn't truly needed when pipreqs is walking + the AST to find imports """ import_name_with_alias = "requests as R" expected_import_name_without_alias = "requests" import_name_without_aliases = pipreqs.get_name_without_alias( import_name_with_alias) self.assertEqual( - import_name_without_aliases, expected_import_name_without_alias) + import_name_without_aliases, + expected_import_name_without_alias + ) def test_custom_pypi_server(self): """ Test that trying to get a custom pypi sever fails correctly """ - self.assertRaises(requests.exceptions.MissingSchema, pipreqs.init, {'': self.project, '--savepath': None, '--print': False, - '--use-local': None, '--force': True, '--proxy': None, '--pypi-server': 'nonexistent'}) + self.assertRaises( + requests.exceptions.MissingSchema, pipreqs.init, + {'': self.project, '--savepath': None, '--print': False, + '--use-local': None, '--force': True, '--proxy': None, + '--pypi-server': 'nonexistent'} + ) def test_ignored_directory(self): """ Test --ignore parameter """ pipreqs.init( - {'': self.project_with_ignore_directory, '--savepath': None, '--print': False, - '--use-local': None, '--force': True, - '--proxy':None, - '--pypi-server':None, + {'': self.project_with_ignore_directory, '--savepath': None, + '--print': False, '--use-local': None, '--force': True, + '--proxy':None, '--pypi-server':None, '--ignore':'.ignored_dir,.ignore_second', '--diff': None, - '--clean': None + '--clean': None, + '--mode': None } ) with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: @@ -181,9 +217,27 @@ class TestPipreqs(unittest.TestCase): for item in ['click', 'getpass']: self.assertFalse(item.lower() in data) - def test_omit_version(self): + def test_dynamic_version_no_pin_scheme(self): """ - Test --no-pin parameter + Test --mode=no-pin + """ + pipreqs.init( + {'': self.project_with_ignore_directory, '--savepath': None, + '--print': False, '--use-local': None, '--force': True, + '--proxy': None, '--pypi-server': None, + '--diff': None, + '--clean': None, + '--mode': 'no-pin' + } + ) + with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: + data = f.read().lower() + for item in ['beautifulsoup4', 'boto']: + self.assertTrue(item.lower() in data) + + def test_dynamic_version_gt_scheme(self): + """ + Test --mode=gt """ pipreqs.init( {'': self.project_with_ignore_directory, '--savepath': None, '--print': False, @@ -192,13 +246,81 @@ class TestPipreqs(unittest.TestCase): '--pypi-server': None, '--diff': None, '--clean': None, - '--no-pin': True + '--mode': 'gt' } ) with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: + data = f.readlines() + for item in data: + symbol = '>=' + message = 'symbol is not in item' + self.assertIn(symbol, item, message) + + def test_dynamic_version_compat_scheme(self): + """ + Test --mode=compat + """ + pipreqs.init( + {'': self.project_with_ignore_directory, '--savepath': None, '--print': False, + '--use-local': None, '--force': True, + '--proxy': None, + '--pypi-server': None, + '--diff': None, + '--clean': None, + '--mode': 'compat' + } + ) + with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: + data = f.readlines() + for item in data: + symbol = '~=' + message = 'symbol is not in item' + self.assertIn(symbol, item, message) + + def test_clean(self): + """ + Test --clean parameter + """ + pipreqs.init( + {'': self.project, '--savepath': None, '--print': False, + '--use-local': None, '--force': True, '--proxy': None, + '--pypi-server': None, '--diff': None, '--clean': None, + '--mode': None} + ) + assert os.path.exists(self.requirements_path) == 1 + pipreqs.init( + {'': self.project, '--savepath': None, '--print': False, + '--use-local': None, '--force': None, '--proxy': None, + '--pypi-server': None, '--diff': None, + '--clean': self.requirements_path, '--mode': 'non-pin'} + ) + with open(self.requirements_path, "r") as f: data = f.read().lower() - for item in ['beautifulsoup4==4.8.1', 'boto==2.49.0']: - self.assertFalse(item.lower() in data) + for item in self.modules[:-3]: + self.assertTrue(item.lower() in data) + + def test_clean_with_imports_to_clean(self): + """ + Test --clean parameter when there are imports to clean + """ + cleaned_module = 'sqlalchemy' + pipreqs.init( + {'': self.project, '--savepath': None, '--print': False, + '--use-local': None, '--force': True, '--proxy': None, + '--pypi-server': None, '--diff': None, '--clean': None, + '--mode': None} + ) + assert os.path.exists(self.requirements_path) == 1 + modules_clean = [m for m in self.modules if m != cleaned_module] + pipreqs.init( + {'': self.project_clean, '--savepath': None, + '--print': False, '--use-local': None, '--force': None, + '--proxy': None, '--pypi-server': None, '--diff': None, + '--clean': self.requirements_path, '--mode': 'non-pin'} + ) + with open(self.requirements_path, "r") as f: + data = f.read().lower() + self.assertTrue(cleaned_module not in data) def tearDown(self): """ diff --git a/tox.ini b/tox.ini index 28a1dfa..554b3c1 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py27, py34, py35, py36, pypy, flake8 +envlist = py27, py34, py35, py36, pypy3, flake8 [testenv] setenv = From 65ccd7eca3ac2dbf998d22e7ce72298457577e7e Mon Sep 17 00:00:00 2001 From: alan-barzilay Date: Sat, 8 May 2021 01:10:16 -0300 Subject: [PATCH 24/32] delete everything related to python2 We are dropping support for python 2, so we are dropping the verification of which python version is currently running and we also stop checking for python2 specific packages. We also drop the encoding definition since python3 uses utf-8 as default. The helper open_func function is also substituted by open. --- pipreqs/pipreqs.py | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/pipreqs/pipreqs.py b/pipreqs/pipreqs.py index 6c936aa..381d8d9 100644 --- a/pipreqs/pipreqs.py +++ b/pipreqs/pipreqs.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- """pipreqs - Generate pip requirements.txt file based on imports Usage: @@ -37,13 +36,11 @@ Options: | e.g. Flask>=1.1.2 | e.g. Flask """ -from __future__ import print_function, absolute_import from contextlib import contextmanager import os import sys import re import logging -import codecs import ast import traceback from docopt import docopt @@ -58,14 +55,6 @@ REGEXP = [ re.compile(r'^from ((?!\.+).*?) import (?:.*)$') ] -if sys.version_info[0] > 2: - open_func = open - py2 = False -else: - open_func = codecs.open - py2 = True - py2_exclude = ["concurrent", "concurrent.futures"] - @contextmanager def _open(filename=None, mode='r'): @@ -122,7 +111,7 @@ def get_all_imports( candidates += [os.path.splitext(fn)[0] for fn in files] for file_name in files: file_name = os.path.join(root, file_name) - with open_func(file_name, "r", encoding=encoding) as f: + with open(file_name, "r", encoding=encoding) as f: contents = f.read() try: tree = ast.parse(contents) @@ -157,7 +146,6 @@ def get_all_imports( with open(join("stdlib"), "r") as f: data = {x.strip() for x in f} - data = {x for x in data if x not in py2_exclude} if py2 else data return list(packages - data) @@ -214,7 +202,7 @@ def get_locally_installed_packages(encoding=None): for item in files: if "top_level" in item: item = os.path.join(root, item) - with open_func(item, "r", encoding=encoding) as f: + with open(item, "r", encoding=encoding) as f: package = root.split(os.sep)[-1].split("-") try: package_import = f.read().strip().split("\n") @@ -309,7 +297,7 @@ def parse_requirements(file_): delim = ["<", ">", "=", "!", "~"] try: - f = open_func(file_, "r") + f = open(file_, "r") except OSError: logging.error("Failed on file: {}".format(file_)) raise @@ -381,7 +369,7 @@ def clean(file_, imports): to_write = [] try: - f = open_func(file_, "r+") + f = open(file_, "r+") except OSError: logging.error("Failed on file: {}".format(file_)) raise From 30a944cddaf3a0635ad59448d292ebd4752242ca Mon Sep 17 00:00:00 2001 From: alan-barzilay Date: Sat, 8 May 2021 01:16:46 -0300 Subject: [PATCH 25/32] Bump python version Bump tests version and supported versions in setup.py stdlib: update packages for python 3.9 By utilizing the packages listed in https://github.com/jackmaney/python-stdlib-list for python 3.8 and 3.9, we were able to drop all stdlib packages that existed solely in python 2 and add the missing stdlib python 3 packages --- .travis.yml | 14 +- pipreqs/stdlib | 1652 ++++++++++++++++++++++++++++++++++++++++++------ setup.py | 11 +- tox.ini | 4 +- 4 files changed, 1483 insertions(+), 198 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7988659..67be4ad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,17 +4,17 @@ language: python matrix: include: + - python: 3.9 + env: TOX_ENV=py39 + - python: 3.8 + env: TOX_ENV=py38 + - python: 3.7 + env: TOX_ENV=py37 - python: 3.6 env: TOX_ENV=py36 - - python: 3.5 - env: TOX_ENV=py35 - - python: 3.4 - env: TOX_ENV=py34 - - python: 2.7 - env: TOX_ENV=py27 - python: pypy3 env: TOX_ENV=pypy3 - - python: 3.6 + - python: 3.9 env: TOX_ENV=flake8 # Use tox to run tests on Travis-CI to keep one unified method of running tests in any environment diff --git a/pipreqs/stdlib b/pipreqs/stdlib index c2c1fdd..ec03d25 100644 --- a/pipreqs/stdlib +++ b/pipreqs/stdlib @@ -1,149 +1,181 @@ -__builtin__ -__future__ -__main__ -_dummy_thread -_thread -_winreg +_abc abc -aepack -aetools -aetypes aifc -AL -al -anydbm -applesingle +_aix_support +antigravity argparse array +_ast ast asynchat +_asyncio asyncio +asyncio.base_events +asyncio.base_futures +asyncio.base_subprocess +asyncio.base_tasks +asyncio.constants +asyncio.coroutines +asyncio.events +asyncio.exceptions +asyncio.format_helpers +asyncio.futures +asyncio.locks +asyncio.log +asyncio.__main__ +asyncio.proactor_events +asyncio.protocols +asyncio.queues +asyncio.runners +asyncio.selector_events +asyncio.sslproto +asyncio.staggered +asyncio.streams +asyncio.subprocess +asyncio.tasks +asyncio.threads +asyncio.transports +asyncio.trsock +asyncio.unix_events +asyncio.windows_events +asyncio.windows_utils asyncore atexit audioop -autoGIL base64 -BaseHTTPServer -Bastion bdb binascii binhex +_bisect bisect -bsddb -buildtools +_blake2 +_bootlocale +_bootsubprocess builtins +_bz2 bz2 calendar -Carbon -Carbon.AE -Carbon.AH -Carbon.App -Carbon.Appearance -Carbon.CarbonEvents -Carbon.CarbonEvt -Carbon.CF -Carbon.CG -Carbon.Cm -Carbon.Components -Carbon.ControlAccessor -Carbon.Controls -Carbon.CoreFounation -Carbon.CoreGraphics -Carbon.Ctl -Carbon.Dialogs -Carbon.Dlg -Carbon.Drag -Carbon.Dragconst -Carbon.Events -Carbon.Evt -Carbon.File -Carbon.Files -Carbon.Fm -Carbon.Folder -Carbon.Folders -Carbon.Fonts -Carbon.Help -Carbon.IBCarbon -Carbon.IBCarbonRuntime -Carbon.Icns -Carbon.Icons -Carbon.Launch -Carbon.LaunchServices -Carbon.List -Carbon.Lists -Carbon.MacHelp -Carbon.MediaDescr -Carbon.Menu -Carbon.Menus -Carbon.Mlte -Carbon.OSA -Carbon.OSAconst -Carbon.Qd -Carbon.Qdoffs -Carbon.QDOffscreen -Carbon.Qt -Carbon.QuickDraw -Carbon.QuickTime -Carbon.Res -Carbon.Resources -Carbon.Scrap -Carbon.Snd -Carbon.Sound -Carbon.TE -Carbon.TextEdit -Carbon.Win -Carbon.Windows -cd -cfmfile cgi -CGIHTTPServer cgitb chunk cmath cmd code +_codecs codecs +_codecs_cn +_codecs_hk +_codecs_iso2022 +_codecs_jp +_codecs_kr +_codecs_tw codeop +_collections collections +_collections_abc collections.abc -ColorPicker colorsys -commands +_compat_pickle compileall -compiler -compiler.ast -compiler.visitor +_compression concurrent concurrent.futures -ConfigParser +concurrent.futures._base +concurrent.futures.process +concurrent.futures.thread configparser contextlib -Cookie -cookielib +_contextvars +contextvars copy -copy_reg copyreg -cPickle cProfile +_crypt crypt -cStringIO +_csv csv +_ctypes ctypes +ctypes._aix +ctypes._endian +ctypes.macholib +ctypes.macholib.dyld +ctypes.macholib.dylib +ctypes.macholib.framework +_ctypes_test +ctypes.test +ctypes.test.__main__ +ctypes.test.test_anon +ctypes.test.test_array_in_pointer +ctypes.test.test_arrays +ctypes.test.test_as_parameter +ctypes.test.test_bitfields +ctypes.test.test_buffers +ctypes.test.test_bytes +ctypes.test.test_byteswap +ctypes.test.test_callbacks +ctypes.test.test_cast +ctypes.test.test_cfuncs +ctypes.test.test_checkretval +ctypes.test.test_delattr +ctypes.test.test_errno +ctypes.test.test_find +ctypes.test.test_frombuffer +ctypes.test.test_funcptr +ctypes.test.test_functions +ctypes.test.test_incomplete +ctypes.test.test_init +ctypes.test.test_internals +ctypes.test.test_keeprefs +ctypes.test.test_libc +ctypes.test.test_loading +ctypes.test.test_macholib +ctypes.test.test_memfunctions +ctypes.test.test_numbers +ctypes.test.test_objects +ctypes.test.test_parameters +ctypes.test.test_pep3118 +ctypes.test.test_pickling +ctypes.test.test_pointers +ctypes.test.test_prototypes +ctypes.test.test_python_api +ctypes.test.test_random_things +ctypes.test.test_refcounts +ctypes.test.test_repr +ctypes.test.test_returnfuncptrs +ctypes.test.test_simplesubclasses +ctypes.test.test_sizes +ctypes.test.test_slicing +ctypes.test.test_stringptr +ctypes.test.test_strings +ctypes.test.test_struct_fields +ctypes.test.test_structures +ctypes.test.test_unaligned_structures +ctypes.test.test_unicode +ctypes.test.test_values +ctypes.test.test_varsize_struct +ctypes.test.test_win32 +ctypes.test.test_wintypes +ctypes.util +ctypes.wintypes +_curses curses curses.ascii +curses.has_key +_curses_panel curses.panel curses.textpad dataclasses +_datetime datetime -dbhash +_dbm dbm dbm.dumb dbm.gnu dbm.ndbm +_decimal decimal -DEVICE difflib -dircache dis distutils distutils.archive_util @@ -167,248 +199,688 @@ distutils.command.clean distutils.command.config distutils.command.install distutils.command.install_data +distutils.command.install_egg_info distutils.command.install_headers distutils.command.install_lib distutils.command.install_scripts distutils.command.register distutils.command.sdist +distutils.command.upload +distutils.config distutils.core distutils.cygwinccompiler distutils.debug distutils.dep_util distutils.dir_util distutils.dist -distutils.emxccompiler distutils.errors distutils.extension distutils.fancy_getopt -distutils.file_util distutils.filelist +distutils.file_util distutils.log +distutils.msvc9compiler +distutils._msvccompiler distutils.msvccompiler distutils.spawn distutils.sysconfig +distutils.tests +distutils.tests.support +distutils.tests.test_archive_util +distutils.tests.test_bdist +distutils.tests.test_bdist_dumb +distutils.tests.test_bdist_msi +distutils.tests.test_bdist_rpm +distutils.tests.test_bdist_wininst +distutils.tests.test_build +distutils.tests.test_build_clib +distutils.tests.test_build_ext +distutils.tests.test_build_py +distutils.tests.test_build_scripts +distutils.tests.test_check +distutils.tests.test_clean +distutils.tests.test_cmd +distutils.tests.test_config +distutils.tests.test_config_cmd +distutils.tests.test_core +distutils.tests.test_cygwinccompiler +distutils.tests.test_dep_util +distutils.tests.test_dir_util +distutils.tests.test_dist +distutils.tests.test_extension +distutils.tests.test_filelist +distutils.tests.test_file_util +distutils.tests.test_install +distutils.tests.test_install_data +distutils.tests.test_install_headers +distutils.tests.test_install_lib +distutils.tests.test_install_scripts +distutils.tests.test_log +distutils.tests.test_msvc9compiler +distutils.tests.test_msvccompiler +distutils.tests.test_register +distutils.tests.test_sdist +distutils.tests.test_spawn +distutils.tests.test_sysconfig +distutils.tests.test_text_file +distutils.tests.test_unixccompiler +distutils.tests.test_upload +distutils.tests.test_util +distutils.tests.test_version +distutils.tests.test_versionpredicate distutils.text_file distutils.unixccompiler distutils.util distutils.version -dl +distutils.versionpredicate doctest -DocXMLRPCServer -dumbdbm -dummy_thread +_dummy_thread dummy_threading -EasyDialogs +_elementtree email +email.base64mime email.charset email.contentmanager +email._encoded_words email.encoders email.errors +email.feedparser email.generator email.header email.headerregistry +email._header_value_parser email.iterators email.message email.mime +email.mime.application +email.mime.audio +email.mime.base +email.mime.image +email.mime.message +email.mime.multipart +email.mime.nonmultipart +email.mime.text +email._parseaddr email.parser email.policy +email._policybase +email.quoprimime email.utils encodings +encodings.aliases +encodings.ascii +encodings.base64_codec +encodings.big5 +encodings.big5hkscs +encodings.bz2_codec +encodings.charmap +encodings.cp037 +encodings.cp1006 +encodings.cp1026 +encodings.cp1125 +encodings.cp1140 +encodings.cp1250 +encodings.cp1251 +encodings.cp1252 +encodings.cp1253 +encodings.cp1254 +encodings.cp1255 +encodings.cp1256 +encodings.cp1257 +encodings.cp1258 +encodings.cp273 +encodings.cp424 +encodings.cp437 +encodings.cp500 +encodings.cp720 +encodings.cp737 +encodings.cp775 +encodings.cp850 +encodings.cp852 +encodings.cp855 +encodings.cp856 +encodings.cp857 +encodings.cp858 +encodings.cp860 +encodings.cp861 +encodings.cp862 +encodings.cp863 +encodings.cp864 +encodings.cp865 +encodings.cp866 +encodings.cp869 +encodings.cp874 +encodings.cp875 +encodings.cp932 +encodings.cp949 +encodings.cp950 +encodings.euc_jis_2004 +encodings.euc_jisx0213 +encodings.euc_jp +encodings.euc_kr +encodings.gb18030 +encodings.gb2312 +encodings.gbk +encodings.hex_codec +encodings.hp_roman8 +encodings.hz encodings.idna +encodings.iso2022_jp +encodings.iso2022_jp_1 +encodings.iso2022_jp_2 +encodings.iso2022_jp_2004 +encodings.iso2022_jp_3 +encodings.iso2022_jp_ext +encodings.iso2022_kr +encodings.iso8859_1 +encodings.iso8859_10 +encodings.iso8859_11 +encodings.iso8859_13 +encodings.iso8859_14 +encodings.iso8859_15 +encodings.iso8859_16 +encodings.iso8859_2 +encodings.iso8859_3 +encodings.iso8859_4 +encodings.iso8859_5 +encodings.iso8859_6 +encodings.iso8859_7 +encodings.iso8859_8 +encodings.iso8859_9 +encodings.johab +encodings.koi8_r +encodings.koi8_t +encodings.koi8_u +encodings.kz1048 +encodings.latin_1 +encodings.mac_arabic +encodings.mac_centeuro +encodings.mac_croatian +encodings.mac_cyrillic +encodings.mac_farsi +encodings.mac_greek +encodings.mac_iceland +encodings.mac_latin2 +encodings.mac_roman +encodings.mac_romanian +encodings.mac_turkish encodings.mbcs +encodings.oem +encodings.palmos +encodings.ptcp154 +encodings.punycode +encodings.quopri_codec +encodings.raw_unicode_escape +encodings.rot_13 +encodings.shift_jis +encodings.shift_jis_2004 +encodings.shift_jisx0213 +encodings.tis_620 +encodings.undefined +encodings.unicode_escape +encodings.utf_16 +encodings.utf_16_be +encodings.utf_16_le +encodings.utf_32 +encodings.utf_32_be +encodings.utf_32_le +encodings.utf_7 +encodings.utf_8 encodings.utf_8_sig +encodings.uu_codec +encodings.zlib_codec ensurepip +ensurepip._bundled +ensurepip.__main__ +ensurepip._uninstall enum errno -exceptions faulthandler fcntl filecmp fileinput -findertools -FL -fl -flp -fm fnmatch formatter -fpectl -fpformat fractions -FrameWork +_frozen_importlib +_frozen_importlib_external ftplib +_functools functools -future_builtins +__future__ gc -gdbm -gensuitemodule +_gdbm +genericpath getopt getpass gettext -GL -gl glob +graphlib grp gzip +_hashlib hashlib +_heapq heapq hmac -hotshot -hotshot.stats html html.entities html.parser -htmlentitydefs -htmllib -HTMLParser http http.client http.cookiejar http.cookies http.server -httplib -ic -icopen -imageop +idlelib +idlelib.autocomplete +idlelib.autocomplete_w +idlelib.autoexpand +idlelib.browser +idlelib.calltip +idlelib.calltip_w +idlelib.codecontext +idlelib.colorizer +idlelib.config +idlelib.configdialog +idlelib.config_key +idlelib.debugger +idlelib.debugger_r +idlelib.debugobj +idlelib.debugobj_r +idlelib.delegator +idlelib.dynoption +idlelib.editor +idlelib.filelist +idlelib.format +idlelib.grep +idlelib.help +idlelib.help_about +idlelib.history +idlelib.hyperparser +idlelib.idle +idlelib.idle_test +idlelib.idle_test.htest +idlelib.idle_test.mock_idle +idlelib.idle_test.mock_tk +idlelib.idle_test.template +idlelib.idle_test.test_autocomplete +idlelib.idle_test.test_autocomplete_w +idlelib.idle_test.test_autoexpand +idlelib.idle_test.test_browser +idlelib.idle_test.test_calltip +idlelib.idle_test.test_calltip_w +idlelib.idle_test.test_codecontext +idlelib.idle_test.test_colorizer +idlelib.idle_test.test_config +idlelib.idle_test.test_configdialog +idlelib.idle_test.test_config_key +idlelib.idle_test.test_debugger +idlelib.idle_test.test_debugger_r +idlelib.idle_test.test_debugobj +idlelib.idle_test.test_debugobj_r +idlelib.idle_test.test_delegator +idlelib.idle_test.test_editmenu +idlelib.idle_test.test_editor +idlelib.idle_test.test_filelist +idlelib.idle_test.test_format +idlelib.idle_test.test_grep +idlelib.idle_test.test_help +idlelib.idle_test.test_help_about +idlelib.idle_test.test_history +idlelib.idle_test.test_hyperparser +idlelib.idle_test.test_iomenu +idlelib.idle_test.test_macosx +idlelib.idle_test.test_mainmenu +idlelib.idle_test.test_multicall +idlelib.idle_test.test_outwin +idlelib.idle_test.test_parenmatch +idlelib.idle_test.test_pathbrowser +idlelib.idle_test.test_percolator +idlelib.idle_test.test_pyparse +idlelib.idle_test.test_pyshell +idlelib.idle_test.test_query +idlelib.idle_test.test_redirector +idlelib.idle_test.test_replace +idlelib.idle_test.test_rpc +idlelib.idle_test.test_run +idlelib.idle_test.test_runscript +idlelib.idle_test.test_scrolledlist +idlelib.idle_test.test_search +idlelib.idle_test.test_searchbase +idlelib.idle_test.test_searchengine +idlelib.idle_test.test_sidebar +idlelib.idle_test.test_squeezer +idlelib.idle_test.test_stackviewer +idlelib.idle_test.test_statusbar +idlelib.idle_test.test_text +idlelib.idle_test.test_textview +idlelib.idle_test.test_tooltip +idlelib.idle_test.test_tree +idlelib.idle_test.test_undo +idlelib.idle_test.test_warning +idlelib.idle_test.test_window +idlelib.idle_test.test_zoomheight +idlelib.iomenu +idlelib.macosx +idlelib.__main__ +idlelib.mainmenu +idlelib.multicall +idlelib.outwin +idlelib.parenmatch +idlelib.pathbrowser +idlelib.percolator +idlelib.pyparse +idlelib.pyshell +idlelib.query +idlelib.redirector +idlelib.replace +idlelib.rpc +idlelib.run +idlelib.runscript +idlelib.scrolledlist +idlelib.search +idlelib.searchbase +idlelib.searchengine +idlelib.sidebar +idlelib.squeezer +idlelib.stackviewer +idlelib.statusbar +idlelib.textview +idlelib.tooltip +idlelib.tree +idlelib.undo +idlelib.window +idlelib.zoomheight +idlelib.zzdummy imaplib -imgfile imghdr +_imp imp importlib importlib.abc +importlib._bootstrap +importlib._bootstrap_external +importlib._common importlib.machinery +importlib.metadata +importlib.resources importlib.util -imputil inspect +_io io ipaddress itertools -jpeg +_json json +json.decoder +json.encoder +json.scanner json.tool keyword lib2to3 +lib2to3.btm_matcher +lib2to3.btm_utils +lib2to3.fixer_base +lib2to3.fixer_util +lib2to3.fixes +lib2to3.fixes.fix_apply +lib2to3.fixes.fix_asserts +lib2to3.fixes.fix_basestring +lib2to3.fixes.fix_buffer +lib2to3.fixes.fix_dict +lib2to3.fixes.fix_except +lib2to3.fixes.fix_exec +lib2to3.fixes.fix_execfile +lib2to3.fixes.fix_exitfunc +lib2to3.fixes.fix_filter +lib2to3.fixes.fix_funcattrs +lib2to3.fixes.fix_future +lib2to3.fixes.fix_getcwdu +lib2to3.fixes.fix_has_key +lib2to3.fixes.fix_idioms +lib2to3.fixes.fix_import +lib2to3.fixes.fix_imports +lib2to3.fixes.fix_imports2 +lib2to3.fixes.fix_input +lib2to3.fixes.fix_intern +lib2to3.fixes.fix_isinstance +lib2to3.fixes.fix_itertools +lib2to3.fixes.fix_itertools_imports +lib2to3.fixes.fix_long +lib2to3.fixes.fix_map +lib2to3.fixes.fix_metaclass +lib2to3.fixes.fix_methodattrs +lib2to3.fixes.fix_ne +lib2to3.fixes.fix_next +lib2to3.fixes.fix_nonzero +lib2to3.fixes.fix_numliterals +lib2to3.fixes.fix_operator +lib2to3.fixes.fix_paren +lib2to3.fixes.fix_print +lib2to3.fixes.fix_raise +lib2to3.fixes.fix_raw_input +lib2to3.fixes.fix_reduce +lib2to3.fixes.fix_reload +lib2to3.fixes.fix_renames +lib2to3.fixes.fix_repr +lib2to3.fixes.fix_set_literal +lib2to3.fixes.fix_standarderror +lib2to3.fixes.fix_sys_exc +lib2to3.fixes.fix_throw +lib2to3.fixes.fix_tuple_params +lib2to3.fixes.fix_types +lib2to3.fixes.fix_unicode +lib2to3.fixes.fix_urllib +lib2to3.fixes.fix_ws_comma +lib2to3.fixes.fix_xrange +lib2to3.fixes.fix_xreadlines +lib2to3.fixes.fix_zip +lib2to3.main +lib2to3.__main__ +lib2to3.patcomp +lib2to3.pgen2 +lib2to3.pgen2.conv +lib2to3.pgen2.driver +lib2to3.pgen2.grammar +lib2to3.pgen2.literals +lib2to3.pgen2.parse +lib2to3.pgen2.pgen +lib2to3.pgen2.token +lib2to3.pgen2.tokenize +lib2to3.pygram +lib2to3.pytree +lib2to3.refactor +lib2to3.tests +lib2to3.tests.data.bom +lib2to3.tests.data.crlf +lib2to3.tests.data.different_encoding +lib2to3.tests.data.false_encoding +lib2to3.tests.data.fixers.bad_order +lib2to3.tests.data.fixers.myfixes +lib2to3.tests.data.fixers.myfixes.fix_explicit +lib2to3.tests.data.fixers.myfixes.fix_first +lib2to3.tests.data.fixers.myfixes.fix_last +lib2to3.tests.data.fixers.myfixes.fix_parrot +lib2to3.tests.data.fixers.myfixes.fix_preorder +lib2to3.tests.data.fixers.no_fixer_cls +lib2to3.tests.data.fixers.parrot_example +lib2to3.tests.data.infinite_recursion +lib2to3.tests.data.py2_test_grammar +lib2to3.tests.data.py3_test_grammar +lib2to3.tests.__main__ +lib2to3.tests.pytree_idempotency +lib2to3.tests.support +lib2to3.tests.test_all_fixers +lib2to3.tests.test_fixers +lib2to3.tests.test_main +lib2to3.tests.test_parser +lib2to3.tests.test_pytree +lib2to3.tests.test_refactor +lib2to3.tests.test_util +lib.libpython3 linecache +_locale locale logging logging.config logging.handlers +_lsprof +_lzma lzma -macerrors -MacOS -macostools -macpath -macresource mailbox mailcap +__main__ +_markupbase marshal math -md5 -mhlib -mimetools +_md5 mimetypes -MimeWriter -mimify -MiniAEFrame mmap modulefinder msilib msvcrt -multifile +_multibytecodec +_multiprocessing multiprocessing multiprocessing.connection +multiprocessing.context multiprocessing.dummy +multiprocessing.dummy.connection +multiprocessing.forkserver +multiprocessing.heap multiprocessing.managers multiprocessing.pool +multiprocessing.popen_fork +multiprocessing.popen_forkserver +multiprocessing.popen_spawn_posix +multiprocessing.popen_spawn_win32 +multiprocessing.process +multiprocessing.queues +multiprocessing.reduction +multiprocessing.resource_sharer +multiprocessing.resource_tracker multiprocessing.sharedctypes -mutex -Nav +multiprocessing.shared_memory +multiprocessing.spawn +multiprocessing.synchronize +multiprocessing.util netrc -new nis nntplib +ntpath +nturl2path numbers +_opcode +opcode +_operator operator optparse os os.path ossaudiodev +_osx_support parser pathlib pdb +__phello__.foo +_pickle pickle pickletools pipes -PixMapWrapper -pkg_resources pkgutil platform plistlib -popen2 poplib posix -posixfile +posixpath +_posixshmem +_posixsubprocess pprint profile pstats pty pwd -py_compile +_py_abc pyclbr +py_compile +_pydecimal pydoc -Queue +pydoc_data +pydoc_data.topics +pyexpat +_pyio +_queue queue quopri +_random random re readline reprlib resource -rexec -rfc822 rlcompleter -robotparser runpy sched -ScrolledText secrets select selectors -sets -setuptools -sgmllib -sha +_sha1 +_sha256 +_sha3 +_sha512 shelve shlex shutil +_signal signal -SimpleHTTPServer -SimpleXMLRPCServer site +_sitebuiltins smtpd smtplib sndhdr +_socket socket -SocketServer socketserver spwd +_sqlite3 sqlite3 +sqlite3.dbapi2 +sqlite3.dump +sqlite3.test +sqlite3.test.backup +sqlite3.test.dbapi +sqlite3.test.dump +sqlite3.test.factory +sqlite3.test.hooks +sqlite3.test.regression +sqlite3.test.transactions +sqlite3.test.types +sqlite3.test.userfunctions +_sre +sre_compile +sre_constants +sre_parse +_ssl ssl +_stat stat +_statistics statistics -statvfs +_string string -StringIO stringprep +_strptime +_struct struct subprocess sunau -SUNAUDIODEV -sunaudiodev symbol +_symtable symtable sys sysconfig +_sysconfigdata_x86_64_conda_cos6_linux_gnu +_sysconfigdata_x86_64_conda_linux_gnu syslog tabnanny tarfile @@ -416,55 +888,853 @@ telnetlib tempfile termios test +test.ann_module +test.ann_module2 +test.ann_module3 +test.audiotests +test.autotest +test.bad_coding +test.bad_coding2 +test.bad_getattr +test.bad_getattr2 +test.bad_getattr3 +test.badsyntax_3131 +test.badsyntax_future10 +test.badsyntax_future3 +test.badsyntax_future4 +test.badsyntax_future5 +test.badsyntax_future6 +test.badsyntax_future7 +test.badsyntax_future8 +test.badsyntax_future9 +test.badsyntax_pep3120 +test.bisect_cmd +_testbuffer +test.bytecode_helper +_testcapi +test.coding20731 +test.curses_tests +test.dataclass_module_1 +test.dataclass_module_1_str +test.dataclass_module_2 +test.dataclass_module_2_str +test.datetimetester +test.dis_module +test.doctest_aliases +test.double_const +test.dtracedata.call_stack +test.dtracedata.gc +test.dtracedata.instance +test.dtracedata.line +test.eintrdata.eintr_tester +test.encoded_modules +test.encoded_modules.module_iso_8859_1 +test.encoded_modules.module_koi8_r +test.final_a +test.final_b +test.fork_wait +test.future_test1 +test.future_test2 +test.gdb_sample +test.good_getattr +test.imp_dummy +_testimportmultiple +test.inspect_fodder +test.inspect_fodder2 +_testinternalcapi +test.libregrtest +test.libregrtest.cmdline +test.libregrtest.main +test.libregrtest.pgo +test.libregrtest.refleak +test.libregrtest.runtest +test.libregrtest.runtest_mp +test.libregrtest.save_env +test.libregrtest.setup +test.libregrtest.utils +test.libregrtest.win_utils +test.list_tests +test.lock_tests +test.__main__ +test.make_ssl_certs +test.mapping_tests +test.memory_watchdog +test.mock_socket +test.mod_generics_cache +test.mp_fork_bomb +test.mp_preload +test.multibytecodec_support +_testmultiphase +test.outstanding_bugs +test.pickletester +test.profilee +test.pyclbr_input +test.pydocfodder +test.pydoc_mod +test.pythoninfo +test.regrtest +test.relimport +test.reperf +test.re_tests +test.sample_doctest +test.sample_doctest_no_docstrings +test.sample_doctest_no_doctests +test.seq_tests +test.signalinterproctester +test.sortperf +test.ssl_servers +test.ssltests +test.string_tests +test.subprocessdata.fd_status +test.subprocessdata.input_reader +test.subprocessdata.qcat +test.subprocessdata.qgrep +test.subprocessdata.sigchild_ignore test.support +test.support.bytecode_helper +test.support.hashlib_helper +test.support.logging_helper +test.support.script_helper +test.support.socket_helper +test.support.testresult +test.test_abc +test.test_abstract_numbers +test.test_aifc +test.test___all__ +test.test_argparse +test.test_array +test.test_asdl_parser +test.test_ast +test.test_asyncgen +test.test_asynchat +test.test_asyncio +test.test_asyncio.echo +test.test_asyncio.echo2 +test.test_asyncio.echo3 +test.test_asyncio.functional +test.test_asyncio.__main__ +test.test_asyncio.test_base_events +test.test_asyncio.test_buffered_proto +test.test_asyncio.test_context +test.test_asyncio.test_events +test.test_asyncio.test_futures +test.test_asyncio.test_locks +test.test_asyncio.test_pep492 +test.test_asyncio.test_proactor_events +test.test_asyncio.test_protocols +test.test_asyncio.test_queues +test.test_asyncio.test_runners +test.test_asyncio.test_selector_events +test.test_asyncio.test_sendfile +test.test_asyncio.test_server +test.test_asyncio.test_sock_lowlevel +test.test_asyncio.test_sslproto +test.test_asyncio.test_streams +test.test_asyncio.test_subprocess +test.test_asyncio.test_tasks +test.test_asyncio.test_transports +test.test_asyncio.test_unix_events +test.test_asyncio.test_windows_events +test.test_asyncio.test_windows_utils +test.test_asyncio.utils +test.test_asyncore +test.test_atexit +test.test_audioop +test.test_audit +test.test_augassign +test.test_base64 +test.test_baseexception +test.test_bdb +test.test_bigaddrspace +test.test_bigmem +test.test_binascii +test.test_binhex +test.test_binop +test.test_bisect +test.test_bool +test.test_buffer +test.test_bufio +test.test_builtin +test.test_bytes +test.test_bz2 +test.test_calendar +test.test_call +test.test_capi +test.test_cgi +test.test_cgitb +test.test_charmapcodec +test.test_class +test.test_clinic +test.test_c_locale_coercion +test.test_cmath +test.test_cmd +test.test_cmd_line +test.test_cmd_line_script +test.test_code +test.testcodec +test.test_codeccallbacks +test.test_codecencodings_cn +test.test_codecencodings_hk +test.test_codecencodings_iso2022 +test.test_codecencodings_jp +test.test_codecencodings_kr +test.test_codecencodings_tw +test.test_codecmaps_cn +test.test_codecmaps_hk +test.test_codecmaps_jp +test.test_codecmaps_kr +test.test_codecmaps_tw +test.test_codecs +test.test_code_module +test.test_codeop +test.test_collections +test.test_colorsys +test.test_compare +test.test_compile +test.test_compileall +test.test_complex +test.test_concurrent_futures +test.test_configparser +test.test_contains +test.test_context +test.test_contextlib +test.test_contextlib_async +test.test_copy +test.test_copyreg +test.test_coroutines +test.test_cprofile +test.test_crashers +test.test_crypt +test.test_csv +test.test_ctypes +test.test_curses +test.test_dataclasses +test.test_datetime +test.test_dbm +test.test_dbm_dumb +test.test_dbm_gnu +test.test_dbm_ndbm +test.test_decimal +test.test_decorators +test.test_defaultdict +test.test_deque +test.test_descr +test.test_descrtut +test.test_devpoll +test.test_dict +test.test_dictcomps +test.test_dict_version +test.test_dictviews +test.test_difflib +test.test_dis +test.test_distutils +test.test_doctest +test.test_doctest2 +test.test_docxmlrpc +test.test_dtrace +test.test_dummy_thread +test.test_dummy_threading +test.test_dynamic +test.test_dynamicclassattribute +test.test_eintr +test.test_email +test.test_email.__main__ +test.test_email.test_asian_codecs +test.test_email.test_contentmanager +test.test_email.test_defect_handling +test.test_email.test_email +test.test_email.test__encoded_words +test.test_email.test_generator +test.test_email.test_headerregistry +test.test_email.test__header_value_parser +test.test_email.test_inversion +test.test_email.test_message +test.test_email.test_parser +test.test_email.test_pickleable +test.test_email.test_policy +test.test_email.test_utils +test.test_email.torture_test +test.test_embed +test.test_ensurepip +test.test_enum +test.test_enumerate +test.test_eof +test.test_epoll +test.test_errno +test.test_exception_hierarchy +test.test_exceptions +test.test_exception_variations +test.test_extcall +test.test_faulthandler +test.test_fcntl +test.test_file +test.test_filecmp +test.test_file_eintr +test.test_fileinput +test.test_fileio +test.test_finalization +test.test_float +test.test_flufl +test.test_fnmatch +test.test_fork1 +test.test_format +test.test_fractions +test.test_frame +test.test_frozen +test.test_fstring +test.test_ftplib +test.test_funcattrs +test.test_functools +test.test___future__ +test.test_future +test.test_future3 +test.test_future4 +test.test_future5 +test.test_gc +test.test_gdb +test.test_generators +test.test_generator_stop +test.test_genericclass +test.test_genericpath +test.test_genexps +test.test_getargs2 +test.test_getopt +test.test_getpass +test.test_gettext +test.test_glob +test.test_global +test.test_grammar +test.test_grp +test.test_gzip +test.test_hash +test.test_hashlib +test.test_heapq +test.test_hmac +test.test_html +test.test_htmlparser +test.test_http_cookiejar +test.test_http_cookies +test.test_httplib +test.test_httpservers +test.test_idle +test.test_imaplib +test.test_imghdr +test.test_imp +test.test_import +test.test_import.data.circular_imports.basic +test.test_import.data.circular_imports.basic2 +test.test_import.data.circular_imports.binding +test.test_import.data.circular_imports.binding2 +test.test_import.data.circular_imports.from_cycle1 +test.test_import.data.circular_imports.from_cycle2 +test.test_import.data.circular_imports.indirect +test.test_import.data.circular_imports.rebinding +test.test_import.data.circular_imports.rebinding2 +test.test_import.data.circular_imports.source +test.test_import.data.circular_imports.subpackage +test.test_import.data.circular_imports.subpkg.subpackage2 +test.test_import.data.circular_imports.subpkg.util +test.test_import.data.circular_imports.use +test.test_import.data.circular_imports.util +test.test_import.data.package +test.test_import.data.package2.submodule1 +test.test_import.data.package2.submodule2 +test.test_import.data.package.submodule +test.test_importlib +test.test_importlib.abc +test.test_importlib.builtin +test.test_importlib.builtin.__main__ +test.test_importlib.builtin.test_finder +test.test_importlib.builtin.test_loader +test.test_importlib.data +test.test_importlib.data01 +test.test_importlib.data01.subdirectory +test.test_importlib.data02 +test.test_importlib.data02.one +test.test_importlib.data02.two +test.test_importlib.data03 +test.test_importlib.data03.namespace.portion1 +test.test_importlib.data03.namespace.portion2 +test.test_importlib.extension +test.test_importlib.extension.__main__ +test.test_importlib.extension.test_case_sensitivity +test.test_importlib.extension.test_finder +test.test_importlib.extension.test_loader +test.test_importlib.extension.test_path_hook +test.test_importlib.fixtures +test.test_importlib.frozen +test.test_importlib.frozen.__main__ +test.test_importlib.frozen.test_finder +test.test_importlib.frozen.test_loader +test.test_importlib.import_ +test.test_importlib.import_.__main__ +test.test_importlib.import_.test_api +test.test_importlib.import_.test_caching +test.test_importlib.import_.test_fromlist +test.test_importlib.import_.test___loader__ +test.test_importlib.import_.test_meta_path +test.test_importlib.import_.test___package__ +test.test_importlib.import_.test_packages +test.test_importlib.import_.test_path +test.test_importlib.import_.test_relative_imports +test.test_importlib.__main__ +test.test_importlib.namespace_pkgs.both_portions.foo.one +test.test_importlib.namespace_pkgs.both_portions.foo.two +test.test_importlib.namespace_pkgs.module_and_namespace_package.a_test +test.test_importlib.namespace_pkgs.not_a_namespace_pkg.foo +test.test_importlib.namespace_pkgs.not_a_namespace_pkg.foo.one +test.test_importlib.namespace_pkgs.portion1.foo.one +test.test_importlib.namespace_pkgs.portion2.foo.two +test.test_importlib.namespace_pkgs.project1.parent.child.one +test.test_importlib.namespace_pkgs.project2.parent.child.two +test.test_importlib.namespace_pkgs.project3.parent.child.three +test.test_importlib.source +test.test_importlib.source.__main__ +test.test_importlib.source.test_case_sensitivity +test.test_importlib.source.test_file_loader +test.test_importlib.source.test_finder +test.test_importlib.source.test_path_hook +test.test_importlib.source.test_source_encoding +test.test_importlib.test_abc +test.test_importlib.test_api +test.test_importlib.test_lazy +test.test_importlib.test_locks +test.test_importlib.test_main +test.test_importlib.test_metadata_api +test.test_importlib.test_namespace_pkgs +test.test_importlib.test_open +test.test_importlib.test_path +test.test_importlib.test_read +test.test_importlib.test_resource +test.test_importlib.test_spec +test.test_importlib.test_util +test.test_importlib.test_windows +test.test_importlib.test_zip +test.test_importlib.util +test.test_importlib.zipdata01 +test.test_importlib.zipdata02 +test.test_import.__main__ +test.test_index +test.test_inspect +test.test_int +test.test_int_literal +test.test_io +test.test_ioctl +test.test_ipaddress +test.test_isinstance +test.test_iter +test.test_iterlen +test.test_itertools +test.test_json +test.test_json.__main__ +test.test_json.test_decode +test.test_json.test_default +test.test_json.test_dump +test.test_json.test_encode_basestring_ascii +test.test_json.test_enum +test.test_json.test_fail +test.test_json.test_float +test.test_json.test_indent +test.test_json.test_pass1 +test.test_json.test_pass2 +test.test_json.test_pass3 +test.test_json.test_recursion +test.test_json.test_scanstring +test.test_json.test_separators +test.test_json.test_speedups +test.test_json.test_tool +test.test_json.test_unicode +test.test_keyword +test.test_keywordonlyarg +test.test_kqueue +test.test_largefile +test.test_lib2to3 +test.test_linecache +test.test_list +test.test_listcomps +test.test_lltrace +test.test__locale +test.test_locale +test.test_logging +test.test_long +test.test_longexp +test.test_lzma +test.test_mailbox +test.test_mailcap +test.test_marshal +test.test_math +test.test_memoryio +test.test_memoryview +test.test_metaclass +test.test_mimetypes +test.test_minidom +test.test_mmap +test.test_module +test.test_modulefinder +test.test_msilib +test.test_multibytecodec +test._test_multiprocessing +test.test_multiprocessing_fork +test.test_multiprocessing_forkserver +test.test_multiprocessing_main_handling +test.test_multiprocessing_spawn +test.test_named_expressions +test.test_netrc +test.test_nis +test.test_nntplib +test.test_normalization +test.test_ntpath +test.test_numeric_tower +test.test__opcode +test.test_opcodes +test.test_openpty +test.test_operator +test.test_optparse +test.test_ordered_dict +test.test_os +test.test_ossaudiodev +test.test_osx_env +test.test__osx_support +test.test_parser +test.test_pathlib +test.test_pdb +test.test_peepholer +test.test_pickle +test.test_picklebuffer +test.test_pickletools +test.test_pipes +test.test_pkg +test.test_pkgimport +test.test_pkgutil +test.test_platform +test.test_plistlib +test.test_poll +test.test_popen +test.test_poplib +test.test_positional_only_arg +test.test_posix +test.test_posixpath +test.test_pow +test.test_pprint +test.test_print +test.test_profile +test.test_property +test.test_pstats +test.test_pty +test.test_pulldom +test.test_pwd +test.test_pyclbr +test.test_py_compile +test.test_pydoc +test.test_pyexpat +test.test_queue +test.test_quopri +test.test_raise +test.test_random +test.test_range +test.test_re +test.test_readline +test.test_regrtest +test.test_repl +test.test_reprlib +test.test_resource +test.test_richcmp +test.test_rlcompleter +test.test_robotparser +test.test_runpy +test.test_sax +test.test_sched +test.test_scope +test.test_script_helper +test.test_secrets +test.test_select +test.test_selectors +test.test_set +test.test_setcomps +test.test_shelve +test.test_shlex +test.test_shutil +test.test_signal +test.test_site +test.test_slice +test.test_smtpd +test.test_smtplib +test.test_smtpnet +test.test_sndhdr +test.test_socket +test.test_socketserver +test.test_sort +test.test_source_encoding +test.test_spwd +test.test_sqlite +test.test_ssl +test.test_startfile +test.test_stat +test.test_statistics +test.test_strftime +test.test_string +test.test_string_literals +test.test_stringprep +test.test_strptime +test.test_strtod +test.test_struct +test.test_structmembers +test.test_structseq +test.test_subclassinit +test.test_subprocess +test.test_sunau +test.test_sundry +test.test_super test.test_support +test.test_symbol +test.test_symtable +test.test_syntax +test.test_sys +test.test_sysconfig +test.test_syslog +test.test_sys_setprofile +test.test_sys_settrace +test.test_tabnanny +test.test_tarfile +test.test_tcl +test.test_telnetlib +test.test_tempfile +test.test_textwrap +test.test_thread +test.test_threaded_import +test.test_threadedtempfile +test.test_threading +test.test_threading_local +test.test_threadsignals +test.test_time +test.test_timeit +test.test_timeout +test.test_tix +test.test_tk +test.test_tokenize +test.test_tools +test.test_tools.__main__ +test.test_tools.test_fixcid +test.test_tools.test_gprof2html +test.test_tools.test_i18n +test.test_tools.test_lll +test.test_tools.test_md5sum +test.test_tools.test_pathfix +test.test_tools.test_pdeps +test.test_tools.test_pindent +test.test_tools.test_reindent +test.test_tools.test_sundry +test.test_tools.test_unparse +test.test_trace +test.test_traceback +test.test_tracemalloc +test.test_ttk_guionly +test.test_ttk_textonly +test.test_tuple +test.test_turtle +test.test_typechecks +test.test_type_comments +test.test_types +test.test_typing +test.test_ucn +test.test_unary +test.test_unicode +test.test_unicodedata +test.test_unicode_file +test.test_unicode_file_functions +test.test_unicode_identifiers +test.test_unittest +test.test_univnewlines +test.test_unpack +test.test_unpack_ex +test.test_urllib +test.test_urllib2 +test.test_urllib2_localnet +test.test_urllib2net +test.test_urllibnet +test.test_urllib_response +test.test_urlparse +test.test_userdict +test.test_userlist +test.test_userstring +test.test_utf8_mode +test.test_utf8source +test.test_uu +test.test_uuid +test.test_venv +test.test_wait3 +test.test_wait4 +test.test_warnings +test.test_warnings.data.import_warning +test.test_warnings.data.stacklevel +test.test_warnings.__main__ +test.test_wave +test.test_weakref +test.test_weakset +test.test_webbrowser +test.test_winconsoleio +test.test_winreg +test.test_winsound +test.test_with +test.test_wsgiref +test.test_xdrlib +test.test_xml_dom_minicompat +test.test_xml_etree +test.test_xml_etree_c +test.test_xmlrpc +test.test_xmlrpc_net +test.test__xxsubinterpreters +test.test_xxtestfuzz +test.test_yield_from +test.test_zipapp +test.test_zipfile +test.test_zipfile64 +test.test_zipimport +test.test_zipimport_support +test.test_zlib +test.tf_inherit_check +test.threaded_import_hangers +test.time_hashlib +test.tracedmodules +test.tracedmodules.testmod +test.win_console_handler +test.xmltests +test.ziptestdata.testdata_module_inside_zip textwrap -thread +this +_thread threading +_threading_local time timeit -Tix -Tkinter +_tkinter tkinter +tkinter.colorchooser +tkinter.commondialog +tkinter.constants +tkinter.dialog +tkinter.dnd +tkinter.filedialog +tkinter.font +tkinter.__main__ +tkinter.messagebox tkinter.scrolledtext +tkinter.simpledialog +tkinter.test +tkinter.test.runtktests +tkinter.test.support +tkinter.test.test_tkinter +tkinter.test.test_tkinter.test_font +tkinter.test.test_tkinter.test_geometry_managers +tkinter.test.test_tkinter.test_images +tkinter.test.test_tkinter.test_loadtk +tkinter.test.test_tkinter.test_misc +tkinter.test.test_tkinter.test_text +tkinter.test.test_tkinter.test_variables +tkinter.test.test_tkinter.test_widgets +tkinter.test.test_ttk +tkinter.test.test_ttk.test_extensions +tkinter.test.test_ttk.test_functions +tkinter.test.test_ttk.test_style +tkinter.test.test_ttk.test_widgets +tkinter.test.widget_tests tkinter.tix tkinter.ttk token tokenize trace traceback +_tracemalloc tracemalloc -ttk tty turtle turtledemo +turtledemo.bytedesign +turtledemo.chaos +turtledemo.clock +turtledemo.colormixer +turtledemo.forest +turtledemo.fractalcurves +turtledemo.lindenmayer +turtledemo.__main__ +turtledemo.minimal_hanoi +turtledemo.nim +turtledemo.paint +turtledemo.peace +turtledemo.penrose +turtledemo.planet_and_moon +turtledemo.rosette +turtledemo.round_dance +turtledemo.sorting_animate +turtledemo.tree +turtledemo.two_canvases +turtledemo.yinyang types typing +typing.io +typing.re unicodedata unittest +unittest.async_case +unittest.case +unittest.loader +unittest._log +unittest.__main__ +unittest.main unittest.mock +unittest.result +unittest.runner +unittest.signals +unittest.suite +unittest.test +unittest.test.dummy +unittest.test.__main__ +unittest.test.support +unittest.test.test_assertions +unittest.test.test_async_case +unittest.test.test_break +unittest.test.test_case +unittest.test.test_discovery +unittest.test.test_functiontestcase +unittest.test.test_loader +unittest.test.testmock +unittest.test.testmock.__main__ +unittest.test.testmock.support +unittest.test.testmock.testasync +unittest.test.testmock.testcallable +unittest.test.testmock.testhelpers +unittest.test.testmock.testmagicmethods +unittest.test.testmock.testmock +unittest.test.testmock.testpatch +unittest.test.testmock.testsealable +unittest.test.testmock.testsentinel +unittest.test.testmock.testwith +unittest.test.test_program +unittest.test.test_result +unittest.test.test_runner +unittest.test.test_setups +unittest.test.test_skipping +unittest.test.test_suite +unittest.test._test_warnings +unittest.util urllib urllib.error urllib.parse urllib.request urllib.response urllib.robotparser -urllib2 -urlparse -user -UserDict -UserList -UserString uu +_uuid uuid venv -videoreader -W +venv.__main__ +_warnings warnings wave +_weakref weakref +_weakrefset webbrowser -whichdb winreg winsound wsgiref @@ -476,22 +1746,40 @@ wsgiref.validate xdrlib xml xml.dom +xml.dom.domreg +xml.dom.expatbuilder +xml.dom.minicompat xml.dom.minidom +xml.dom.NodeFilter xml.dom.pulldom +xml.dom.xmlbuilder +xml.etree +xml.etree.cElementTree +xml.etree.ElementInclude +xml.etree.ElementPath xml.etree.ElementTree +xml.parsers xml.parsers.expat xml.parsers.expat.errors xml.parsers.expat.model -xml.sax -xml.sax.handler -xml.sax.saxutils -xml.sax.xmlreader xmlrpc xmlrpc.client xmlrpc.server -xmlrpclib -yp +xml.sax +xml.sax._exceptions +xml.sax.expatreader +xml.sax.handler +xml.sax.saxutils +xml.sax.xmlreader +xxlimited +_xxsubinterpreters +xxsubtype +_xxtestfuzz zipapp zipfile zipimport zlib +zoneinfo +zoneinfo._common +zoneinfo._tzpath +zoneinfo._zoneinfo diff --git a/setup.py b/setup.py index 1afa42f..f119905 100755 --- a/setup.py +++ b/setup.py @@ -1,6 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- - try: from setuptools import setup @@ -34,7 +32,7 @@ setup( package_dir={'pipreqs': 'pipreqs'}, include_package_data=True, - package_data={'': ['stdlib','mapping']}, + package_data={'': ['stdlib', 'mapping']}, install_requires=requirements, license='Apache License', zip_safe=False, @@ -44,12 +42,11 @@ setup( 'Intended Audience :: Developers', 'License :: OSI Approved :: Apache Software License', 'Natural Language :: English', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', ], test_suite='tests', entry_points={ diff --git a/tox.ini b/tox.ini index 554b3c1..253097e 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py27, py34, py35, py36, pypy3, flake8 +envlist = py36, py37, py38, py39, pypy3, flake8 [testenv] setenv = @@ -9,7 +9,7 @@ deps = -r{toxinidir}/requirements.txt [testenv:flake8] -basepython = python3.6 +basepython = python3.9 commands = flake8 pipreqs deps = -r{toxinidir}/requirements.txt From 9e514a4caa203d5a02364421abdd5646a8736bf1 Mon Sep 17 00:00:00 2001 From: Rahul Kumaresan Date: Sun, 9 May 2021 21:02:11 +0530 Subject: [PATCH 26/32] update README and pipreqs docstring to help prevent discripancies --- README.rst | 37 +++++++++++++++++++++---------------- pipreqs/pipreqs.py | 10 +++++----- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/README.rst b/README.rst index 07fee33..3c4a530 100644 --- a/README.rst +++ b/README.rst @@ -4,20 +4,20 @@ .. image:: https://img.shields.io/travis/bndr/pipreqs.svg :target: https://travis-ci.org/bndr/pipreqs - - + + .. image:: https://img.shields.io/pypi/v/pipreqs.svg :target: https://pypi.python.org/pypi/pipreqs - -.. image:: https://img.shields.io/coveralls/bndr/pipreqs.svg + +.. image:: https://img.shields.io/coveralls/bndr/pipreqs.svg :target: https://coveralls.io/r/bndr/pipreqs - - -.. image:: https://img.shields.io/pypi/l/pipreqs.svg + + +.. image:: https://img.shields.io/pypi/l/pipreqs.svg :target: https://pypi.python.org/pypi/pipreqs - + Installation ------------ @@ -32,7 +32,11 @@ Usage :: Usage: - pipreqs [options] + pipreqs [options] [] + + Arguments: + The path to the directory containing the application files for which a requirements file + should be generated (defaults to the current working directory) Options: --use-local Use ONLY local package info instead of querying PyPI @@ -42,14 +46,15 @@ Usage $ export HTTP_PROXY="http://10.10.1.10:3128" $ export HTTPS_PROXY="https://10.10.1.10:1080" --debug Print debug information - --ignore ... Ignore extra directories + --ignore ... Ignore extra directories, each separated by a comma + --no-follow-links Do not follow symbolic links in the project --encoding Use encoding parameter for file open --savepath Save the list of requirements in the given file --print Output the list of requirements in the standard output --force Overwrite existing requirements.txt - --diff Compare modules in requirements.txt to project imports. - --clean Clean up requirements.txt by removing modules that are not imported in project. - --mode Enables dynamic versioning with , or schemes. + --diff Compare modules in requirements.txt to project imports + --clean Clean up requirements.txt by removing modules that are not imported in project + --mode Enables dynamic versioning with , or schemes | e.g. Flask~=1.1.2 | e.g. Flask>=1.1.2 | e.g. Flask @@ -68,10 +73,10 @@ Contents of requirements.txt wheel==0.23.0 Yarg==0.1.9 docopt==0.6.2 - + Why not pip freeze? ------------------- -- ``pip freeze`` only saves the packages that are installed with ``pip install`` in your environment. -- ``pip freeze`` saves all packages in the environment including those that you don't use in your current project (if you don't have ``virtualenv``). +- ``pip freeze`` only saves the packages that are installed with ``pip install`` in your environment. +- ``pip freeze`` saves all packages in the environment including those that you don't use in your current project. (if you don't have ``virtualenv``). - and sometimes you just need to create ``requirements.txt`` for a new project without installing modules. diff --git a/pipreqs/pipreqs.py b/pipreqs/pipreqs.py index 381d8d9..24eeeb7 100644 --- a/pipreqs/pipreqs.py +++ b/pipreqs/pipreqs.py @@ -18,18 +18,18 @@ Options: parameter in your terminal: $ export HTTP_PROXY="http://10.10.1.10:3128" $ export HTTPS_PROXY="https://10.10.1.10:1080" - --debug Print debug information. - --ignore ... Ignore extra directories, each separated by a comma. + --debug Print debug information + --ignore ... Ignore extra directories, each separated by a comma --no-follow-links Do not follow symbolic links in the project --encoding Use encoding parameter for file open --savepath Save the list of requirements in the given file --print Output the list of requirements in the standard - output. + output --force Overwrite existing requirements.txt --diff Compare modules in requirements.txt to project - imports. + imports --clean Clean up requirements.txt by removing modules - that are not imported in project. + that are not imported in project --mode Enables dynamic versioning with , or schemes. | e.g. Flask~=1.1.2 From e1d4a929108ea532c2d8b8d957b3b1ccc7f31acc Mon Sep 17 00:00:00 2001 From: Rahul Kumaresan Date: Tue, 11 May 2021 00:55:24 +0530 Subject: [PATCH 27/32] refine markdown --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 3c4a530..fd4b363 100644 --- a/README.rst +++ b/README.rst @@ -78,5 +78,5 @@ Why not pip freeze? ------------------- - ``pip freeze`` only saves the packages that are installed with ``pip install`` in your environment. -- ``pip freeze`` saves all packages in the environment including those that you don't use in your current project. (if you don't have ``virtualenv``). +- ``pip freeze`` saves all packages in the environment including those that you don't use in your current project (if you don't have ``virtualenv``). - and sometimes you just need to create ``requirements.txt`` for a new project without installing modules. From 682a0e2fcf0e3d76a76e99f1744821d789645edb Mon Sep 17 00:00:00 2001 From: Alan Barzilay Date: Fri, 3 Sep 2021 20:51:20 -0300 Subject: [PATCH 28/32] Drop Travis as our CI provider Since travis changed its pricing policy it has become more limited in what we can accomplish with it. It now uses a limited credit model for open source projects which besides being cumbersome puts the project in a precarious position where we may be unable to run tests if we dont have anymore credits. For this reason we will be moving to github actions since they seem to be the best alternative at the moment --- .coveralls.yml | 1 - .travis.yml | 30 ------------------------------ 2 files changed, 31 deletions(-) delete mode 100644 .coveralls.yml delete mode 100644 .travis.yml diff --git a/.coveralls.yml b/.coveralls.yml deleted file mode 100644 index c9c691f..0000000 --- a/.coveralls.yml +++ /dev/null @@ -1 +0,0 @@ -service_name: "travis-ci" \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 67be4ad..0000000 --- a/.travis.yml +++ /dev/null @@ -1,30 +0,0 @@ -# Config file for automatic testing at travis-ci.org - -language: python - -matrix: - include: - - python: 3.9 - env: TOX_ENV=py39 - - python: 3.8 - env: TOX_ENV=py38 - - python: 3.7 - env: TOX_ENV=py37 - - python: 3.6 - env: TOX_ENV=py36 - - python: pypy3 - env: TOX_ENV=pypy3 - - python: 3.9 - env: TOX_ENV=flake8 - -# Use tox to run tests on Travis-CI to keep one unified method of running tests in any environment -install: - - pip install coverage coveralls tox - -# Command to run tests, e.g. python setup.py test -script: tox -e $TOX_ENV - -# Use after_success to get a single coveralls report -after_success: - - coverage run --source=pipreqs setup.py test - - coveralls From aadc9c8de1eebb83c5d6d3fe06d46847090ec1dd Mon Sep 17 00:00:00 2001 From: Alan Barzilay Date: Fri, 3 Sep 2021 20:49:55 -0300 Subject: [PATCH 29/32] Add flake8 github action with review dog Review dog is an incredible project that makes linting and formatting review a breeze by commenting inline what is wrong in a pull request. This makes the review process easier for the maintainer and also provides a clearer feedback to the contributor --- .github/workflows/flake8.yml | 20 ++++++++++++++++++++ tox.ini | 9 +-------- 2 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/flake8.yml diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml new file mode 100644 index 0000000..819104d --- /dev/null +++ b/.github/workflows/flake8.yml @@ -0,0 +1,20 @@ +name: flake8 + +on: pull_request + +jobs: + flake8-lint: + runs-on: ubuntu-latest + name: Lint + steps: + - name: Check out source repository + uses: actions/checkout@v2 + - name: Set up Python environment + uses: actions/setup-python@v2 + with: + python-version: "3.9" + - name: flake8 Lint + uses: reviewdog/action-flake8@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + reporter: github-pr-review diff --git a/tox.ini b/tox.ini index 253097e..6d7a99a 100644 --- a/tox.ini +++ b/tox.ini @@ -6,11 +6,4 @@ setenv = PYTHONPATH = {toxinidir}:{toxinidir}/pipreqs commands = python setup.py test deps = - -r{toxinidir}/requirements.txt - -[testenv:flake8] -basepython = python3.9 -commands = flake8 pipreqs -deps = - -r{toxinidir}/requirements.txt - flake8 + -r{toxinidir}/requirements.txt \ No newline at end of file From e7571ea033a8133d6c344ec5fbc3cfe8c33d9573 Mon Sep 17 00:00:00 2001 From: Alan Barzilay Date: Fri, 3 Sep 2021 20:47:51 -0300 Subject: [PATCH 30/32] Add tox tests & codecov github action This commit essentially adds back tests to our CI pipeline. They were previously dropped due to Travis pricing policy change. This workflow utilizes a few interesting projects to make this action easier to maintain such as the codecov github action and the tox-gh-actions project (https://github.com/ymyzk/tox-gh-actions) This commit uses codecov instead of coveralls because using coveralls directly inside GH-actions is buggy and the official coveralls action only supports lcov reports which we can't seem to be able to generate at the moment. For more information see the pull request that introduced this commit --- .github/workflows/tests.yml | 50 +++++++++++++++++++++++++++++++++++++ README.rst | 5 ++-- tox.ini | 8 ++++++ 3 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/tests.yml diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..288065e --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,50 @@ +name: Tests and Codecov +on: pull_request +jobs: + run_tests: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: [3.6, 3.7, 3.8, 3.9, pypy-3.7] + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install tox tox-gh-actions + + - name: Test with tox + run: tox + + coverage_report: + needs: run_tests + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install coverage docopt yarg requests + + - name: Calculate coverage + run: coverage run --source=pipreqs -m unittest discover + + - name: Create XML report + run: coverage xml + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v2 + with: + files: coverage.xml + fail_ci_if_error: true diff --git a/README.rst b/README.rst index fd4b363..68411fc 100644 --- a/README.rst +++ b/README.rst @@ -10,9 +10,8 @@ :target: https://pypi.python.org/pypi/pipreqs -.. image:: https://img.shields.io/coveralls/bndr/pipreqs.svg - :target: https://coveralls.io/r/bndr/pipreqs - +.. image:: https://codecov.io/gh/bndr/pipreqs/branch/master/graph/badge.svg?token=0rfPfUZEAX + :target: https://codecov.io/gh/bndr/pipreqs .. image:: https://img.shields.io/pypi/l/pipreqs.svg :target: https://pypi.python.org/pypi/pipreqs diff --git a/tox.ini b/tox.ini index 6d7a99a..cf5c2c2 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,14 @@ [tox] envlist = py36, py37, py38, py39, pypy3, flake8 +[gh-actions] +python = + 3.6: py36 + 3.7: py37 + 3.8: py38 + 3.9: py39 + pypy-3.7: pypy3 + [testenv] setenv = PYTHONPATH = {toxinidir}:{toxinidir}/pipreqs From 23097b102c9adedc897852e25083d7dd177c4ffa Mon Sep 17 00:00:00 2001 From: Alan Barzilay Date: Sat, 23 Oct 2021 05:54:58 -0300 Subject: [PATCH 31/32] Version bump to 0.4.11 --- pipreqs/__init__.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pipreqs/__init__.py b/pipreqs/__init__.py index 5b8d242..0491276 100755 --- a/pipreqs/__init__.py +++ b/pipreqs/__init__.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - __author__ = 'Vadim Kravcenko' __email__ = 'vadim.kravcenko@gmail.com' -__version__ = '0.4.8' +__version__ = '0.4.11' From a593d27e3d9fcdecc0fbf385ef43116cccad71ec Mon Sep 17 00:00:00 2001 From: Alan Barzilay Date: Sat, 23 Oct 2021 06:17:21 -0300 Subject: [PATCH 32/32] readme: fix rst syntax While trying to upload release 0.4.11 to pypi I got a few errors due to the rst syntax of the readme. This commit fixes the errors but not the warnings (mostly undeclared long format description type in setup.py) --- README.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 68411fc..16c477a 100644 --- a/README.rst +++ b/README.rst @@ -1,6 +1,6 @@ -=============================== +============================================================================= ``pipreqs`` - Generate requirements.txt file for any project based on imports -=============================== +============================================================================= .. image:: https://img.shields.io/travis/bndr/pipreqs.svg :target: https://travis-ci.org/bndr/pipreqs @@ -57,6 +57,7 @@ Usage | e.g. Flask~=1.1.2 | e.g. Flask>=1.1.2 | e.g. Flask + Example -------