diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..7e2c020e2 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +poetry.lock linguist-generated=true \ No newline at end of file diff --git a/.import_linter_config b/.import_linter_config new file mode 100644 index 000000000..6afea97c5 --- /dev/null +++ b/.import_linter_config @@ -0,0 +1,2 @@ +[importlinter] +root_package = exasol.toolbox diff --git a/doc/changes/unreleased.md b/doc/changes/unreleased.md index ba9fbab9b..24c21d053 100644 --- a/doc/changes/unreleased.md +++ b/doc/changes/unreleased.md @@ -5,6 +5,7 @@ * Fixed the issue with publishing new documentation after releasing a new version ## ✨ Added +* #149: Added nox task to lint imports * Added support to manually trigger documentation build * #248: Added security results to workflow summary * #233: Added nox task to verify dependency declarations diff --git a/doc/developer_guide/modules/modules.rst b/doc/developer_guide/modules/modules.rst index ac317dde0..e24157259 100644 --- a/doc/developer_guide/modules/modules.rst +++ b/doc/developer_guide/modules/modules.rst @@ -6,5 +6,6 @@ Modules sphinx/sphinx nox + nox_tasks pre_commit_hooks diff --git a/doc/developer_guide/modules/nox.rst b/doc/developer_guide/modules/nox.rst index 5818aeecc..20966422c 100644 --- a/doc/developer_guide/modules/nox.rst +++ b/doc/developer_guide/modules/nox.rst @@ -1,5 +1,6 @@ nox === + The nox package contains nox related functionalities like pre defined nox tasks. .. figure:: ../../_static/nothing-to-see-here.png diff --git a/doc/developer_guide/modules/nox_tasks.rst b/doc/developer_guide/modules/nox_tasks.rst new file mode 100644 index 000000000..77fe9794b --- /dev/null +++ b/doc/developer_guide/modules/nox_tasks.rst @@ -0,0 +1,15 @@ +nox_tasks +========= + +lint:import (experimental) +__________________________ + +`Import Linter `_ +allows you to define and enforce rules for the imports within and between Python packages. + +.. important:: + + First configure the linter in file :code:`.import_linter_config`, see + `import-linter top-level-configuration `_ + and `import-linter contract types `_ + diff --git a/doc/developer_guide/modules/pre_commit_hooks.rst b/doc/developer_guide/modules/pre_commit_hooks.rst index 00d24a845..7807655d0 100644 --- a/doc/developer_guide/modules/pre_commit_hooks.rst +++ b/doc/developer_guide/modules/pre_commit_hooks.rst @@ -1,5 +1,6 @@ pre_commit_hooks ================= + In the pre_commit_hook package contains git commit hooks and similar functionalities. .. figure:: ../../_static/nothing-to-see-here.png diff --git a/exasol/toolbox/nox/_lint.py b/exasol/toolbox/nox/_lint.py index 5ca637448..d189cccb9 100644 --- a/exasol/toolbox/nox/_lint.py +++ b/exasol/toolbox/nox/_lint.py @@ -1,22 +1,22 @@ from __future__ import annotations +import argparse +import sys +from pathlib import Path from typing import ( + Dict, Iterable, List, - Dict ) import nox +import rich.console +import tomlkit from nox import Session from exasol.toolbox.nox._shared import python_files from noxconfig import PROJECT_CONFIG -from pathlib import Path -import rich.console -import tomlkit -import sys - def _pylint(session: Session, files: Iterable[str]) -> None: session.run( @@ -74,27 +74,28 @@ def _security_lint(session: Session, files: Iterable[str]) -> None: ) +def _import_lint(session: Session, path: Path) -> None: + session.run("poetry", "run", "lint-imports", "--config", path) + + class Dependencies: - def __init__(self, illegal: Dict[str, List[str]] | None): + def __init__(self, illegal: dict[str, list[str]] | None): self._illegal = illegal or {} @staticmethod - def parse(pyproject_toml: str) -> "Dependencies": + def parse(pyproject_toml: str) -> Dependencies: def _source_filter(version) -> bool: - ILLEGAL_SPECIFIERS = ['url', 'git', 'path'] - return any( - specifier in version - for specifier in ILLEGAL_SPECIFIERS - ) + ILLEGAL_SPECIFIERS = ["url", "git", "path"] + return any(specifier in version for specifier in ILLEGAL_SPECIFIERS) - def find_illegal(part) -> List[str]: + def find_illegal(part) -> list[str]: return [ f"{name} = {version}" for name, version in part.items() if _source_filter(version) ] - illegal: Dict[str, List[str]] = {} + illegal: dict[str, list[str]] = {} toml = tomlkit.loads(pyproject_toml) poetry = toml.get("tool", {}).get("poetry", {}) @@ -114,11 +115,11 @@ def find_illegal(part) -> List[str]: return Dependencies(illegal) @property - def illegal(self) -> Dict[str, List[str]]: + def illegal(self) -> dict[str, list[str]]: return self._illegal -def report_illegal(illegal: Dict[str, List[str]], console: rich.console.Console): +def report_illegal(illegal: dict[str, list[str]], console: rich.console.Console): count = sum(len(deps) for deps in illegal.values()) suffix = "y" if count == 1 else "ies" console.print(f"{count} illegal dependenc{suffix}\n", style="red") @@ -158,4 +159,35 @@ def dependency_check(session: Session) -> None: console = rich.console.Console() if illegal := dependencies.illegal: report_illegal(illegal, console) - sys.exit(1) \ No newline at end of file + sys.exit(1) + + +@nox.session(name="lint:import", python=False) +def import_lint(session: Session) -> None: + """(experimental) Runs import linter on the project""" + parser = argparse.ArgumentParser( + usage="nox -s import-lint -- [options]", + description="Runs the import linter on the project", + ) + parser.add_argument( + "-c", + "--config", + type=str, + help="path to the configuration file for the importlinter", + metavar="TEXT", + ) + + args: argparse.Namespace = parser.parse_args(args=session.posargs) + file: str = args.config + path: Path | None = None + if file is None: + path = getattr( + PROJECT_CONFIG, "import_linter_config", Path(".import_linter_config") + ) + else: + path = Path(file) + if not path.exists(): + session.error( + "Please make sure you have a configuration file for the importlinter" + ) + _import_lint(session=session, path=path) diff --git a/exasol/toolbox/tools/security.py b/exasol/toolbox/tools/security.py index 1af8e88c0..23ae38f9a 100644 --- a/exasol/toolbox/tools/security.py +++ b/exasol/toolbox/tools/security.py @@ -11,13 +11,14 @@ from enum import Enum from functools import partial from inspect import cleandoc +from pathlib import Path from typing import ( Generator, Iterable, Tuple, ) + import typer -from pathlib import Path stdout = print stderr = partial(print, file=sys.stderr) @@ -128,14 +129,16 @@ def from_json(report_str: str, prefix: Path) -> Iterable[SecurityIssue]: cwe=str(issue["issue_cwe"].get("id", "")), test_id=issue["test_id"], description=issue["issue_text"], - references=tuple(references) + references=tuple(references), ) def issues_to_markdown(issues: Iterable[SecurityIssue]) -> str: - template = cleandoc(""" + template = cleandoc( + """ {header}{rows} - """) + """ + ) def _header(): header = "# Security\n\n" @@ -153,10 +156,7 @@ def _row(issue): row = row[:-5] + "|" return row - return template.format( - header=_header(), - rows="\n".join(_row(i) for i in issues) - ) + return template.format(header=_header(), rows="\n".join(_row(i) for i in issues)) def security_issue_title(issue: Issue) -> str: @@ -217,6 +217,7 @@ def create_security_issue(issue: Issue, project="") -> Tuple[str, str]: CVE_CLI = typer.Typer() CLI.add_typer(CVE_CLI, name="cve", help="Work with CVE's") + class Format(str, Enum): Maven = "maven" @@ -320,8 +321,10 @@ class PPrintFormats(str, Enum): @CLI.command(name="pretty-print") def json_issue_to_markdown( - json_file: typer.FileText = typer.Argument(mode="r", help="json file with issues to convert"), - path: Path = typer.Argument(default=Path("."), help="path to project root") + json_file: typer.FileText = typer.Argument( + mode="r", help="json file with issues to convert" + ), + path: Path = typer.Argument(default=Path("."), help="path to project root"), ) -> None: content = json_file.read() issues = from_json(content, path.absolute()) diff --git a/noxconfig.py b/noxconfig.py index 0e94bf0e2..ad20121d1 100644 --- a/noxconfig.py +++ b/noxconfig.py @@ -35,6 +35,7 @@ class Config: root: Path = Path(__file__).parent doc: Path = Path(__file__).parent / "doc" + importlinter: Path = Path(__file__).parent / ".import_linter_config" version_file: Path = Path(__file__).parent / "exasol" / "toolbox" / "version.py" path_filters: Iterable[str] = ( "dist", diff --git a/poetry.lock b/poetry.lock index 755b5dbd5..6c5ab51ad 100644 --- a/poetry.lock +++ b/poetry.lock @@ -526,6 +526,109 @@ pygments = ">=2.7" sphinx = ">=6.0,<9.0" sphinx-basic-ng = ">=1.0.0.beta2" +[[package]] +name = "grimp" +version = "3.5" +description = "Builds a queryable graph of the imports within one or more Python packages." +optional = false +python-versions = ">=3.9" +files = [ + {file = "grimp-3.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:73538d288752ea7b10fdfd05406a1c1507531b5763ad97994cd1646283112d93"}, + {file = "grimp-3.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8c2f4a16626b6de9f5ea6e87e685e5810be7712461ef29260c67b5b868f64ae5"}, + {file = "grimp-3.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5d495c9d527535872d78dfbc0f74f2650ad6b13e12f7d8b11da9d91ebaf2bda"}, + {file = "grimp-3.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b2ea1402221bf00dee7ae5357ef549151b1ad213a892cfe734b7156413d99a38"}, + {file = "grimp-3.5-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a71a6c4e411adfeb6b8ba0fc5eff60505bf758aea9e4c7169a6fce5a57833cf"}, + {file = "grimp-3.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60e92da02c72eebb9f1aaecd48c3b9fd234de6a6427da6b2232918cb88b409c0"}, + {file = "grimp-3.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5f9db004a253329f480a3ec0b0929558a6427f2db0610900b57fded591f6e3be"}, + {file = "grimp-3.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7fa6188b077339f030973b6cb3e1947175c45f6f9a472162435a5f80afd21805"}, + {file = "grimp-3.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3140ec48aaa43e124a735878fdf527cad7fa65230c2b69abc8124a22afb755bc"}, + {file = "grimp-3.5-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:7e6f9af573b59bb0dd07e182482277922889329672cb418a0e8617de3aaf4922"}, + {file = "grimp-3.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:374ad436ffdd29ffd6ae4b2a345783aad08f0d674b1ee01b55b824420b6f8e85"}, + {file = "grimp-3.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b10e7d4f67bae4326275b63aa1987652f6d673264fd8e2eb6804d64e0bfc4fa2"}, + {file = "grimp-3.5-cp310-none-win32.whl", hash = "sha256:077a0e5fe97a95183e9302615dd10b69f4b378efb9158504a57b7e71871259a3"}, + {file = "grimp-3.5-cp310-none-win_amd64.whl", hash = "sha256:80a04c1559bfe45a8cb49caf160391e180cf24db9af443f34ed01e5ededba025"}, + {file = "grimp-3.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3d2130cbdbcd01ae65ebe39520f8a38e5f4ed445a4989eb1c8c0796759ddc5c6"}, + {file = "grimp-3.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b2f9fdafc36dcf3ae80f7da2696bc7cbd1ef73ddd0f043446d63facc474cb2ab"}, + {file = "grimp-3.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2320207ad620ed383533f3178783b5d82a9f100dbc9d7fc1c50e40275dc9a002"}, + {file = "grimp-3.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:24b83512a3195c4f927e3968b0c61db9c6d5758f748bf6d3fec197f0b61309e8"}, + {file = "grimp-3.5-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e6abffdfe3b70723fe6a61f3c3e2c5c415a18d06387929bf4b223aa050c618d3"}, + {file = "grimp-3.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ba4988e1c96415d02f49b4677e1a219c048c2cbb358c812c99b303310f4adaa"}, + {file = "grimp-3.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d3d11d7ed0b0313cb378a5d138f4644189ffc77fb358d60d21d54c3d32f0a5a5"}, + {file = "grimp-3.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b175fb636e7d2d1e6feb79ad09794740b03458eb838c341e51112beee8ae5f6e"}, + {file = "grimp-3.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a93990401856d4ba7620faa123d1949059b2b5c169b6ef1bdf4d1f8df316c0a1"}, + {file = "grimp-3.5-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f8676bc2e0ecdc61376aba038b8ebd3380630a78f1c44426b393dd616eb3899b"}, + {file = "grimp-3.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e270c5342302aabf97ad4e810101fcfc38c5f9360cbdd5b6f653ce43f29bf1bf"}, + {file = "grimp-3.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e6682704bd7c3a2f9098747b524038f15df4d1456aded3265596fb2360fca872"}, + {file = "grimp-3.5-cp311-none-win32.whl", hash = "sha256:7aa32379f91494d1f1779a3e469ebf5d3e515c8c978bb5d585f6a87c297f45a1"}, + {file = "grimp-3.5-cp311-none-win_amd64.whl", hash = "sha256:bbcd2468a2609a8c662429ed34357ff50efb194c00c1c88a6336c92d662439ad"}, + {file = "grimp-3.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:e09db10a7395b3930ebe95eee2ac440c5ee24ce77b6171e807a8aacb4625cca2"}, + {file = "grimp-3.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:977c6b220671d7332657be13c51e4f6f38c76d911680f844806a5346142910fc"}, + {file = "grimp-3.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f4e2159c3c75b62f9ea59a539ac93f89b9ced38811b453d3b78be62c8395b01"}, + {file = "grimp-3.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8d7bb3f2178b3a8115eca5f6ea5f766a283b8a7ede84fbbdda2a40b7d28624cb"}, + {file = "grimp-3.5-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e023c883a83fa8ca1a613b1e8b39834545818971a8d94977bcd4b491537cde"}, + {file = "grimp-3.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce7440c8498fa5b47acfffce7fe42d6c63be94dbe2fff7f524522fa7e422e0eb"}, + {file = "grimp-3.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0724f60d7cccf2c94616f0282ba8eec85a1956b59b8d22274409a60539fc462"}, + {file = "grimp-3.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a486e985fa4d4fb9dc6ebb094ed17a293809ff5cf6532bba26a5ae064d350539"}, + {file = "grimp-3.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8a98f06d58b0cb7b8bfe5846d8ab07adb36c313dd3c7298836ddd3df98a8344a"}, + {file = "grimp-3.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:13924943d6e5a0f0150c8f2a05d87042f03510b633b198ac3dd5c4274d36f28c"}, + {file = "grimp-3.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8194ac4c54fac7641bfcef332aaec1af590e97b2aa8993e47a7c51ff84220f44"}, + {file = "grimp-3.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3f83b85aad278dfcaf2bf27b9cfa6dd6533dd96ecc510ba3bc0141344686857f"}, + {file = "grimp-3.5-cp312-none-win32.whl", hash = "sha256:f88307f0e50883ab73cc59164a5a9396e8e1c8b68b8e2edef68d478b91d81000"}, + {file = "grimp-3.5-cp312-none-win_amd64.whl", hash = "sha256:6fa422c150597f8e6ad51c4fe2b271747057abe638acca5eebb2162e536065ed"}, + {file = "grimp-3.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:448dba63f938d0e13e6121559749816e3b2644202c912cc308e7608c6034737a"}, + {file = "grimp-3.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:17113aba41269d0ee91512c96eeb850c7c668440c6a8e0bfc94d17762184b293"}, + {file = "grimp-3.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6a55614945c319d1dc692c3e43f3a02b80c116a1298e593f5f887b97e6c983a"}, + {file = "grimp-3.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aba7ce7839b72efb4c6d06404d2b2a3026e28dd89816f4e546b3cd6626cbeeb1"}, + {file = "grimp-3.5-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eaedfba320a70d87b14acb25a685c8629586b943129c71ffd02b47d9531c11ce"}, + {file = "grimp-3.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60a9afd3dd00ad1d301a07f97e26bc9ecdc3d2db39ab6ac46c315a7dea0a96cb"}, + {file = "grimp-3.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:11c66039c0475e5c9fc6a086264f11870181ae79f603caa5dffa1411ddad636b"}, + {file = "grimp-3.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bff39a0061790f074f86a7841cd8e6064aa7b2208cb1ee5c3f2e685dead2b66e"}, + {file = "grimp-3.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cf7f5367c4a87b8e9f08c09e7401d2d73f21cb65d6142445819f9df0d6ab3f6b"}, + {file = "grimp-3.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:edee4b087f007dab8b65461caf6a1b67b2f9480cceb5f6aceea87008d8f283c4"}, + {file = "grimp-3.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6af125013ad2a56c18f2f53a3fcabbfbe96c70374abecd6f14b82dc444726ebe"}, + {file = "grimp-3.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:24aabae0183ca5fd5a710257ff37120b55d8e6d6d4cbb2c08481552832e5c901"}, + {file = "grimp-3.5-cp313-none-win32.whl", hash = "sha256:506091bfd600dd7ad427586998ef5e54a2098485148a1499bd9af5943d2fb0b7"}, + {file = "grimp-3.5-cp313-none-win_amd64.whl", hash = "sha256:099388df82d922ddc589f362f1a523ab053c8dee5d29a6b622b2cddf481c6a2f"}, + {file = "grimp-3.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:4bec3fbe008c8f8c546a640e6e74a519c9d33720c315c72013f1b6455543d1a9"}, + {file = "grimp-3.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea11cf5a0e1cd8fb1a119304128c85162bb2e4ad49c7583ab7835c783fc45457"}, + {file = "grimp-3.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a63b444410c78763b506c9f31cd813b5c3ff3ed14100d102f1a705201f70f2f"}, + {file = "grimp-3.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fffb6e7b066636e69f1b70ed617891d04efc14c8d740015026c6c01ede03196f"}, + {file = "grimp-3.5-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:057a4afece42540d51817f8acca889bde87d78720ff7bf51833b27a83ea0a74b"}, + {file = "grimp-3.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e7a59650956cd1e29810a5611395560c33a27cf3acddd587437745c8b136a820"}, + {file = "grimp-3.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57d35306da73b62d3d29fc482e8add9e6781fc004ca080c1b74b0d21d62e1613"}, + {file = "grimp-3.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb3a24b5f4c1b19a19712855dbb82a7d82d8dc565e99464c3fb15fefd5ae81ae"}, + {file = "grimp-3.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:bb3adae6cc3938aa487fc206c4a44af026907ec98322c738e5f2f3435e34e7cd"}, + {file = "grimp-3.5-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:b14b00f15bf1e5901ec50fad0b4238522aef7b37b0cce770c100e387e278cd6e"}, + {file = "grimp-3.5-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:40c6473a12ac8f71f66d3215269011fd8e480b99947f1dbb12e1d83b3fc3df74"}, + {file = "grimp-3.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2967cef66f123f9c90281ad2525995302dea3d52416e5177b3eb9cd7eea0f617"}, + {file = "grimp-3.5-cp39-none-win32.whl", hash = "sha256:d1aeb5ffb188d10a28a4508cc33e5f06f03a032c484a8b2d5bd0a2fad115d3c2"}, + {file = "grimp-3.5-cp39-none-win_amd64.whl", hash = "sha256:98d6be78ffabc28016d313847ff990f2625b6d2c7015edd34f0bad4be97bb648"}, + {file = "grimp-3.5-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:952c0ea0c652c3aea99411921e1a43b015c4ef96466a8b0d78b8d15c820228ca"}, + {file = "grimp-3.5-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:33da59560da889ad41018f0c93f58833018922a1fff7ae44bcf20a0644bda9fc"}, + {file = "grimp-3.5-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f8ee28ff91df8e6c8ce2ea4334bb487ebd7adeef94f6d0170314cb3e0179e272"}, + {file = "grimp-3.5-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4dca05a5beb2346630968127612ebd7771084890297d4de25cde24ac937dc11b"}, + {file = "grimp-3.5-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bb6feb9667349fba87d85d210a85480e43dc96a65b6229baf3a0439ebf44613f"}, + {file = "grimp-3.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b35460a314a720d1a332222621dc9a8b412d9c56bc19866019d6c6451cc09dc"}, + {file = "grimp-3.5-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:03350ec0378d984d6d8ff09fa607ecdeca59d8ee4636a029f1a7475e8a9cd74a"}, + {file = "grimp-3.5-pp310-pypy310_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:d9ef6c6c8d1d64eabb555a7ecf4ec3dce91d0ade54b3724a03169a298a65f2f7"}, + {file = "grimp-3.5-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:813ec51de74800043c543ab2979dd7b383aeb6b5cd52adf092ef7fa69c6c2b2f"}, + {file = "grimp-3.5-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:1966b0059b38b5aeca9da3fb3c036590d783d7330eb9e1300b2779f7e6d41650"}, + {file = "grimp-3.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca26b2e1acd3ecfba14a9987dc2cf81b44cd05be755e7a112e05ae8c54626548"}, + {file = "grimp-3.5-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d2257a4abfe40578e546e2f74b698b58645aeb3137fd7c3c95ac49a84ebe3009"}, + {file = "grimp-3.5-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c07bab1917ae798381a63f065e804fb1b5797bb727bb17671453bb6c02639944"}, + {file = "grimp-3.5-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:74b035af58fa6171f07972bac3cb970ac409c10c222515c913b468c7e067f23a"}, + {file = "grimp-3.5-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ba0066ab7d081c1637947a82c744081654150e9dcb6967ae9bdad3a69a55224c"}, + {file = "grimp-3.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6e6f7d75e9f32022b57ca9d83239a0325a495cb6dc3ddb629654aa3d30f0a88"}, + {file = "grimp-3.5-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:697ec33b8ed0803b5c7ca68d297d90cfc36940b2a4fc64651bf29953f126ada3"}, + {file = "grimp-3.5-pp39-pypy39_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:1f3b3a8f309c9a9026324745f744ffc60cd54d1a07bc1ddbb1ba73e7bacb2a78"}, + {file = "grimp-3.5-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:320bcca184841f7935df8c50636607e452ebea1891e9985a6fe9b82b96a3cd6c"}, + {file = "grimp-3.5-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ed910d51b1105799882beb3936d5dcb7617ae17494864bbef01617e52c9866f4"}, + {file = "grimp-3.5.tar.gz", hash = "sha256:dc9560aed1d82222b361fe5f312a775b15a96b9237670f3a9fb20f44d30d5762"}, +] + +[package.dependencies] +typing-extensions = ">=3.10.0.0" + [[package]] name = "identify" version = "2.6.2" @@ -565,6 +668,23 @@ files = [ {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, ] +[[package]] +name = "import-linter" +version = "2.1" +description = "Enforces rules for the imports within and between Python packages." +optional = false +python-versions = ">=3.9" +files = [ + {file = "import_linter-2.1-py3-none-any.whl", hash = "sha256:324d65035f0252a8e432f60256b0d0d32d8d5d6e4f8fd29716688b09d7a2217a"}, + {file = "import_linter-2.1.tar.gz", hash = "sha256:393fadb2e91304c22c5ceab575213ed2b6a794abc7bd05ab345f2430930b2eae"}, +] + +[package.dependencies] +click = ">=6" +grimp = ">=3.2" +tomli = {version = ">=1.2.1", markers = "python_version < \"3.11\""} +typing-extensions = ">=3.10.0.0" + [[package]] name = "importlib-metadata" version = "8.5.0" @@ -1794,4 +1914,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "c36b26bba43eec74c211889dd6b7e86371d89cea60268094105b3d11a093d4d7" +content-hash = "c17078dab11190733cc350a2ceac6ae3db81a209ee01b4d326abbe032abfef62" diff --git a/pyproject.toml b/pyproject.toml index 523c6221b..2b3761642 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,6 +38,7 @@ black = ">=24.1.0" coverage = ">=6.4.4,<8.0.0" furo = ">=2022.9.15" importlib-resources = ">=5.12.0" +import-linter = "^2.0" isort = "^5.12.0" mypy = ">=0.971" myst-parser = ">=2.0.0,<4" diff --git a/test/unit/dependencies_check_test.py b/test/unit/dependencies_check_test.py index 030e66cc9..4c4218ba8 100644 --- a/test/unit/dependencies_check_test.py +++ b/test/unit/dependencies_check_test.py @@ -1,7 +1,10 @@ import pytest import rich.console -from exasol.toolbox.nox._lint import Dependencies, report_illegal +from exasol.toolbox.nox._lint import ( + Dependencies, + report_illegal, +) @pytest.mark.parametrize( @@ -10,7 +13,7 @@ ( """ """, - {} + {}, ), ( """ @@ -31,11 +34,19 @@ example-path1 = {path = "../my-package/dist/my-package-0.1.0.tar.gz"} """, { - "tool.poetry.dependencies": ["example-url1 = {'url': 'https://example.com/my-package-0.1.0.tar.gz'}"], - "tool.poetry.dev.dependencies": ["example-url2 = {'url': 'https://example.com/my-package-0.2.0.tar.gz'}"], - "tool.poetry.group.test.dependencies": ["example-git = {'git': 'git@github.com:requests/requests.git'}"], - "tool.poetry.group.dev.dependencies": ["example-path1 = {'path': '../my-package/dist/my-package-0.1.0.tar.gz'}"], - } + "tool.poetry.dependencies": [ + "example-url1 = {'url': 'https://example.com/my-package-0.1.0.tar.gz'}" + ], + "tool.poetry.dev.dependencies": [ + "example-url2 = {'url': 'https://example.com/my-package-0.2.0.tar.gz'}" + ], + "tool.poetry.group.test.dependencies": [ + "example-git = {'git': 'git@github.com:requests/requests.git'}" + ], + "tool.poetry.group.dev.dependencies": [ + "example-path1 = {'path': '../my-package/dist/my-package-0.1.0.tar.gz'}" + ], + }, ), ( """ @@ -52,10 +63,16 @@ example-path1 = {path = "../my-package/dist/my-package-0.1.0.tar.gz"} """, { - "tool.poetry.dev.dependencies": ["example-url2 = {'url': 'https://example.com/my-package-0.2.0.tar.gz'}"], - "tool.poetry.group.test.dependencies": ["example-git = {'git': 'git@github.com:requests/requests.git'}"], - "tool.poetry.group.dev.dependencies": ["example-path1 = {'path': '../my-package/dist/my-package-0.1.0.tar.gz'}"], - } + "tool.poetry.dev.dependencies": [ + "example-url2 = {'url': 'https://example.com/my-package-0.2.0.tar.gz'}" + ], + "tool.poetry.group.test.dependencies": [ + "example-git = {'git': 'git@github.com:requests/requests.git'}" + ], + "tool.poetry.group.dev.dependencies": [ + "example-path1 = {'path': '../my-package/dist/my-package-0.1.0.tar.gz'}" + ], + }, ), ( """ @@ -72,10 +89,16 @@ example-path1 = {path = "../my-package/dist/my-package-0.1.0.tar.gz"} """, { - "tool.poetry.dependencies": ["example-url1 = {'url': 'https://example.com/my-package-0.1.0.tar.gz'}"], - "tool.poetry.group.test.dependencies": ["example-git = {'git': 'git@github.com:requests/requests.git'}"], - "tool.poetry.group.dev.dependencies": ["example-path1 = {'path': '../my-package/dist/my-package-0.1.0.tar.gz'}"], - } + "tool.poetry.dependencies": [ + "example-url1 = {'url': 'https://example.com/my-package-0.1.0.tar.gz'}" + ], + "tool.poetry.group.test.dependencies": [ + "example-git = {'git': 'git@github.com:requests/requests.git'}" + ], + "tool.poetry.group.dev.dependencies": [ + "example-path1 = {'path': '../my-package/dist/my-package-0.1.0.tar.gz'}" + ], + }, ), ( """ @@ -88,11 +111,15 @@ example-url2 = {url = "https://example.com/my-package-0.2.0.tar.gz"} """, { - "tool.poetry.dependencies": ["example-url1 = {'url': 'https://example.com/my-package-0.1.0.tar.gz'}"], - "tool.poetry.dev.dependencies": ["example-url2 = {'url': 'https://example.com/my-package-0.2.0.tar.gz'}"], - } - ) - ] + "tool.poetry.dependencies": [ + "example-url1 = {'url': 'https://example.com/my-package-0.1.0.tar.gz'}" + ], + "tool.poetry.dev.dependencies": [ + "example-url2 = {'url': 'https://example.com/my-package-0.2.0.tar.gz'}" + ], + }, + ), + ], ) def test_dependency_check_parse(toml, expected): dependencies = dependencies = Dependencies.parse(toml) @@ -136,9 +163,9 @@ def test_dependency_check_parse(toml, expected): example-path1 = {'path': '../my-package/dist/my-package-0.1.0.tar.gz'} example-path2 = {'path': '../my-package/dist/my-package-0.2.0.tar.gz'} -""" +""", ), - ] + ], ) def test_dependencies_check_report(toml, expected, capsys): console = rich.console.Console() diff --git a/test/unit/security_test.py b/test/unit/security_test.py index c58f98715..42b26d1a4 100644 --- a/test/unit/security_test.py +++ b/test/unit/security_test.py @@ -410,7 +410,7 @@ def test_format_jsonl_removes_newline(): "json_file,expected", [ ( - '''{ + """{ "results": [ { "code": "1 import subprocess\\n2 from typing import Iterable\\n3 \\n", @@ -434,7 +434,7 @@ def test_format_jsonl_removes_newline(): } ] } - ''', + """, { "file_name": "exasol/toolbox/git.py", "line": 53, @@ -444,11 +444,11 @@ def test_format_jsonl_removes_newline(): "description": "Consider possible security implications associated with the subprocess module.", "references": ( "https://bandit.readthedocs.io/en/1.7.10/blacklists/blacklist_imports.html#b404-import-subprocess", - "https://cwe.mitre.org/data/definitions/78.html" - ) - } + "https://cwe.mitre.org/data/definitions/78.html", + ), + }, ) - ] + ], ) def test_from_json(json_file, expected): actual = security.from_json(json_file, pathlib.Path("/home/test/python-toolbox")) @@ -459,6 +459,6 @@ def test_from_json(json_file, expected): cwe=expected["cwe"], test_id=expected["test_id"], description=expected["description"], - references=expected["references"] + references=expected["references"], ) assert list(actual) == [expected_issue]