From e4336fbceb92e1673967b1f1bd9ca50ac947d7ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgar=20Ram=C3=ADrez=20Mondrag=C3=B3n?= <16805946+edgarrmondragon@users.noreply.github.com> Date: Fri, 17 Jan 2025 13:23:35 -0600 Subject: [PATCH 1/2] Bump Ruff and use formatter (#96) --- .pre-commit-config.yaml | 3 ++- plugin_test.py | 4 +++- pyproject.toml | 1 - pytest_github_actions_annotate_failures/plugin.py | 6 ++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 091ecc2..eb8015c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,8 @@ repos: - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.7.0" + rev: "v0.9.2" hooks: - id: ruff args: ["--fix", "--show-fixes"] + - id: ruff-format diff --git a/plugin_test.py b/plugin_test.py index 3037fa7..b827269 100644 --- a/plugin_test.py +++ b/plugin_test.py @@ -49,7 +49,9 @@ def test_error(): result = testdir.runpytest_subprocess() result.stderr.re_match_lines( - [r"::error file=test_annotation_pytest_error\.py,line=8::test_error.*",] + [ + r"::error file=test_annotation_pytest_error\.py,line=8::test_error.*", + ] ) diff --git a/pyproject.toml b/pyproject.toml index a4c5cb6..70e582c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -77,7 +77,6 @@ extend-select = [ ] ignore = [ "PLR", # Design related pylint codes - "PT004", # Use underscore for non-returning fixture (use usefixture instead) ] isort.required-imports = ["from __future__ import annotations"] diff --git a/pytest_github_actions_annotate_failures/plugin.py b/pytest_github_actions_annotate_failures/plugin.py index 0c364ea..2c29fad 100644 --- a/pytest_github_actions_annotate_failures/plugin.py +++ b/pytest_github_actions_annotate_failures/plugin.py @@ -1,4 +1,3 @@ - from __future__ import annotations import contextlib @@ -133,6 +132,7 @@ def pytest_addoption(parser): help="Annotate failures in GitHub Actions.", ) + def pytest_configure(config): if not config.option.exclude_warning_annotations: config.pluginmanager.register(_AnnotateWarnings(), "annotate_warnings") @@ -160,9 +160,7 @@ def _build_workflow_command( ("title", title), ] - result = result + ",".join( - f"{k}={v}" for k, v in entries if v is not None - ) + result = result + ",".join(f"{k}={v}" for k, v in entries if v is not None) if message is not None: result = result + "::" + _escape(message) From fd623c13147eb6b48a87f1c44ae69c15ae976be8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgar=20Ram=C3=ADrez=20Mondrag=C3=B3n?= <16805946+edgarrmondragon@users.noreply.github.com> Date: Fri, 17 Jan 2025 13:28:14 -0600 Subject: [PATCH 2/2] fix: support Pytest 7.4+ (#97) Co-authored-by: Henry Schreiner --- .github/workflows/test.yml | 6 ++ plugin_test.py | 2 +- .../plugin.py | 74 ++++++++++--------- tox.ini | 2 +- 4 files changed, 48 insertions(+), 36 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 97916b1..d5d4310 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -54,6 +54,12 @@ jobs: PYTEST_MAJOR_VERSION: 7 PYTEST_PLUGINS: pytest_github_actions_annotate_failures + - name: Run tests with PyTest 8 + run: tox + env: + PYTEST_MAJOR_VERSION: 8 + PYTEST_PLUGINS: pytest_github_actions_annotate_failures + post-test: name: All tests passed if: always() diff --git a/plugin_test.py b/plugin_test.py index b827269..1b32b6c 100644 --- a/plugin_test.py +++ b/plugin_test.py @@ -223,7 +223,7 @@ def test_fail(): result = testdir.runpytest_subprocess("--rootdir=foo") result.stderr.fnmatch_lines( [ - "::error file=test_annotation_fail_cwd.py,line=5::test_fail*assert 0*", + "::error file=test_annotation_fail_cwd0/test_annotation_fail_cwd.py,line=5::test_fail*assert 0*", ] ) diff --git a/pytest_github_actions_annotate_failures/plugin.py b/pytest_github_actions_annotate_failures/plugin.py index 2c29fad..3f58b95 100644 --- a/pytest_github_actions_annotate_failures/plugin.py +++ b/pytest_github_actions_annotate_failures/plugin.py @@ -6,7 +6,7 @@ from typing import TYPE_CHECKING import pytest -from _pytest._code.code import ExceptionRepr +from _pytest._code.code import ExceptionRepr, ReprEntry from packaging import version if TYPE_CHECKING: @@ -38,32 +38,12 @@ def pytest_runtest_makereport(item: Item, call): # noqa: ARG001 return if report.when == "call" and report.failed: - # collect information to be annotated filesystempath, lineno, _ = report.location - runpath = os.environ.get("PYTEST_RUN_PATH") - if runpath: - filesystempath = os.path.join(runpath, filesystempath) - - # try to convert to absolute path in GitHub Actions - workspace = os.environ.get("GITHUB_WORKSPACE") - if workspace: - full_path = os.path.abspath(filesystempath) - try: - rel_path = os.path.relpath(full_path, workspace) - except ValueError: - # os.path.relpath() will raise ValueError on Windows - # when full_path and workspace have different mount points. - # https://github.com/utgwkk/pytest-github-actions-annotate-failures/issues/20 - rel_path = filesystempath - if not rel_path.startswith(".."): - filesystempath = rel_path - if lineno is not None: # 0-index to 1-index lineno += 1 - # get the name of the current failed test, with parametrize info longrepr = report.head_line or item.name # get the error message and line number from the actual error @@ -71,26 +51,52 @@ def pytest_runtest_makereport(item: Item, call): # noqa: ARG001 if report.longrepr.reprcrash is not None: longrepr += "\n\n" + report.longrepr.reprcrash.message tb_entries = report.longrepr.reprtraceback.reprentries - if len(tb_entries) > 1 and tb_entries[0].reprfileloc is not None: + if tb_entries: + entry = tb_entries[0] # Handle third-party exceptions - lineno = tb_entries[0].reprfileloc.lineno + if isinstance(entry, ReprEntry) and entry.reprfileloc is not None: + lineno = entry.reprfileloc.lineno + filesystempath = entry.reprfileloc.path + elif report.longrepr.reprcrash is not None: lineno = report.longrepr.reprcrash.lineno elif isinstance(report.longrepr, tuple): - _, lineno, message = report.longrepr + filesystempath, lineno, message = report.longrepr longrepr += "\n\n" + message elif isinstance(report.longrepr, str): longrepr += "\n\n" + report.longrepr workflow_command = _build_workflow_command( "error", - filesystempath, + compute_path(filesystempath), lineno, message=longrepr, ) print(workflow_command, file=sys.stderr) +def compute_path(filesystempath: str) -> str: + """Extract and process location information from the report.""" + runpath = os.environ.get("PYTEST_RUN_PATH") + if runpath: + filesystempath = os.path.join(runpath, filesystempath) + + # try to convert to absolute path in GitHub Actions + workspace = os.environ.get("GITHUB_WORKSPACE") + if workspace: + full_path = os.path.abspath(filesystempath) + try: + rel_path = os.path.relpath(full_path, workspace) + except ValueError: + # os.path.relpath() will raise ValueError on Windows + # when full_path and workspace have different mount points. + rel_path = filesystempath + if not rel_path.startswith(".."): + filesystempath = rel_path + + return filesystempath + + class _AnnotateWarnings: def pytest_warning_recorded(self, warning_message, when, nodeid, location): # noqa: ARG002 # enable only in a workflow of GitHub Actions @@ -139,14 +145,14 @@ def pytest_configure(config): def _build_workflow_command( - command_name, - file, - line, - end_line=None, - column=None, - end_column=None, - title=None, - message=None, + command_name: str, + file: str, + line: int, + end_line: int | None = None, + column: int | None = None, + end_column: int | None = None, + title: str | None = None, + message: str | None = None, ): """Build a command to annotate a workflow.""" result = f"::{command_name} " @@ -168,5 +174,5 @@ def _build_workflow_command( return result -def _escape(s): +def _escape(s: str) -> str: return s.replace("%", "%25").replace("\r", "%0D").replace("\n", "%0A") diff --git a/tox.ini b/tox.ini index 877d362..11016c2 100644 --- a/tox.ini +++ b/tox.ini @@ -20,7 +20,7 @@ PYTEST_MAJOR_VERSION = extras = test deps = pytest6: pytest>=6.0.0,<7.0.0 - pytest7: pytest>=7.0.0,<7.4.0 + pytest7: pytest>=7.0.0,<8.0.0 pytest8: pytest>=8.0.0,<9.0.0 commands = {envpython} -m pytest {posargs}