Skip to content

Commit

Permalink
Enable ruff, black, mypy and pylint (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
ssbarnea authored Aug 7, 2024
1 parent 4f9eaa8 commit 8ce04c6
Show file tree
Hide file tree
Showing 11 changed files with 331 additions and 33 deletions.
4 changes: 4 additions & 0 deletions .config/requirements-test.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
coverage-enable-subprocess # see https://github.com/nedbat/coveragepy/issues/1341#issuecomment-1228942657
coverage[toml] >= 6.4.4
pytest >= 7.2.2
pytest-xdist >= 2.1.0
1 change: 1 addition & 0 deletions .config/requirements.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
actions-toolkit
2 changes: 1 addition & 1 deletion .github/workflows/self-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:

jobs:
self-test:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Self test
Expand Down
21 changes: 13 additions & 8 deletions .github/workflows/tox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,39 @@ env:
jobs:
pre:
name: pre
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
outputs:
matrix: ${{ steps.generate_matrix.outputs.matrix }}
steps:
- name: Determine matrix
id: generate_matrix
uses: coactions/matrix@main
with:
min_python: "3.10"
max_python: "3.13"
default_python: "3.10"
other_names: lint
build:
name: ${{ matrix.name || matrix.passed_name || '?' }}
runs-on: ${{ matrix.os || 'ubuntu-22.04' }}
runs-on: ${{ matrix.os || 'ubuntu-24.04' }}
needs: pre
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.pre.outputs.matrix) }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python_version }}
uses: actions/setup-python@v5
with:
cache-dependency-path: .config/requirements*.in
cache: pip
python-version: ${{ matrix.python_version }}

- run: |
python3 --version
echo "${{ matrix.passed_name }}"
- run: pip3 install -U tox
- run: tox -e "${{ matrix.passed_name }}"
codeql:
name: codeql
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
needs:
- build
permissions:
Expand Down Expand Up @@ -95,7 +100,7 @@ jobs:
needs:
- build

runs-on: ubuntu-latest
runs-on: ubuntu-24.04

steps:
- name: Decide whether the needed jobs succeeded or failed
Expand Down
26 changes: 26 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,29 @@ repos:
- id: fix-byte-order-marker
- id: check-executables-have-shebangs
- id: check-merge-conflict
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.5.6"
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- repo: https://github.com/psf/black
rev: 24.8.0
hooks:
- id: black
language_version: python3
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.11.1
hooks:
- id: mypy
# empty args needed in order to match mypy cli behavior
args: [--strict]
additional_dependencies:
- actions-toolkit
- repo: https://github.com/pycqa/pylint
rev: v3.2.6
hooks:
- id: pylint
args:
- --output-format=colorized
additional_dependencies:
- actions-toolkit
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
FROM python:latest
COPY entrypoint.py /entrypoint.py
COPY .config/requirements.in requirements.txt
ENTRYPOINT ["python3", "/entrypoint.py"]
RUN pip3 install actions-toolkit
RUN pip3 install -r requirements.txt
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ projects using:
jobs:
pre: # <-- this runs before your real matrix job
name: pre
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
outputs:
matrix: ${{ steps.generate_matrix.outputs.matrix }}
steps:
Expand All @@ -41,7 +41,7 @@ jobs:
build:
name: ${{ matrix.name }}
runs-on: ${{ matrix.os || 'ubuntu-22.04' }}
runs-on: ${{ matrix.os || 'ubuntu-24.04' }}
needs: pre
strategy: # this the magic part, entire matrix comes from pre job!
matrix: ${{ fromJson(needs.pre.outputs.matrix) }}
Expand Down
37 changes: 16 additions & 21 deletions entrypoint.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!env python3
# """Action body."""
"""Action body."""
import json
import os
import re
Expand All @@ -8,7 +8,7 @@

