From 90f94c8a8b746433e0925664aa7ea69a014538a1 Mon Sep 17 00:00:00 2001 From: craigmiller Date: Thu, 12 Jan 2023 22:59:10 -0700 Subject: [PATCH] fix_SSLError with testing and doc edits --- .eggs/README.txt | 6 + .vscode/cspell.json | 29 +++ .vscode/extensions.json | 185 ++++++++++++++ .vscode/launch.json | 13 + .vscode/settings.json | 32 ++- CONTRIBUTING.rst | 10 +- README.rst | 2 + pipreqs/pipreqs.py | 1 + requirements-dev.txt | 1 + setup.py | 4 + tests/.env.test.example | 8 + tests/.gitignore | 3 + tests/_data_ignore/requirements.txt | 12 + tests/settings.py | 16 ++ tests/test_pipreqs.py | 381 +++++++++++++++++++--------- tox.ini | 40 ++- 16 files changed, 606 insertions(+), 137 deletions(-) create mode 100644 .eggs/README.txt create mode 100644 .vscode/cspell.json create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 tests/.env.test.example create mode 100644 tests/.gitignore create mode 100644 tests/_data_ignore/requirements.txt create mode 100644 tests/settings.py diff --git a/.eggs/README.txt b/.eggs/README.txt new file mode 100644 index 0000000..5d01668 --- /dev/null +++ b/.eggs/README.txt @@ -0,0 +1,6 @@ +This directory contains eggs that were downloaded by setuptools to build, test, and run plug-ins. + +This directory caches those eggs to prevent repeated downloads. + +However, it is safe to delete this directory. + diff --git a/.vscode/cspell.json b/.vscode/cspell.json new file mode 100644 index 0000000..ff3f350 --- /dev/null +++ b/.vscode/cspell.json @@ -0,0 +1,29 @@ +{ + "version": "0.2", + "ignorePaths": [], + "dictionaryDefinitions": [], + "dictionaries": [], + "words": [ + "beautifulsoup", + "boto", + "compat", + "docopt", + "docstrings", + "dotenv", + "mkvirtualenv", + "nonexistendmodule", + "pipreqs", + "pymongo", + "pypi", + "requiremnts", + "savepath", + "seasurf", + "sqlalchemy", + "ujson", + "virtualenv", + "virtualenvwrapper", + "Yarg" + ], + "ignoreWords": [], + "import": [] +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..f5c874b --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,185 @@ +{ + "recommendations": [ + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // VS Code Editor, Config, Spelling and Themes + // ----------------------------------------------------------------------- + // - Code Spell Checker + "streetsidesoftware.code-spell-checker", + // - EditorConfig for VS Code + "editorconfig.editorconfig", + // - Peacock + "johnpapa.vscode-peacock", + // - Night Owl + "sdras.night-owl", + // - indent-rainbow + "oderwat.indent-rainbow", + // - isort + "ms-python.isort", + // - Prettier - Code formatter + "esbenp.prettier-vscode", + // - vscode-icons + "vscode-icons-team.vscode-icons", + // - vscode-pdf + "tomoki1207.pdf", + // - Workspace Config+ + "swellaby.workspace-config-plus", + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Python + // ----------------------------------------------------------------------- + // - autoDocstring - Python Docstring Generator + //"njpwerner.autodocstring", + // - Django + "batisteo.vscode-django", + // - Pylance + "ms-python.vscode-pylance", + // - Python + "ms-python.python", + // - Python Environment Manager + "donjayamanne.python-environment-manager", + // - Python Extension Pack + "donjayamanne.python-extension-pack", + // - Python Indent + "kevinrose.vsc-python-indent", + // - Test Adapter Converter + "ms-vscode.test-adapter-converter", + // - Test Explorer UI + "hbenl.vscode-test-explorer", + // - python-tox + "the-compiler.python-tox", + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Rust + // ----------------------------------------------------------------------- + // - Rust-Analyzer + "rust-lang.rust-analyzer", + // Better TOML + "bungcip.better-toml", + // - crates + "serayuzgur.crates", + // - Rust Test Explorer + "swellaby.vscode-rust-test-adapter", + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Docker + // ----------------------------------------------------------------------- + // - Docker Compose + "p1c2u.docker-compose", + // - Dev Container + "ms-vscode-remote.remote-containers", + // - Docker + "ms-azuretools.vscode-docker", + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Data + // ----------------------------------------------------------------------- + // - Excel Viewer + "grapecity.gc-excelviewer", + // - MongoDB for VS Code + "mongodb.mongodb-vscode", + // - PlantUML + //"jebbs.plantuml", + // - REST Client + //"humao.rest-client", + // - SQLite Viewer + "qwtel.sqlite-viewer", + // - Thunder Client + "rangav.vscode-thunder-client", + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Git + // ----------------------------------------------------------------------- + // - Git Config User Profiles + "onlyutkarsh.git-config-user-profiles", + // - Git Graph + "mhutchie.git-graph", + // - Git History + "donjayamanne.githistory", + // - git-autoconfig + "shyykoserhiy.git-autoconfig", + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Jupyter Notebook + // ----------------------------------------------------------------------- + // - Jupyter + "ms-toolsai.jupyter", + // - Jupyter Cell Tags + "ms-toolsai.vscode-jupyter-cell-tags", + // - Jupyter Keymap + "ms-toolsai.jupyter-keymap", + // - Jupyter Notebook Renderers + "ms-toolsai.jupyter-renderers", + // - Jupyter PowerToys + //"ms-toolsai.vscode-jupyter-powertoys", + // - Jupyter Slide Show + "ms-toolsai.vscode-jupyter-slideshow", + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Yaml and Json + // ----------------------------------------------------------------------- + // - .NET Install Tool for Extension Authors + "ms-dotnettools.vscode-dotnet-runtime", + // - Azure Resource Manager (ARM) Tools + "msazurermtools.azurerm-vscode-tools", + // - YAML + "redhat.vscode-yaml", + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Markdown + // ----------------------------------------------------------------------- + // - Markdown All in One + "yzhang.markdown-all-in-one", + // - Markdown PDF + "yzane.markdown-pdf", + // - markdownlint + "davidanson.vscode-markdownlint" + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CSS + // ----------------------------------------------------------------------- + // - Auto Rename Tag + //"formulahendry.auto-rename-tag", + // - IntelliSense for CSS class names in HTML + //"zignd.html-css-class-completion", + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // local web server + // ----------------------------------------------------------------------- + // - Live Server + //"ritwickdey.liveserver", + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // JavaScript + // ----------------------------------------------------------------------- + // - Babel JavaScript + //"mgmcdermott.vscode-language-babel", + // - ES7+ React/Redux/React-Native snippets + //"dsznajder.es7-react-js-snippets", + // - ESLint + //"dbaeumer.vscode-eslint", + // - JavaScript (ES6) code snippets + //"xabikos.javascriptsnippets", + // - JavaScript Debugger (Nightly) + //"ms-vscode.js-debug-nightly", + // - Material-UI Snippets + //"vscodeshift.material-ui-snippets", + // - TypeScript + Webpack Problem Matchers + //"amodio.tsl-problem-matcher", + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Java + // ----------------------------------------------------------------------- + // - Debugger for Java + //"vscjava.vscode-java-debug", + // - Extension Pack for Java + //"vscjava.vscode-java-pack", + // - Language Support for Java(TM) by Red Hat + //"redhat.java", + // - Maven for Java + //"vscjava.vscode-maven", + // - Project Manager for Java + //"vscjava.vscode-java-dependency", + // - Test Runner for Java + //"vscjava.vscode-java-test", + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..9197dd3 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,13 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Current File", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal", + "justMyCode": true + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 7369a24..b1f764a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,21 +1,25 @@ { "workbench.colorCustomizations": { - "activityBar.activeBackground": "#f75e3c", - "activityBar.background": "#f75e3c", - "activityBar.foreground": "#15202b", - "activityBar.inactiveForeground": "#15202b99", - "activityBarBadge.background": "#0af535", - "activityBarBadge.foreground": "#15202b", + "activityBar.activeBackground": "#990000", + "activityBar.background": "#990000", + "activityBar.foreground": "#e7e7e7", + "activityBar.inactiveForeground": "#e7e7e799", + "activityBarBadge.background": "#000000", + "activityBarBadge.foreground": "#e7e7e7", "commandCenter.border": "#e7e7e799", - "sash.hoverBorder": "#f75e3c", - "statusBar.background": "#f5350b", + "sash.hoverBorder": "#990000", + "statusBar.background": "#660000", "statusBar.foreground": "#e7e7e7", - "statusBarItem.hoverBackground": "#f75e3c", - "statusBarItem.remoteBackground": "#f5350b", + "statusBarItem.hoverBackground": "#990000", + "statusBarItem.remoteBackground": "#660000", "statusBarItem.remoteForeground": "#e7e7e7", - "titleBar.activeBackground": "#f5350b", + "titleBar.activeBackground": "#660000", "titleBar.activeForeground": "#e7e7e7", - "titleBar.inactiveBackground": "#f5350b99", + "titleBar.inactiveBackground": "#66000099", "titleBar.inactiveForeground": "#e7e7e799" - } -} \ No newline at end of file + }, + "python.testing.unittestArgs": ["-v", "-s", "./tests", "-p", "test_*.py"], + "python.testing.pytestEnabled": false, + "python.testing.unittestEnabled": true, + "peacock.color": "#660000" +} diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 60e73a2..60fcb82 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -66,7 +66,7 @@ Ready to contribute? Here's how to set up `pipreqs` for local development. $ mkvirtualenv pipreqs $ cd pipreqs/ - $ python setup.py develop + $ python setup.py develop (or $pip install -e .) 4. Create a branch for local development:: @@ -80,7 +80,7 @@ Ready to contribute? Here's how to set up `pipreqs` for local development. $ python setup.py test $ tox - To get flake8 and tox, just pip install them into your virtualenv. + To get flake8 and tox, just pip install them into your virtualenv. (or $pip install -r requirements-dev.txt) 6. Commit your changes and push your branch to GitHub:: @@ -99,9 +99,9 @@ Before you submit a pull request, check that it meets these guidelines: 2. If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the list in README.rst. -3. The pull request should work for Python 3.7 to 3.11, and PyPy. Check - https://travis-ci.org/bndr/pipreqs/pull_requests and make sure that the - tests pass for all supported Python versions. +3. The pull request should work for Python 3.7 to 3.10 (3.11 needs work), + and PyPy3. Check https://travis-ci.org/bndr/pipreqs/pull_requests and + make sure that the tests pass for all supported Python versions. Tips ---- diff --git a/README.rst b/README.rst index 16c477a..fe5c87a 100644 --- a/README.rst +++ b/README.rst @@ -44,6 +44,8 @@ Usage environments parameter in your terminal: $ export HTTP_PROXY="http://10.10.1.10:3128" $ export HTTPS_PROXY="https://10.10.1.10:1080" + --verify Use verify to provide a CA_BUNDLE file or directory + with certificates of trusted CAs --debug Print debug information --ignore ... Ignore extra directories, each separated by a comma --no-follow-links Do not follow symbolic links in the project diff --git a/pipreqs/pipreqs.py b/pipreqs/pipreqs.py index 7b1f7e5..2bbb552 100644 --- a/pipreqs/pipreqs.py +++ b/pipreqs/pipreqs.py @@ -187,6 +187,7 @@ def get_imports_info( pypi_server="https://pypi.python.org/pypi/", proxy=None, verify=None, + c=None, ): result = [] diff --git a/requirements-dev.txt b/requirements-dev.txt index e87d699..de3d53b 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,3 +1,4 @@ black flake8 tox +python-dotenv # optional to use .env file instead of environment variables diff --git a/setup.py b/setup.py index 8b826ed..6506d54 100755 --- a/setup.py +++ b/setup.py @@ -17,6 +17,9 @@ with open('HISTORY.rst') as history_file: requirements = [ 'docopt', 'yarg' ] +tests_requirements = [ + 'python-dotenv' +] setup( name='pipreqs', @@ -49,6 +52,7 @@ setup( 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', ], + tests_require=tests_requirements, test_suite='tests', entry_points={ 'console_scripts': [ diff --git a/tests/.env.test.example b/tests/.env.test.example new file mode 100644 index 0000000..5e9f357 --- /dev/null +++ b/tests/.env.test.example @@ -0,0 +1,8 @@ +# create a new file named `.env.test` +# and assign CA_BUNDLE to your system path\ca.pem file + +CA_BUNDLE=C:\your\path\and\certificates.pem + +# alternatively you can set this value as an environment variable +# $ set CA_BUNDLE="C:\your\path\and\certificates.pem" # for win OS +# $ export CA_BUNDLE="C:\your\path\and\certificates.pem" # for nix OS diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..b3d1e40 --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1,3 @@ +# .env.test is system specific +# do not check in to repository +.env.test \ No newline at end of file diff --git a/tests/_data_ignore/requirements.txt b/tests/_data_ignore/requirements.txt new file mode 100644 index 0000000..b7f100d --- /dev/null +++ b/tests/_data_ignore/requirements.txt @@ -0,0 +1,12 @@ +asposestorage==1.0.2 +beautifulsoup4==4.11.1 +boto==2.49.0 +docopt==0.6.2 +Flask==2.2.2 +ipython==8.8.0 +nose==1.3.7 +peewee==3.15.4 +pyflakes==3.0.1 +requests==2.28.2 +SQLAlchemy==1.4.46 +ujson==5.7.0 diff --git a/tests/settings.py b/tests/settings.py new file mode 100644 index 0000000..f5698b6 --- /dev/null +++ b/tests/settings.py @@ -0,0 +1,16 @@ +import importlib +import os + +CA_BUNDLE = os.environ.get("CA_BUNDLE") + +if CA_BUNDLE is None and importlib.find_loader("dotenv"): + # optional loading of values from .env.test file + from pathlib import Path + + import dotenv + + env_test_path = Path(os.path.dirname(__file__) + "/.env.test") + config = dotenv.dotenv_values(env_test_path) + + if config is not None: + CA_BUNDLE = config["CA_BUNDLE"] diff --git a/tests/test_pipreqs.py b/tests/test_pipreqs.py index 6e1510f..1c861ba 100644 --- a/tests/test_pipreqs.py +++ b/tests/test_pipreqs.py @@ -6,6 +6,11 @@ test_pipreqs ---------------------------------- Tests for `pipreqs` module. + +Environment variables used to mock arguments +e.g., +$ set CA_BUNDLE="certificates.pem" # for win OS +$ export CA_BUNDLE="certificates.pem" # for nix OS """ import os @@ -14,48 +19,55 @@ import unittest import requests from pipreqs import pipreqs +from .settings import CA_BUNDLE 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.modules2 = ['beautifulsoup4'] - self.local = ["docopt", "requests", "nose", 'pyflakes'] + "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" - ) + os.path.dirname(__file__), "_data_clean" + ) self.project_invalid = os.path.join( - os.path.dirname(__file__), - "_invalid_data" - ) + os.path.dirname(__file__), "_invalid_data" + ) self.project_with_ignore_directory = os.path.join( - os.path.dirname(__file__), - "_data_ignore" - ) + os.path.dirname(__file__), "_data_ignore" + ) self.project_with_duplicated_deps = os.path.join( - os.path.dirname(__file__), - "_data_duplicated_deps" - ) + 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) for item in imports: self.assertTrue( - item.lower() in self.modules, "Import is missing: " + item) + item.lower() in self.modules, "Import is missing: " + item + ) self.assertFalse("time" in imports) self.assertFalse("logging" in imports) self.assertFalse("curses" in imports) @@ -74,26 +86,30 @@ class TestPipreqs(unittest.TestCase): Test that invalid python files cannot be imported. """ self.assertRaises( - SyntaxError, pipreqs.get_all_imports, self.project_invalid) + SyntaxError, pipreqs.get_all_imports, self.project_invalid + ) def test_get_imports_info(self): """ Test to see that the right number of packages were found on PyPI """ imports = pipreqs.get_all_imports(self.project) - with_info = pipreqs.get_imports_info(imports) + with_info = pipreqs.get_imports_info( + imports, proxy=None, verify=CA_BUNDLE + ) # 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, - "Import item appears to be missing " + item['name']) + item["name"].lower() in self.modules, + "Import item appears to be missing " + item["name"], + ) def test_get_pkg_names(self): - pkgs = ['jury', 'Japan', 'camel', 'Caroline'] + pkgs = ["jury", "Japan", "camel", "Caroline"] actual_output = pipreqs.get_pkg_names(pkgs) - expected_output = ['camel', 'Caroline', 'Japan', 'jury'] + expected_output = ["camel", "Caroline", "Japan", "jury"] self.assertEqual(actual_output, expected_output) def test_get_use_local_only(self): @@ -108,22 +124,34 @@ class TestPipreqs(unittest.TestCase): # should find only docopt and requests imports_with_info = pipreqs.get_import_local(self.modules) for item in imports_with_info: - self.assertTrue(item['name'].lower() in self.local) + self.assertTrue(item["name"].lower() in self.local) def test_init(self): """ 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}) + pipreqs.init( + { + "": self.project, + "--savepath": None, + "--print": False, + "--use-local": None, + "--force": True, + "--proxy": None, + "--verify": CA_BUNDLE, + "--pypi-server": 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') + data = data.strip().split("\n") self.assertEqual(data, sorted(data)) def test_init_local_only(self): @@ -131,9 +159,21 @@ class TestPipreqs(unittest.TestCase): 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}) + pipreqs.init( + { + "": self.project, + "--savepath": None, + "--print": False, + "--use-local": True, + "--force": True, + "--proxy": None, + "--verify": CA_BUNDLE, + "--pypi-server": 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() @@ -146,9 +186,20 @@ class TestPipreqs(unittest.TestCase): 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, '--mode': None}) + pipreqs.init( + { + "": self.project, + "--savepath": self.alt_requirement_path, + "--use-local": None, + "--proxy": None, + "--verify": CA_BUNDLE, + "--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() @@ -164,9 +215,21 @@ class TestPipreqs(unittest.TestCase): """ 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, + "--verify": CA_BUNDLE, + "--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() @@ -182,40 +245,59 @@ class TestPipreqs(unittest.TestCase): 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) + 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'} - ) + requests.exceptions.MissingSchema, + pipreqs.init, + { + "": self.project, + "--savepath": None, + "--print": False, + "--use-local": None, + "--force": True, + "--proxy": None, + "--verify": CA_BUNDLE, + "--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, - '--mode': None - } + { + "": self.project_with_ignore_directory, + "--savepath": None, + "--print": False, + "--use-local": None, + "--force": True, + "--proxy": None, + "--verify": CA_BUNDLE, + "--pypi-server": None, + "--ignore": ".ignored_dir,.ignore_second", + "--diff": None, + "--clean": None, + "--mode": None, + } ) - with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: + with open( + os.path.join( + self.project_with_ignore_directory, "requirements.txt" + ), + "r", + ) as f: data = f.read().lower() - for item in ['click', 'getpass']: + for item in ["click", "getpass"]: self.assertFalse(item.lower() in data) def test_dynamic_version_no_pin_scheme(self): @@ -223,17 +305,28 @@ class TestPipreqs(unittest.TestCase): 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' - } + { + "": self.project_with_ignore_directory, + "--savepath": None, + "--print": False, + "--use-local": None, + "--force": True, + "--proxy": None, + "--verify": CA_BUNDLE, + "--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: + with open( + os.path.join( + self.project_with_ignore_directory, "requirements.txt" + ), + "r", + ) as f: data = f.read().lower() - for item in ['beautifulsoup4', 'boto']: + for item in ["beautifulsoup4", "boto"]: self.assertTrue(item.lower() in data) def test_dynamic_version_gt_scheme(self): @@ -241,20 +334,30 @@ class TestPipreqs(unittest.TestCase): Test --mode=gt """ 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': 'gt' - } + { + "": self.project_with_ignore_directory, + "--savepath": None, + "--print": False, + "--use-local": None, + "--force": True, + "--proxy": None, + "--verify": CA_BUNDLE, + "--pypi-server": None, + "--diff": None, + "--clean": None, + "--mode": "gt", + } ) - with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: + 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' + symbol = ">=" + message = "symbol is not in item" self.assertIn(symbol, item, message) def test_dynamic_version_compat_scheme(self): @@ -262,20 +365,30 @@ class TestPipreqs(unittest.TestCase): 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' - } + { + "": self.project_with_ignore_directory, + "--savepath": None, + "--print": False, + "--use-local": None, + "--force": True, + "--proxy": None, + "--verify": CA_BUNDLE, + "--pypi-server": None, + "--diff": None, + "--clean": None, + "--mode": "compat", + } ) - with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: + 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' + symbol = "~=" + message = "symbol is not in item" self.assertIn(symbol, item, message) def test_clean(self): @@ -283,18 +396,36 @@ 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, - '--mode': None} - ) + { + "": self.project, + "--savepath": None, + "--print": False, + "--use-local": None, + "--force": True, + "--proxy": None, + "--verify": CA_BUNDLE, + "--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'} - ) + { + "": self.project, + "--savepath": None, + "--print": False, + "--use-local": None, + "--force": None, + "--proxy": None, + "--verify": CA_BUNDLE, + "--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]: @@ -304,21 +435,39 @@ class TestPipreqs(unittest.TestCase): """ Test --clean parameter when there are imports to clean """ - cleaned_module = 'sqlalchemy' + 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} - ) + { + "": self.project, + "--savepath": None, + "--print": False, + "--use-local": None, + "--force": True, + "--proxy": None, + "--verify": CA_BUNDLE, + "--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'} - ) + { + "": self.project_clean, + "--savepath": None, + "--print": False, + "--use-local": None, + "--force": None, + "--proxy": None, + "--verify": CA_BUNDLE, + "--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) @@ -337,5 +486,5 @@ class TestPipreqs(unittest.TestCase): pass -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tox.ini b/tox.ini index aea10ec..ceb5265 100644 --- a/tox.ini +++ b/tox.ini @@ -1,11 +1,12 @@ [tox] -envlist = py37, py38, py39, pypy3, flake8 +envlist = py37, py38, py39, py310, pypy3, flake8 [gh-actions] python = 3.7: py37 3.8: py38 3.9: py39 + 3.10: py310 pypy-3.7: pypy3 [testenv] @@ -13,4 +14,39 @@ setenv = PYTHONPATH = {toxinidir}:{toxinidir}/pipreqs commands = python setup.py test deps = - -r{toxinidir}/requirements.txt \ No newline at end of file + -r{toxinidir}/requirements.txt + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# tox -e dev311 +# Python 3.11 runtime error +# - py310 and py311 were not tested prior to this submission +# - not related to this submission (but this needs further debug to understand) +# +# ====================================================================== +# FAIL: test_get_use_local_only (tests.test_pipreqs.TestPipreqs.test_get_use_local_only) +# Test without checking PyPI, check to see if names of local +# ---------------------------------------------------------------------- +# Traceback (most recent call last): +# File "c:\code\ghcwm\py_dev\src\autoreq\pub\c-w-m\pipreqs\tests\test_pipreqs.py", line 127, in test_get_use_local_only +# self.assertTrue(item["name"].lower() in self.local) +# AssertionError: False is not true +# +# ====================================================================== +# FAIL: test_init_local_only (tests.test_pipreqs.TestPipreqs.test_init_local_only) +# Test that items listed in requirements.text are the same +# ---------------------------------------------------------------------- +# Traceback (most recent call last): +# File "c:\code\ghcwm\py_dev\src\autoreq\pub\c-w-m\pipreqs\tests\test_pipreqs.py", line 182, in test_init_local_only +# self.assertTrue(item[0].lower() in self.local) +# AssertionError: False is not true +# +# ---------------------------------------------------------------------- +[testenv:dev311] +description = development mode environment for debug of py311 +basepython = python3.11 +deps = {[testenv]deps} +# development mode for debuging +usedevelop = True +commands = python setup.py test + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~