diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..521e659 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,756 @@ +[[package]] +name = "astroid" +version = "2.11.7" +description = "An abstract syntax tree for Python with inference support." +category = "dev" +optional = false +python-versions = ">=3.6.2" + +[package.dependencies] +lazy-object-proxy = ">=1.4.0" +typed-ast = {version = ">=1.4.0,<2.0", markers = "implementation_name == \"cpython\" and python_version < \"3.8\""} +typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} +wrapt = ">=1.11,<2" + +[[package]] +name = "atomicwrites" +version = "1.4.1" +description = "Atomic file writes." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "attrs" +version = "22.1.0" +description = "Classes Without Boilerplate" +category = "dev" +optional = false +python-versions = ">=3.5" + +[package.extras] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] +docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] +tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "cloudpickle"] + +[[package]] +name = "bandit" +version = "1.7.4" +description = "Security oriented static analyser for python code." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} +GitPython = ">=1.0.1" +PyYAML = ">=5.3.1" +stevedore = ">=1.20.0" + +[package.extras] +test = ["coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "toml", "beautifulsoup4 (>=4.8.0)", "pylint (==1.9.4)"] +toml = ["toml"] +yaml = ["pyyaml"] + +[[package]] +name = "black" +version = "22.6.0" +description = "The uncompromising code formatter." +category = "dev" +optional = false +python-versions = ">=3.6.2" + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} +typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""} +typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "certifi" +version = "2022.6.15" +description = "Python package for providing Mozilla's CA Bundle." +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "cfgv" +version = "3.3.1" +description = "Validate configuration and produce human readable error messages." +category = "main" +optional = false +python-versions = ">=3.6.1" + +[[package]] +name = "charset-normalizer" +version = "2.1.0" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" +optional = false +python-versions = ">=3.6.0" + +[package.extras] +unicode_backport = ["unicodedata2"] + +[[package]] +name = "click" +version = "8.1.3" +description = "Composable command line interface toolkit" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} +importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} + +[[package]] +name = "colorama" +version = "0.4.5" +description = "Cross-platform colored terminal text." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "coverage" +version = "6.4.2" +description = "Code coverage measurement for Python" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +toml = ["tomli"] + +[[package]] +name = "dill" +version = "0.3.5.1" +description = "serialize all of python" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" + +[package.extras] +graph = ["objgraph (>=1.7.2)"] + +[[package]] +name = "distlib" +version = "0.3.5" +description = "Distribution utilities" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "dparse" +version = "0.5.1" +description = "A parser for Python dependency files" +category = "main" +optional = false +python-versions = ">=3.5" + +[package.dependencies] +packaging = "*" +pyyaml = "*" +toml = "*" + +[package.extras] +pipenv = ["pipenv"] + +[[package]] +name = "filelock" +version = "3.7.1" +description = "A platform independent file lock." +category = "main" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"] +testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-cov", "pytest-timeout (>=1.4.2)"] + +[[package]] +name = "flake8" +version = "4.0.1" +description = "the modular source code checker: pep8 pyflakes and co" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +importlib-metadata = {version = "<4.3", markers = "python_version < \"3.8\""} +mccabe = ">=0.6.0,<0.7.0" +pycodestyle = ">=2.8.0,<2.9.0" +pyflakes = ">=2.4.0,<2.5.0" + +[[package]] +name = "gitdb" +version = "4.0.9" +description = "Git Object Database" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +smmap = ">=3.0.1,<6" + +[[package]] +name = "gitpython" +version = "3.1.27" +description = "GitPython is a python library used to interact with Git repositories" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +gitdb = ">=4.0.1,<5" +typing-extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.8\""} + +[[package]] +name = "identify" +version = "2.5.2" +description = "File identification library for Python" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.extras] +license = ["ukkonen"] + +[[package]] +name = "idna" +version = "3.3" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "importlib-metadata" +version = "4.2.0" +description = "Read metadata from Python packages" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} +zipp = ">=0.5" + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] +testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] + +[[package]] +name = "iniconfig" +version = "1.1.1" +description = "iniconfig: brain-dead simple config-ini parsing" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "isort" +version = "5.10.1" +description = "A Python utility / library to sort Python imports." +category = "dev" +optional = false +python-versions = ">=3.6.1,<4.0" + +[package.extras] +pipfile_deprecated_finder = ["pipreqs", "requirementslib"] +requirements_deprecated_finder = ["pipreqs", "pip-api"] +colors = ["colorama (>=0.4.3,<0.5.0)"] +plugins = ["setuptools"] + +[[package]] +name = "lazy-object-proxy" +version = "1.7.1" +description = "A fast and thorough lazy object proxy." +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mccabe" +version = "0.6.1" +description = "McCabe checker, plugin for flake8" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "mypy" +version = "0.961" +description = "Optional static typing for Python" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +mypy-extensions = ">=0.4.3" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typed-ast = {version = ">=1.4.0,<2", markers = "python_version < \"3.8\""} +typing-extensions = ">=3.10" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +python2 = ["typed-ast (>=1.4.0,<2)"] +reports = ["lxml"] + +[[package]] +name = "mypy-extensions" +version = "0.4.3" +description = "Experimental type system extensions for programs checked with the mypy typechecker." +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "nodeenv" +version = "1.7.0" +description = "Node.js virtual environment builder" +category = "main" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" + +[[package]] +name = "packaging" +version = "21.3" +description = "Core utilities for Python packages" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" + +[[package]] +name = "pathspec" +version = "0.9.0" +description = "Utility library for gitignore style pattern matching of file paths." +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" + +[[package]] +name = "pbr" +version = "5.9.0" +description = "Python Build Reasonableness" +category = "dev" +optional = false +python-versions = ">=2.6" + +[[package]] +name = "platformdirs" +version = "2.5.2" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "main" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"] +test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"] + +[[package]] +name = "pluggy" +version = "1.0.0" +description = "plugin and hook calling mechanisms for python" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} + +[package.extras] +testing = ["pytest-benchmark", "pytest"] +dev = ["tox", "pre-commit"] + +[[package]] +name = "pre-commit" +version = "2.20.0" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +toml = "*" +virtualenv = ">=20.0.8" + +[[package]] +name = "py" +version = "1.11.0" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "pycodestyle" +version = "2.8.0" +description = "Python style guide checker" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "pyflakes" +version = "2.4.0" +description = "passive checker of Python programs" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "pylint" +version = "2.14.5" +description = "python code static checker" +category = "dev" +optional = false +python-versions = ">=3.7.2" + +[package.dependencies] +astroid = ">=2.11.6,<=2.12.0-dev0" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +dill = ">=0.2" +isort = ">=4.2.5,<6" +mccabe = ">=0.6,<0.8" +platformdirs = ">=2.2.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +tomlkit = ">=0.10.1" +typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} + +[package.extras] +spelling = ["pyenchant (>=3.2,<4.0)"] +testutils = ["gitpython (>3)"] + +[[package]] +name = "pyparsing" +version = "3.0.9" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +category = "main" +optional = false +python-versions = ">=3.6.8" + +[package.extras] +diagrams = ["railroad-diagrams", "jinja2"] + +[[package]] +name = "pytest" +version = "7.1.2" +description = "pytest: simple powerful testing with Python" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} +attrs = ">=19.2.0" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +py = ">=1.8.2" +tomli = ">=1.0.0" + +[package.extras] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "2.6.0" +description = "Pytest plugin for measuring coverage." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[package.dependencies] +coverage = ">=4.4" +pytest = ">=2.9" + +[[package]] +name = "pytest-mock" +version = "3.8.2" +description = "Thin-wrapper around the mock package for easier use with pytest" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +pytest = ">=5.0" + +[package.extras] +dev = ["pre-commit", "tox", "pytest-asyncio"] + +[[package]] +name = "python-dotenv" +version = "0.20.0" +description = "Read key-value pairs from a .env file and set them as environment variables" +category = "dev" +optional = false +python-versions = ">=3.5" + +[package.extras] +cli = ["click (>=5.0)"] + +[[package]] +name = "pyyaml" +version = "6.0" +description = "YAML parser and emitter for Python" +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "requests" +version = "2.28.1" +description = "Python HTTP for Humans." +category = "main" +optional = false +python-versions = ">=3.7, <4" + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<3" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<1.27" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "ruamel.yaml" +version = "0.17.21" +description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" +category = "main" +optional = false +python-versions = ">=3" + +[package.dependencies] +"ruamel.yaml.clib" = {version = ">=0.2.6", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.11\""} + +[package.extras] +docs = ["ryd"] +jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] + +[[package]] +name = "ruamel.yaml.clib" +version = "0.2.6" +description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" +category = "main" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "safety" +version = "2.1.1" +description = "Checks installed dependencies for known vulnerabilities and licenses." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +Click = ">=8.0.2" +dparse = ">=0.5.1" +packaging = ">=21.0" +requests = "*" +"ruamel.yaml" = ">=0.17.21" + +[[package]] +name = "smmap" +version = "5.0.0" +description = "A pure Python implementation of a sliding window memory map manager" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "stevedore" +version = "3.5.0" +description = "Manage dynamic plugins for Python applications" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +importlib-metadata = {version = ">=1.7.0", markers = "python_version < \"3.8\""} +pbr = ">=2.0.0,<2.1.0 || >2.1.0" + +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +category = "main" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "tomlkit" +version = "0.11.1" +description = "Style preserving TOML library" +category = "dev" +optional = false +python-versions = ">=3.6,<4.0" + +[[package]] +name = "typed-ast" +version = "1.5.4" +description = "a fork of Python 2 and 3 ast modules with type comment support" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "typing-extensions" +version = "4.3.0" +description = "Backported and Experimental Type Hints for Python 3.7+" +category = "main" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "urllib3" +version = "1.26.11" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4" + +[package.extras] +brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] +secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + +[[package]] +name = "virtualenv" +version = "20.16.2" +description = "Virtual Python Environment builder" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +distlib = ">=0.3.1,<1" +filelock = ">=3.2,<4" +importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} +platformdirs = ">=2,<3" + +[package.extras] +docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"] +testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "packaging (>=20.0)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)"] + +[[package]] +name = "wrapt" +version = "1.14.1" +description = "Module for decorators, wrappers and monkey patching." +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" + +[[package]] +name = "zipp" +version = "3.8.1" +description = "Backport of pathlib-compatible object wrapper for zip files" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "jaraco.tidelift (>=1.4)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.3)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] + +[metadata] +lock-version = "1.1" +python-versions = ">=3.7.2,<4" +content-hash = "a58f20b25321f48c9341ed827ec1453a92ddc73943e8f3bebe32ae3947b4471c" + +[metadata.files] +astroid = [] +atomicwrites = [] +attrs = [] +bandit = [] +black = [] +certifi = [] +cfgv = [] +charset-normalizer = [] +click = [] +colorama = [] +coverage = [] +dill = [] +distlib = [] +dparse = [] +filelock = [] +flake8 = [] +gitdb = [] +gitpython = [] +identify = [] +idna = [] +importlib-metadata = [] +iniconfig = [] +isort = [] +lazy-object-proxy = [] +mccabe = [] +mypy = [] +mypy-extensions = [] +nodeenv = [] +packaging = [] +pathspec = [] +pbr = [] +platformdirs = [] +pluggy = [] +pre-commit = [] +py = [] +pycodestyle = [] +pyflakes = [] +pylint = [] +pyparsing = [] +pytest = [] +pytest-cov = [] +pytest-mock = [] +python-dotenv = [] +pyyaml = [] +requests = [] +"ruamel.yaml" = [] +"ruamel.yaml.clib" = [] +safety = [] +smmap = [] +stevedore = [] +toml = [] +tomli = [] +tomlkit = [] +typed-ast = [] +typing-extensions = [] +urllib3 = [] +virtualenv = [] +wrapt = [] +zipp = [] diff --git a/pre_commit_hooks/safety_check.py b/pre_commit_hooks/safety_check.py index 5ea36bd..6f6d402 100755 --- a/pre_commit_hooks/safety_check.py +++ b/pre_commit_hooks/safety_check.py @@ -1,5 +1,8 @@ +"""Safety utilities.""" from __future__ import print_function + +# Standar libraries import argparse import os import sys @@ -9,10 +12,12 @@ from subprocess import check_call from tempfile import NamedTemporaryFile +# Third part libraries from safety.cli import cli def build_parser(): + """Build a parser in order to get args.""" parser = argparse.ArgumentParser() parser.add_argument( "--full-report", @@ -36,22 +41,36 @@ def main(argv=None): # pylint: disable=inconsistent-return-statements parser = build_parser() parsed_args, args_rest = parser.parse_known_args(argv) if all("requirements" in file_path for file_path in parsed_args.files): - return call_safety_check(parsed_args.files, parsed_args.ignore, parsed_args.report_arg, args_rest) + return call_safety_check( + parsed_args.files, parsed_args.ignore, parsed_args.report_arg, args_rest + ) files = [Path(f) for f in parsed_args.files] if len(files) == 1 and files[0].name == "pyproject.toml": pyproject_toml_filepath = files[0] with pyproject_toml_filepath.open() as pyproject_file: lines = [line.strip() for line in pyproject_file.readlines()] if any(line.startswith("[tool.poetry]") for line in lines): - with convert_poetry_to_requirements(pyproject_toml_filepath) as tmp_requirements: - return call_safety_check([tmp_requirements.name], parsed_args.ignore, parsed_args.report_arg, args_rest) - parser.error("Unsupported build tool: this pre-commit hook currently only handles pyproject.toml with Poetry" - " ([tool.poetry] must be present in pyproject.toml)") + with convert_poetry_to_requirements( + pyproject_toml_filepath + ) as tmp_requirements: + return call_safety_check( + [tmp_requirements.name], + parsed_args.ignore, + parsed_args.report_arg, + args_rest, + ) + parser.error( + "Unsupported build tool: this pre-commit hook currently only handles pyproject.toml with Poetry" + " ([tool.poetry] must be present in pyproject.toml)" + ) else: - parser.error(f"Unsupported mix of pyproject.toml & requirements files found: {parsed_args.files}") + parser.error( + f"Unsupported mix of pyproject.toml & requirements files found: {parsed_args.files}" + ) def call_safety_check(requirements_file_paths, ignore_args, report_arg, args_rest): + """Call the safety cli checks.""" safety_args = [] if "--disable-telemetry" in args_rest: safety_args.append("--disable-telemetry") @@ -59,7 +78,7 @@ def call_safety_check(requirements_file_paths, ignore_args, report_arg, args_res safety_args.append("check") for file_path in requirements_file_paths: safety_args += ["--file", file_path] - for codes in (ignore_args or []): + for codes in ignore_args or []: for code in codes.split(","): safety_args += ["--ignore", code] try: @@ -73,16 +92,30 @@ def call_safety_check(requirements_file_paths, ignore_args, report_arg, args_res def convert_poetry_to_requirements(pyproject_toml_filepath): # Sad function name :( poetry_cmd_path = which("poetry") if not poetry_cmd_path: # Using install-poetry.py installation $PATH: - poetry_cmd_path = os.path.join(os.environ.get("HOME", ""), ".local", "bin", "poetry") + poetry_cmd_path = os.path.join( + os.environ.get("HOME", ""), ".local", "bin", "poetry" + ) if not os.path.exists(poetry_cmd_path): # Old get-poetry.py installation $PATH: - poetry_cmd_path = os.path.join(os.environ.get("HOME", ""), ".poetry", "bin", "poetry") + poetry_cmd_path = os.path.join( + os.environ.get("HOME", ""), ".poetry", "bin", "poetry" + ) # Always passing delete=False to NamedTemporaryFile in order to avoid permission errors on Windows: try: ntf = NamedTemporaryFile(delete=False) with ntf: # Placing ourselves in the pyproject.toml parent directory: with chdir(pyproject_toml_filepath.parent): - check_call([poetry_cmd_path, "export", "--dev", "--format", "requirements.txt", "--output", ntf.name]) + check_call( + [ + poetry_cmd_path, + "export", + "--dev", + "--format", + "requirements.txt", + "--output", + ntf.name, + ] + ) yield ntf finally: # Manually deleting temporary file: os.remove(ntf.name) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..8d9d61a --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,53 @@ +[tool.poetry] +name = "pre-commit-hooks-safety" +version = "1.3.1" +description = "A pre-commit hook to check your Python dependencies against safety-db" +authors = ["Lucas Cimon "] +repository = "https://github.com/Lucas-C/pre-commit-hooks-safety" +classifiers = [ + 'License :: OSI Approved :: MIT License', + "Intended Audience :: Developers", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + 'Programming Language :: Python :: 3.7', + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + 'Programming Language :: Python :: Implementation :: CPython', + 'Programming Language :: Python :: Implementation :: PyPy', + "Topic :: Software Development", +] +packages = [ + { include = "pre_commit_hooks" }, + { include = "pre_commit_hooks/safety_check.py" }, +] + +[tool.poetry.dependencies] +python = ">=3.7.2,<4" +safety = "^2.1.1" +pre-commit = "^2.20.0" + +[tool.poetry.dev-dependencies] +pytest = "^7.1.2" +pytest-cov = "2.6.0" +pytest-mock = "^3.6.1" +black = "^22.3.0" +mypy = "^0.961" +bandit = "^1.7.4" +flake8 = "^4.0.1" +pylint = "^2.14.2" +python-dotenv = "^0.20.0" + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" + +[tool.poetry.scripts] +safety_check = "pre_commit_hooks.safety_check:main" + +# pyproject.toml +[tool.pytest.ini_options] +addopts = "--verbose --junit-xml=report.xml --cov --cov-report=xml:coverage.xml" + +[flake8] +max-line-length = 140 \ No newline at end of file diff --git a/tests/safety_test.py b/tests/safety_test.py index 48619c9..6e4005c 100644 --- a/tests/safety_test.py +++ b/tests/safety_test.py @@ -1,50 +1,66 @@ +"""Test module.""" + # pylint: disable=invalid-name,line-too-long from __future__ import absolute_import from __future__ import unicode_literals +# Standar libraries import pytest from safety.constants import EXIT_CODE_VULNERABILITIES_FOUND +# Third part libraries from pre_commit_hooks.safety_check import main as safety def test_dev_requirements(): - assert safety(['dev-requirements.txt']) == 0 + assert safety(["dev-requirements.txt"]) == 0 + def test_non_ok_dependency(tmpdir): - requirements_file = tmpdir.join('requirements.txt') - requirements_file.write('urllib3==1.24.1') + requirements_file = tmpdir.join("requirements.txt") + requirements_file.write("urllib3==1.24.1") assert safety([str(requirements_file)]) == EXIT_CODE_VULNERABILITIES_FOUND + def test_short_report(tmpdir): - requirements_file = tmpdir.join('requirements.txt') - requirements_file.write('urllib3==1.24.1') - assert safety(["--short-report", str(requirements_file)]) == EXIT_CODE_VULNERABILITIES_FOUND + requirements_file = tmpdir.join("requirements.txt") + requirements_file.write("urllib3==1.24.1") + assert ( + safety(["--short-report", str(requirements_file)]) + == EXIT_CODE_VULNERABILITIES_FOUND + ) + def test_disable_telemetry(tmpdir): - requirements_file = tmpdir.join('requirements.txt') - requirements_file.write('urllib3==1.24.1') - assert safety(["--disable-telemetry", str(requirements_file)]) == EXIT_CODE_VULNERABILITIES_FOUND + requirements_file = tmpdir.join("requirements.txt") + requirements_file.write("urllib3==1.24.1") + assert ( + safety(["--disable-telemetry", str(requirements_file)]) + == EXIT_CODE_VULNERABILITIES_FOUND + ) + @pytest.mark.parametrize("report", [["--full-report"], []]) def test_full_report(tmpdir, report, capfd): - requirements_file = tmpdir.join('requirements.txt') - requirements_file.write('urllib3==1.24.1') + requirements_file = tmpdir.join("requirements.txt") + requirements_file.write("urllib3==1.24.1") assert safety(report + [str(requirements_file)]) == EXIT_CODE_VULNERABILITIES_FOUND assert "urllib3 library" in capfd.readouterr().out + @pytest.mark.parametrize( "args", [ ["--ignore=37055,37071,38834,43975"], - ['--ignore=37055', '--ignore=37071', '--ignore=38834', '--ignore=43975'], - ] + ["--ignore=37055", "--ignore=37071", "--ignore=38834", "--ignore=43975"], + ], ) def test_ignore_ok(tmpdir, args): - requirements_file = tmpdir.join('requirements.txt') - requirements_file.write('urllib3==1.24.1') + requirements_file = tmpdir.join("requirements.txt") + requirements_file.write("urllib3==1.24.1") assert safety([str(requirements_file)] + args) == 0 + @pytest.mark.parametrize( "ignore_arg,status", [ @@ -53,16 +69,20 @@ def test_ignore_ok(tmpdir, args): ("--ignore=37055", EXIT_CODE_VULNERABILITIES_FOUND), ("--ignore=37071", EXIT_CODE_VULNERABILITIES_FOUND), ("--ignore=38834", EXIT_CODE_VULNERABILITIES_FOUND), - ] + ], ) def test_varargs_escape(tmpdir, ignore_arg, status): - requirements_file = tmpdir.join('requirements.txt') - requirements_file.write('urllib3==1.24.1') + requirements_file = tmpdir.join("requirements.txt") + requirements_file.write("urllib3==1.24.1") assert safety([ignore_arg, "--", str(requirements_file)]) == status -def test_poetry_requirements(tmpdir): # cf. https://github.com/Lucas-C/pre-commit-hooks-safety/issues/5 - requirements_file = tmpdir.join('requirements.txt') - requirements_file.write('''colored==1.4.2 \ + +def test_poetry_requirements( + tmpdir, +): # cf. https://github.com/Lucas-C/pre-commit-hooks-safety/issues/5 + requirements_file = tmpdir.join("requirements.txt") + requirements_file.write( + """colored==1.4.2 \ --hash=sha256:056fac09d9e39b34296e7618897ed1b8c274f98423770c2980d829fd670955ed colored-traceback==0.3.0 \ --hash=sha256:6da7ce2b1da869f6bb54c927b415b95727c4bb6d9a84c4615ea77d9872911b05 \ @@ -76,49 +96,68 @@ def test_poetry_requirements(tmpdir): # cf. https://github.com/Lucas-C/pre-comm --hash=sha256:98c8aa5a9f778fcd1026a17361ddaf7330d1b7c62ae97c3bb0ae73e0b9b6b0fe six==1.13.0 \ --hash=sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd \ - --hash=sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66''') + --hash=sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66""" + ) assert safety([str(requirements_file)]) == 0 + def test_editable_url_to_tarball_dependency(tmpdir): - requirements_file = tmpdir.join('requirements.txt') - requirements_file.write('-e https://files.pythonhosted.org/packages/6a/11/114c67b0e3c25c19497fde977538339530d8ffa050d6ec9349793f933faa/lockfile-0.10.2.tar.gz') + requirements_file = tmpdir.join("requirements.txt") + requirements_file.write( + '-e https://files.pythonhosted.org/packages/6a/11/" \ + 114c67b0e3c25c19497fde977538339530d8ffa050d6ec9349793f933faa/lockfile-0.10.2.tar.gz' + ) assert safety([str(requirements_file)]) == 0 -@pytest.mark.xfail(reason='cf. https://github.com/Lucas-C/pre-commit-hooks-safety/issues/1') + +@pytest.mark.xfail( + reason="cf. https://github.com/Lucas-C/pre-commit-hooks-safety/issues/1" +) def test_bare_url_to_tarball_dependency(tmpdir): - requirements_file = tmpdir.join('requirements.txt') - requirements_file.write('https://files.pythonhosted.org/packages/6a/11/114c67b0e3c25c19497fde977538339530d8ffa050d6ec9349793f933faa/lockfile-0.10.2.tar.gz') + requirements_file = tmpdir.join("requirements.txt") + requirements_file.write( + "https://files.pythonhosted.org/packages/6a/11/114c67b0e3c25c19497fde977538339530d8ffa050d6ec9349793f933faa/lockfile-0.10.2.tar.gz" + ) assert safety([str(requirements_file)]) == 0 + def test_pyproject_toml_without_deps(tmpdir): - pyproject_file = tmpdir.join('pyproject.toml') - pyproject_file.write("""[tool.poetry] + pyproject_file = tmpdir.join("pyproject.toml") + pyproject_file.write( + """[tool.poetry] name = 'Thing' version = '1.2.3' description = 'Dummy' -authors = ['Lucas Cimon']""") +authors = ['Lucas Cimon']""" + ) assert safety([str(pyproject_file)]) == 0 + def test_pyproject_toml_with_ko_deps(tmpdir): - pyproject_file = tmpdir.join('pyproject.toml') - pyproject_file.write("""[tool.poetry] + pyproject_file = tmpdir.join("pyproject.toml") + pyproject_file.write( + """[tool.poetry] name = 'Thing' version = '1.2.3' description = 'Dummy' authors = ['Lucas Cimon'] [tool.poetry.dependencies] -jsonpickle = '1.4.1'""") +jsonpickle = '1.4.1'""" + ) assert safety([str(pyproject_file)]) == EXIT_CODE_VULNERABILITIES_FOUND + def test_pyproject_toml_with_ko_dev_deps(tmpdir): - pyproject_file = tmpdir.join('pyproject.toml') - pyproject_file.write("""[tool.poetry] + pyproject_file = tmpdir.join("pyproject.toml") + pyproject_file.write( + """[tool.poetry] name = 'Thing' version = '1.2.3' description = 'Dummy' authors = ['Lucas Cimon'] [tool.poetry.dev-dependencies] -jsonpickle = '1.4.1'""") +jsonpickle = '1.4.1'""" + ) assert safety([str(pyproject_file)]) == EXIT_CODE_VULNERABILITIES_FOUND