KNOWN_PYTHONS = ("3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13-dev")
PYTHON_REDIRECTS = {
"3.13": "3.13-dev" # Remove once GHA allows 3.13 as a valid version
"3.13": "3.13-dev", # Remove once GHA allows 3.13 as a valid version
}
PLATFORM_MAP = {
"linux": "ubuntu-24.04",
Expand All @@ -21,8 +21,10 @@
IMPLICIT_DEFAULT_PYTHON = "3.9"
IMPLICIT_SKIP_EXPLODE = "0"


# loop list staring with given item
def main() -> None:
# pylint: disable=too-many-locals,too-many-branches
def main() -> None: # noqa: C901
"""Main."""
# print all env vars starting with INPUT_
for k, v in os.environ.items():
Expand All @@ -42,16 +44,12 @@ def main() -> None:
core.debug(f"Testing strategy: {strategies}")

result = []
try:
if max_python == "3.13":
python_names = KNOWN_PYTHONS[KNOWN_PYTHONS.index(min_python) :]
else:
python_names = KNOWN_PYTHONS[
KNOWN_PYTHONS.index(min_python) : (KNOWN_PYTHONS.index(max_python) + 1)
]
except Exception as e:
core.debug(e)
python_names = ()
if max_python == "3.13":
python_names = KNOWN_PYTHONS[KNOWN_PYTHONS.index(min_python) :]
else:
python_names = KNOWN_PYTHONS[
KNOWN_PYTHONS.index(min_python) : (KNOWN_PYTHONS.index(max_python) + 1)
]
python_flavours = len(python_names)
core.debug("...")
for env in other_names:
Expand All @@ -67,18 +65,14 @@ def main() -> None:
"passed_name": env,
"python_version": PYTHON_REDIRECTS.get(env_python, env_python),
"os": PLATFORM_MAP["linux"],
}
},
)

if not skip_explode:
for platform in platforms:
for i, python in enumerate(python_names):
py_name = re.sub(r"[^0-9]", "", python.strip("."))
if platform == IMPLICIT_PLATFORM:
suffix = ""
else:
suffix = f"-{platform}"

suffix = "" if platform == IMPLICIT_PLATFORM else f"-{platform}"
if strategies[platform] == "minmax" and (
i not in (0, python_flavours - 1)
):
Expand All @@ -90,7 +84,7 @@ def main() -> None:
"python_version": python,
"os": PLATFORM_MAP.get(platform, platform),
"passed_name": f"py{py_name}",
}
},
)

core.info(f"Generated {len(result)} matrix entries.")
Expand All @@ -100,7 +94,8 @@ def main() -> None:

core.set_output("matrix", {"include": result})

except Exception as exc:
# pylint: disable=broad-exception-caught
except Exception as exc: # noqa: BLE001
core.set_failed(f"Action failed due to {exc}")


