Skip to content

Commit fd623c1

Browse files
fix: support Pytest 7.4+ (#97)
Co-authored-by: Henry Schreiner <henryschreineriii@gmail.com>
1 parent e4336fb commit fd623c1

File tree

4 files changed

+48
-36
lines changed

4 files changed

+48
-36
lines changed

.github/workflows/test.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ jobs:
5454
PYTEST_MAJOR_VERSION: 7
5555
PYTEST_PLUGINS: pytest_github_actions_annotate_failures
5656

57+
- name: Run tests with PyTest 8
58+
run: tox
59+
env:
60+
PYTEST_MAJOR_VERSION: 8
61+
PYTEST_PLUGINS: pytest_github_actions_annotate_failures
62+
5763
post-test:
5864
name: All tests passed
5965
if: always()

plugin_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ def test_fail():
223223
result = testdir.runpytest_subprocess("--rootdir=foo")
224224
result.stderr.fnmatch_lines(
225225
[
226-
"::error file=test_annotation_fail_cwd.py,line=5::test_fail*assert 0*",
226+
"::error file=test_annotation_fail_cwd0/test_annotation_fail_cwd.py,line=5::test_fail*assert 0*",
227227
]
228228
)
229229

pytest_github_actions_annotate_failures/plugin.py

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from typing import TYPE_CHECKING
77

88
import pytest
9-
from _pytest._code.code import ExceptionRepr
9+
from _pytest._code.code import ExceptionRepr, ReprEntry
1010
from packaging import version
1111

1212
if TYPE_CHECKING:
@@ -38,59 +38,65 @@ def pytest_runtest_makereport(item: Item, call): # noqa: ARG001
3838
return
3939

4040
if report.when == "call" and report.failed:
41-
# collect information to be annotated
4241
filesystempath, lineno, _ = report.location
4342

44-
runpath = os.environ.get("PYTEST_RUN_PATH")
45-
if runpath:
46-
filesystempath = os.path.join(runpath, filesystempath)
47-
48-
# try to convert to absolute path in GitHub Actions
49-
workspace = os.environ.get("GITHUB_WORKSPACE")
50-
if workspace:
51-
full_path = os.path.abspath(filesystempath)
52-
try:
53-
rel_path = os.path.relpath(full_path, workspace)
54-
except ValueError:
55-
# os.path.relpath() will raise ValueError on Windows
56-
# when full_path and workspace have different mount points.
57-
# https://github.com/utgwkk/pytest-github-actions-annotate-failures/issues/20
58-
rel_path = filesystempath
59-
if not rel_path.startswith(".."):
60-
filesystempath = rel_path
61-
6243
if lineno is not None:
6344
# 0-index to 1-index
6445
lineno += 1
6546

66-
# get the name of the current failed test, with parametrize info
6747
longrepr = report.head_line or item.name
6848

6949
# get the error message and line number from the actual error
7050
if isinstance(report.longrepr, ExceptionRepr):
7151
if report.longrepr.reprcrash is not None:
7252
longrepr += "\n\n" + report.longrepr.reprcrash.message
7353
tb_entries = report.longrepr.reprtraceback.reprentries
74-
if len(tb_entries) > 1 and tb_entries[0].reprfileloc is not None:
54+
if tb_entries:
55+
entry = tb_entries[0]
7556
# Handle third-party exceptions
76-
lineno = tb_entries[0].reprfileloc.lineno
57+
if isinstance(entry, ReprEntry) and entry.reprfileloc is not None:
58+
lineno = entry.reprfileloc.lineno
59+
filesystempath = entry.reprfileloc.path
60+
7761
elif report.longrepr.reprcrash is not None:
7862
lineno = report.longrepr.reprcrash.lineno
7963
elif isinstance(report.longrepr, tuple):
80-
_, lineno, message = report.longrepr
64+
filesystempath, lineno, message = report.longrepr
8165
longrepr += "\n\n" + message
8266
elif isinstance(report.longrepr, str):
8367
longrepr += "\n\n" + report.longrepr
8468

8569
workflow_command = _build_workflow_command(
8670
"error",
87-
filesystempath,
71+
compute_path(filesystempath),
8872
lineno,
8973
message=longrepr,
9074
)
9175
print(workflow_command, file=sys.stderr)
9276

9377

78+
def compute_path(filesystempath: str) -> str:
79+
"""Extract and process location information from the report."""
80+
runpath = os.environ.get("PYTEST_RUN_PATH")
81+
if runpath:
82+
filesystempath = os.path.join(runpath, filesystempath)
83+
84+
# try to convert to absolute path in GitHub Actions
85+
workspace = os.environ.get("GITHUB_WORKSPACE")
86+
if workspace:
87+
full_path = os.path.abspath(filesystempath)
88+
try:
89+
rel_path = os.path.relpath(full_path, workspace)
90+
except ValueError:
91+
# os.path.relpath() will raise ValueError on Windows
92+
# when full_path and workspace have different mount points.
93+
rel_path = filesystempath
94+
if not rel_path.startswith(".."):
95+
filesystempath = rel_path
96+
97+
return filesystempath
98+
99+
94100
class _AnnotateWarnings:
95101
def pytest_warning_recorded(self, warning_message, when, nodeid, location): # noqa: ARG002
96102
# enable only in a workflow of GitHub Actions
@@ -139,14 +145,14 @@ def pytest_configure(config):
139145

140146

141147
def _build_workflow_command(
142-
command_name,
143-
file,
144-
line,
145-
end_line=None,
146-
column=None,
147-
end_column=None,
148-
title=None,
149-
message=None,
148+
command_name: str,
149+
file: str,
150+
line: int,
151+
end_line: int | None = None,
152+
column: int | None = None,
153+
end_column: int | None = None,
154+
title: str | None = None,
155+
message: str | None = None,
150156
):
151157
"""Build a command to annotate a workflow."""
152158
result = f"::{command_name} "
@@ -168,5 +174,5 @@ def _build_workflow_command(
168174
return result
169175

170176

171-
def _escape(s):
177+
def _escape(s: str) -> str:
172178
return s.replace("%", "%25").replace("\r", "%0D").replace("\n", "%0A")

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ PYTEST_MAJOR_VERSION =
2020
extras = test
2121
deps =
2222
pytest6: pytest>=6.0.0,<7.0.0
23-
pytest7: pytest>=7.0.0,<7.4.0
23+
pytest7: pytest>=7.0.0,<8.0.0
2424
pytest8: pytest>=8.0.0,<9.0.0
2525

2626
commands = {envpython} -m pytest {posargs}

0 commit comments

Comments
 (0)