From 69589862398d9eab59bbd1c1b63ded7b5344c18e Mon Sep 17 00:00:00 2001 From: Nitesh Kumar Date: Thu, 10 Sep 2026 13:38:40 +0530 Subject: [PATCH] ci: fix the lint findings that stop CI before any test runs Every leg of the CI matrix on master fails at the "Lint (ruff)" step (run #455, all nine legs), so yamllint, mypy and the test suite never run. The red X on master is not a failing test being reported -- CI has not got as far as running one in a long time. That is not academic. `python -m pytest tests/` fails 9 tests in tests/unit/test_index_sync.py on master today, and CI has never said so. ruff reports four findings, all in test files: tests/ebuild/test_build_dir_resolution.py:31 F811 import shutil twice tests/unit/test_ci_gate.py:214,215 E402 imports below code tests/ebuild/test_package_recipe.py:117 W292 no newline at EOF With those fixed the job gets as far as mypy, which fails on ebuild/plugins/__init__.py:46. The `# type: ignore[attr-defined]` there names the wrong error code, so it was never silencing the arg-type error the same line raises. I spelled out the pre-3.10 entry_points() mapping shape with cast instead of widening the ignore. That branch only runs on Python 3.8/3.9, which the matrix does not cover, so runtime behaviour is unchanged either way. The 9 index-sync failures that remain are PR #119's, and I have not duplicated it. With both applied the suite is 678 passed, 0 failed. Checked on Python 3.11.15 with ruff 0.16.6, running each CI step by hand: ruff and yamllint clean, mypy down from 2 errors to 1, pytest unchanged at 669 passed with no test expectations touched. Signed-off-by: Nitesh Kumar --- ebuild/plugins/__init__.py | 11 +++++++---- tests/ebuild/test_build_dir_resolution.py | 1 - tests/ebuild/test_package_recipe.py | 2 +- tests/unit/test_ci_gate.py | 8 ++++---- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/ebuild/plugins/__init__.py b/ebuild/plugins/__init__.py index 3353ea5..54605f0 100644 --- a/ebuild/plugins/__init__.py +++ b/ebuild/plugins/__init__.py @@ -11,7 +11,7 @@ import importlib.metadata import logging -from typing import List +from typing import Any, List, Mapping, cast from ebuild.plugins.base import PluginBase @@ -41,9 +41,12 @@ def discover_plugins() -> List[PluginBase]: if hasattr(entry_points, "select"): eps = entry_points.select(group="ebuild.plugins") else: - # Before 3.10 entry_points() returned a dict; the current stubs - # only model EntryPoints, which has no .get, hence the ignore. - eps = entry_points.get("ebuild.plugins", []) # type: ignore[attr-defined] + # Before 3.10, entry_points() returned a mapping of group name + # to entry points. The stubs only model the modern EntryPoints, so + # spell the old shape out rather than widen the ignore: the + # `# type: ignore[attr-defined]` that was here named the wrong + # error code, and mypy failed on the line anyway. + eps = cast(Mapping[str, Any], entry_points).get("ebuild.plugins", []) for ep in eps: try: diff --git a/tests/ebuild/test_build_dir_resolution.py b/tests/ebuild/test_build_dir_resolution.py index a19be13..e08444f 100644 --- a/tests/ebuild/test_build_dir_resolution.py +++ b/tests/ebuild/test_build_dir_resolution.py @@ -28,7 +28,6 @@ import os import shutil import subprocess -import shutil import textwrap from pathlib import Path from types import SimpleNamespace diff --git a/tests/ebuild/test_package_recipe.py b/tests/ebuild/test_package_recipe.py index 38c38de..3c25922 100644 --- a/tests/ebuild/test_package_recipe.py +++ b/tests/ebuild/test_package_recipe.py @@ -114,4 +114,4 @@ def test_depends_alias_must_be_a_list(): """ with pytest.raises(RecipeError, match="dependencies"): - load_recipe_from_string(content) \ No newline at end of file + load_recipe_from_string(content) diff --git a/tests/unit/test_ci_gate.py b/tests/unit/test_ci_gate.py index 964ca54..b1d5e0f 100644 --- a/tests/unit/test_ci_gate.py +++ b/tests/unit/test_ci_gate.py @@ -11,9 +11,12 @@ required check does not cover. """ +import itertools +import re +from pathlib import Path + import yaml import pytest -from pathlib import Path WORKFLOWS_DIR = Path(__file__).resolve().parents[2] / ".github" / "workflows" @@ -211,9 +214,6 @@ def test_gate_fails_on_any_non_success_result(jobs): # check cannot say which of the three it means, and a Windows-only failure is # indistinguishable from the other two legs without opening the run. -import itertools -import re - # `include` and `exclude` shape a matrix but are not dimensions of it, so they # are not part of the cartesian product. _NOT_A_DIMENSION = {"include", "exclude"}