Expand Down
173 changes: 173 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# cspell: disable addopts conftest minversion pyargs testpaths
[build-system]
requires = ["cython", "setuptools", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = 'dynamic-matrix'
dynamic = ["version", "dependencies", "optional-dependencies"]

[tool.black]
target-version = ["py310"]

[tool.codespell]
skip = ".tox,.mypy_cache,build,.git,.eggs,pip-wheel-metadata"

# Keep this default because xml/report do not know to use load it from config file:
# data_file = ".coverage"
[tool.coverage.paths]
source = ["."]

[tool.coverage.report]
exclude_also = ["pragma: no cover", "if TYPE_CHECKING:"]
omit = ["tests/*"]
# Increase it just so it would pass on any single-python run
fail_under = 92
skip_covered = true
skip_empty = true
# During development we might remove code (files) with coverage data, and we dont want to fail:
ignore_errors = true
show_missing = true

[tool.coverage.run]
source = ["."]
# Do not use branch until bug is fixes:
# https://github.com/nedbat/coveragepy/issues/605
# branch = true
parallel = true
concurrency = ["multiprocessing", "thread"]

[tool.mypy]
python_version = "3.10"
strict = true
color_output = true
error_summary = true
disallow_untyped_calls = true
disallow_untyped_defs = true
disallow_any_generics = true
# disallow_any_unimported = True
# warn_redundant_casts = True
# warn_return_any = True
# warn_unused_configs = True
# https://github.com/python/mypy/issues/12664
incremental = false

[[tool.mypy.overrides]]
module = [
"actions_toolkit",
]
ignore_missing_imports = true
ignore_errors = true

[tool.pylint.IMPORTS]
preferred-modules = ["py:pathlib", "unittest:pytest"]

[tool.pylint.MAIN]
extension-pkg-allow-list = ["black.parsing"]

[tool.pylint."MESSAGES CONTROL"]
# increase from default is 50 which is too aggressive
max-statements = 60
disable = [
# Disabled on purpose:
"line-too-long", # covered by black
"protected-access", # covered by ruff SLF001
"too-many-branches", # covered by ruff C901
# TODO(ssbarnea): remove temporary skips adding during initial adoption:
"duplicate-code",
# unable to disable it inside tests
# https://github.com/PyCQA/pylint/issues/850
"cyclic-import",
# https://github.com/PyCQA/pylint/issues/8453
"preferred-module",
]
enable = [
"useless-suppression", # Identify unneeded pylint disable statements
]

[tool.pylint.REPORTING]
output-format = "colorized"

[tool.pylint.SUMMARY]
# We don't need the score spamming console, as we either pass or fail
score = "n"

[tool.pyright]
# https://github.com/microsoft/pyright/blob/main/docs/configuration.md#sample-pyprojecttoml-file
pythonVersion = "3.10"
include = ["entrypoint.py"]
# https://github.com/microsoft/pyright/issues/777
"stubPath" = ""

# spell-checker:ignore filterwarnings norecursedirs optionflags
[tool.pytest.ini_options]
# do not add options here as this will likely break either console runs or IDE
# integration like vscode or pycharm
addopts = "-p no:pytest_cov"
# https://code.visualstudio.com/docs/python/testing
# coverage is re-enabled in `tox.ini`. That approach is safer than
# `--no-cov` which prevents activation from tox.ini and which also fails
# when plugin is effectively missing.
doctest_optionflags = ["ALLOW_UNICODE", "ELLIPSIS"]
filterwarnings = [
"error",
# https://sourceforge.net/p/ruamel-yaml/tickets/452/
"ignore:Deprecated call to `pkg_resources.declare_namespace:DeprecationWarning",
# https://github.com/spdx/tools-python/issues/507
"ignore:pkg_resources is deprecated as an API:DeprecationWarning",
# We raise one non critical warning from our own conftest.py:
"always::pytest.PytestWarning",
# py312 ansible-core
# https://github.com/ansible/ansible/issues/81906
"ignore:'importlib.abc.TraversableResources' is deprecated and slated for removal in Python 3.14:DeprecationWarning",
# https://github.com/ansible/ansible/pull/80968
"ignore:Attribute s is deprecated and will be removed in Python 3.14; use value instead:DeprecationWarning",
]
minversion = "4.6.6"
norecursedirs = [
"*.egg",
".cache",
".eggs",
".git",
".github",
".mypy_cache",
".projects",
".tox",
"build",
"collections",
"dist",
"docs",
]
python_files = [
"test_*.py",
# Ref: https://docs.pytest.org/en/latest/reference.html#confval-python_files
# Needed to discover legacy nose test modules:
"Test*.py",
]
# Using --pyargs instead of testpath as we embed some tests
# See: https://github.com/pytest-dev/pytest/issues/6451#issuecomment-687043537
# testpaths =
xfail_strict = true

[tool.ruff]
target-version = "py310"
# Same as Black.
line-length = 88
lint.ignore = [
"D203", # incompatible with D211
"D213", # incompatible with D212
"E501", # we use black
"ERA001", # auto-removal of commented out code affects development and vscode integration
"INP001", # "is part of an implicit namespace package", all false positives
"PLW2901", # PLW2901: Redefined loop variable
"RET504", # Unnecessary variable assignment before `return` statement
# temporary disabled until we fix them:
]
lint.select = ["ALL"]

[tool.ruff.lint.pydocstyle]
convention = "google"

[tool.setuptools.dynamic]
dependencies = { file = [".config/requirements.in"] }
optional-dependencies.test = { file = [".config/requirements-test.in"] }
Loading

0 comments on commit 8ce04c6

Please sign in to comment.