diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml index 99e246818..9ecfabe4c 100644 --- a/.github/workflows/pre-commit.yaml +++ b/.github/workflows/pre-commit.yaml @@ -38,7 +38,7 @@ jobs: # Skip terraform_tflint which interferes to commit pre-commit auto-fixes - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 with: - python-version: '3.9' + python-version: '3.10' - name: Execute pre-commit uses: pre-commit/action@9b88afc9cd57fd75b655d5c71bd38146d07135fe # v2.0.3 env: diff --git a/.gitignore b/.gitignore index 0bbeada90..350656e80 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,6 @@ tests/results/* + +# Python +__pycache__/ +*.py[cod] +node_modules/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1db1d62b4..979f79e17 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -45,7 +45,7 @@ repos: # Dockerfile linter - repo: https://github.com/hadolint/hadolint - rev: v2.12.1-beta + rev: v2.13.1-beta hooks: - id: hadolint args: [ @@ -66,3 +66,84 @@ repos: - id: prettier # https://prettier.io/docs/en/options.html#parser files: '.json5$' + + +########## +# PYTHON # +########## + +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.8.4 + hooks: + - id: ruff + args: [--fix] + types_or: [python, pyi] + - id: ruff-format + types_or: [python, pyi] + args: [--config, format.quote-style = 'single', --config, line-length = 100] + +- repo: https://github.com/pycqa/isort + rev: 5.13.2 + hooks: + - id: isort + name: isort + args: [--force-single-line, --profile=black] + +- repo: https://github.com/asottile/add-trailing-comma + rev: v3.1.0 + hooks: + - id: add-trailing-comma + +- repo: https://github.com/pre-commit/mirrors-autopep8 + rev: v2.0.4 + hooks: + - id: autopep8 + args: + - -i + - --max-line-length=100 + +# Usage: http://pylint.pycqa.org/en/latest/user_guide/message-control.html +- repo: https://github.com/PyCQA/pylint + rev: v3.3.3 + hooks: + - id: pylint + args: + - --disable=import-error # E0401. Locally you could not have all imports. + - --disable=fixme # W0511. 'TODO' notations. + - --disable=logging-fstring-interpolation # Conflict with "use a single formatting" WPS323 + - --disable=ungrouped-imports # ignore `if TYPE_CHECKING` case. Other do reorder-python-imports + - --disable=R0801 # Similar lines in 2 files. Currently I don't think that it possible to DRY hooks unique files boilerplate + +- repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.14.1 + hooks: + - id: mypy + additional_dependencies: + - types-PyYAML + args: [ + --ignore-missing-imports, + --disallow-untyped-calls, + --warn-redundant-casts, + ] + +- repo: https://github.com/wemake-services/wemake-python-styleguide + rev: 1.0.0 + hooks: + - id: wemake-python-styleguide + args: + - --allowed-module-metadata=__all__ # Default to '' + - --max-local-variables=6 # Default to 5 + - --max-returns=6 # Default to 5 + - --max-imports=15 # Default to 12 + # https://wemake-python-stylegui.de/en/latest/pages/usage/violations/index.html + - --extend-ignore= + E501 + WPS115 + WPS226 + + + exclude: | + (?x) + # Ignore deprecated hook + (^src/pre_commit_terraform/terraform_docs_replace.py$ + ) diff --git a/.vscode/settings.json b/.vscode/settings.json index c1dc51901..caa4801a9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,4 +7,7 @@ "code-block-style": false }, "markdown.validate.enabled": true, + "python.analysis.extraPaths": [ + "./src" + ], } diff --git a/pyproject.toml b/pyproject.toml index e5ff0159a..bbf3ac095 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,15 +9,12 @@ build-backend = 'hatchling.build' name = 'pre-commit-terraform' classifiers = [ 'License :: OSI Approved :: MIT License', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3 :: Only', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', ] -description = 'Pre-commit hooks for terraform_docs_replace' +description = 'Pre-commit hooks for Terraform' dependencies = [] dynamic = [ 'urls', diff --git a/src/pre_commit_terraform/__main__.py b/src/pre_commit_terraform/__main__.py index 18a63dfd0..34ebfdbc0 100644 --- a/src/pre_commit_terraform/__main__.py +++ b/src/pre_commit_terraform/__main__.py @@ -1,9 +1,9 @@ """A runpy-style CLI entry-point module.""" -from sys import argv, exit as exit_with_return_code +from sys import argv +from sys import exit as exit_with_return_code from ._cli import invoke_cli_app - return_code = invoke_cli_app(argv[1:]) exit_with_return_code(return_code) diff --git a/src/pre_commit_terraform/_cli.py b/src/pre_commit_terraform/_cli.py index f52a50b0b..7cbcf129d 100644 --- a/src/pre_commit_terraform/_cli.py +++ b/src/pre_commit_terraform/_cli.py @@ -3,11 +3,9 @@ from sys import stderr from ._cli_parsing import initialize_argument_parser -from ._errors import ( - PreCommitTerraformBaseError, - PreCommitTerraformExit, - PreCommitTerraformRuntimeError, -) +from ._errors import PreCommitTerraformBaseError +from ._errors import PreCommitTerraformExit +from ._errors import PreCommitTerraformRuntimeError from ._structs import ReturnCode from ._types import ReturnCodeType @@ -28,8 +26,7 @@ def invoke_cli_app(cli_args: list[str]) -> ReturnCodeType: raise except PreCommitTerraformRuntimeError as unhandled_exc: print( - f'App execution took an unexpected turn: {unhandled_exc !s}. ' - 'Exiting...', + f'App execution took an unexpected turn: {unhandled_exc !s}. Exiting...', file=stderr, ) return ReturnCode.ERROR diff --git a/src/pre_commit_terraform/_cli_subcommands.py b/src/pre_commit_terraform/_cli_subcommands.py index fc268e552..2923ea927 100644 --- a/src/pre_commit_terraform/_cli_subcommands.py +++ b/src/pre_commit_terraform/_cli_subcommands.py @@ -3,7 +3,6 @@ from . import terraform_docs_replace from ._types import CLISubcommandModuleProtocol - SUBCOMMAND_MODULES: list[CLISubcommandModuleProtocol] = [ terraform_docs_replace, ] diff --git a/src/pre_commit_terraform/_errors.py b/src/pre_commit_terraform/_errors.py index c0f973acc..7bdb738da 100644 --- a/src/pre_commit_terraform/_errors.py +++ b/src/pre_commit_terraform/_errors.py @@ -6,8 +6,8 @@ class PreCommitTerraformBaseError(Exception): class PreCommitTerraformRuntimeError( - PreCommitTerraformBaseError, - RuntimeError, + PreCommitTerraformBaseError, + RuntimeError, ): """An exception representing a runtime error condition.""" diff --git a/src/pre_commit_terraform/_types.py b/src/pre_commit_terraform/_types.py index 99402b447..f2eadb626 100644 --- a/src/pre_commit_terraform/_types.py +++ b/src/pre_commit_terraform/_types.py @@ -1,11 +1,12 @@ """Composite types for annotating in-project code.""" -from argparse import ArgumentParser, Namespace -from typing import Final, Protocol +from argparse import ArgumentParser +from argparse import Namespace +from typing import Final +from typing import Protocol from ._structs import ReturnCode - ReturnCodeType = ReturnCode | int @@ -16,12 +17,14 @@ class CLISubcommandModuleProtocol(Protocol): """This constant contains a CLI.""" def populate_argument_parser( - self, subcommand_parser: ArgumentParser, + self, + subcommand_parser: ArgumentParser, ) -> None: """Run a module hook for populating the subcommand parser.""" def invoke_cli_app( - self, parsed_cli_args: Namespace, + self, + parsed_cli_args: Namespace, ) -> ReturnCodeType | int: """Run a module hook implementing the subcommand logic.""" ... # pylint: disable=unnecessary-ellipsis diff --git a/src/pre_commit_terraform/terraform_docs_replace.py b/src/pre_commit_terraform/terraform_docs_replace.py index b79ba479e..799663936 100644 --- a/src/pre_commit_terraform/terraform_docs_replace.py +++ b/src/pre_commit_terraform/terraform_docs_replace.py @@ -1,13 +1,13 @@ import os import subprocess import warnings -from argparse import ArgumentParser, Namespace +from argparse import ArgumentParser +from argparse import Namespace from typing import Final from ._structs import ReturnCode from ._types import ReturnCodeType - CLI_SUBCOMMAND_NAME: Final[str] = 'replace-docs' @@ -18,14 +18,20 @@ def populate_argument_parser(subcommand_parser: ArgumentParser) -> None: 'replace the entire README.md file each time.' ) subcommand_parser.add_argument( - '--dest', dest='dest', default='README.md', + '--dest', + dest='dest', + default='README.md', ) subcommand_parser.add_argument( - '--sort-inputs-by-required', dest='sort', action='store_true', + '--sort-inputs-by-required', + dest='sort', + action='store_true', help='[deprecated] use --sort-by-required instead', ) subcommand_parser.add_argument( - '--sort-by-required', dest='sort', action='store_true', + '--sort-by-required', + dest='sort', + action='store_true', ) subcommand_parser.add_argument( '--with-aggregate-type-defaults', @@ -51,8 +57,9 @@ def invoke_cli_app(parsed_cli_args: Namespace) -> ReturnCodeType: dirs = [] for filename in parsed_cli_args.filenames: - if (os.path.realpath(filename) not in dirs and - (filename.endswith(".tf") or filename.endswith(".tfvars"))): + if os.path.realpath(filename) not in dirs and ( + filename.endswith('.tf') or filename.endswith('.tfvars') + ): dirs.append(os.path.dirname(filename)) retval = ReturnCode.OK @@ -64,13 +71,12 @@ def invoke_cli_app(parsed_cli_args: Namespace) -> ReturnCodeType: if parsed_cli_args.sort: procArgs.append('--sort-by-required') procArgs.append('md') - procArgs.append("./{dir}".format(dir=dir)) + procArgs.append('./{dir}'.format(dir=dir)) procArgs.append('>') procArgs.append( - './{dir}/{dest}'. - format(dir=dir, dest=parsed_cli_args.dest), + './{dir}/{dest}'.format(dir=dir, dest=parsed_cli_args.dest), ) - subprocess.check_call(" ".join(procArgs), shell=True) + subprocess.check_call(' '.join(procArgs), shell=True) except subprocess.CalledProcessError as e: print(e) retval = ReturnCode.ERROR