Skip to content

Commit 1e16b5c

Browse files
authored
Merge branch 'main' into 13737-require-unique-paramset-ids
2 parents 4d6fa15 + a55c959 commit 1e16b5c

File tree

16 files changed

+295
-70
lines changed

16 files changed

+295
-70
lines changed

AUTHORS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ Andrzej Klajnert
3939
Andrzej Ostrowski
4040
Andy Freeland
4141
Anita Hammer
42+
Anna Tasiopoulou
4243
Anthon van der Neut
4344
Anthony Shaw
4445
Anthony Sottile
@@ -227,6 +228,7 @@ Jon Parise
227228
Jon Sonesen
228229
Jonas Obrist
229230
Jordan Guymon
231+
Jordan Macdonald
230232
Jordan Moldow
231233
Jordan Speicher
232234
Joseph Hunkeler

changelog/13072.feature.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Added support for displaying test session progress in the terminal tab using the `OSC 9;4; <https://conemu.github.io/en/AnsiEscapeCodes.html#ConEmu_specific_OSC>`_ ANSI sequence.
2+
When pytest runs in a supported terminal emulator like ConEmu, Gnome Terminal, Ptyxis, Windows Terminal, Kitty or Ghostty,
3+
you'll see the progress in the terminal tab or window,
4+
allowing you to monitor pytest's progress at a glance.
5+
6+
This feature is automatically enabled when running in a TTY. It is implemented as an internal plugin. If needed, it can be disabled as follows:
7+
- On a user level, using ``-p no:terminalprogress`` on the command line or via an environment variable ``PYTEST_ADDOPTS='-p no:terminalprogress'``.
8+
- On a project configuration level, using ``addopts = "-p no:terminalprogress"``.

changelog/13766.breaking.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Previously, pytest would assume it was running in a CI/CD environment if either of the environment variables `$CI` or `$BUILD_NUMBER` was defined;
2+
now, CI mode is only activated if at least one of those variables is defined and set to a *non-empty* value.

doc/en/explanation/ci.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ adapt some of its behaviours.
1717
How CI is detected
1818
------------------
1919

20-
Pytest knows it is in a CI environment when either one of these environment variables are set,
21-
regardless of their value:
20+
Pytest knows it is in a CI environment when either one of these environment variables are set to a non-empty value:
2221

2322
* `CI`: used by many CI systems.
2423
* `BUILD_NUMBER`: used by Jenkins.

doc/en/reference/reference.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,11 +1165,11 @@ Environment variables that can be used to change pytest's behavior.
11651165

11661166
.. envvar:: CI
11671167

1168-
When set (regardless of value), pytest acknowledges that is running in a CI process. Alternative to ``BUILD_NUMBER`` variable. See also :ref:`ci-pipelines`.
1168+
When set to a non-empty value, pytest acknowledges that is running in a CI process. See also :ref:`ci-pipelines`.
11691169

11701170
.. envvar:: BUILD_NUMBER
11711171

1172-
When set (regardless of value), pytest acknowledges that is running in a CI process. Alternative to CI variable. See also :ref:`ci-pipelines`.
1172+
When set to a non-empty value, pytest acknowledges that is running in a CI process. Alternative to :envvar:`CI`. See also :ref:`ci-pipelines`.
11731173

11741174
.. envvar:: PYTEST_ADDOPTS
11751175

@@ -2412,7 +2412,7 @@ All the command-line flags can be obtained by running ``pytest --help``::
24122412
Plugins that must be present for pytest to run
24132413

24142414
Environment variables:
2415-
CI When set (regardless of value), pytest knows it is running in a CI process and does not truncate summary info
2415+
CI When set to a non-empty value, pytest knows it is running in a CI process and does not truncate summary info
24162416
BUILD_NUMBER Equivalent to CI
24172417
PYTEST_ADDOPTS Extra command line options
24182418
PYTEST_PLUGINS Comma-separated plugins to load during startup

src/_pytest/_io/terminalwriter.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -161,20 +161,23 @@ def write(self, msg: str, *, flush: bool = False, **markup: bool) -> None:
161161

162162
msg = self.markup(msg, **markup)
163163

164-
try:
165-
self._file.write(msg)
166-
except UnicodeEncodeError:
167-
# Some environments don't support printing general Unicode
168-
# strings, due to misconfiguration or otherwise; in that case,
169-
# print the string escaped to ASCII.
170-
# When the Unicode situation improves we should consider
171-
# letting the error propagate instead of masking it (see #7475
172-
# for one brief attempt).
173-
msg = msg.encode("unicode-escape").decode("ascii")
174-
self._file.write(msg)
175-
176-
if flush:
177-
self.flush()
164+
self.write_raw(msg, flush=flush)
165+
166+
def write_raw(self, msg: str, *, flush: bool = False) -> None:
167+
try:
168+
self._file.write(msg)
169+
except UnicodeEncodeError:
170+
# Some environments don't support printing general Unicode
171+
# strings, due to misconfiguration or otherwise; in that case,
172+
# print the string escaped to ASCII.
173+
# When the Unicode situation improves we should consider
174+
# letting the error propagate instead of masking it (see #7475
175+
# for one brief attempt).
176+
msg = msg.encode("unicode-escape").decode("ascii")
177+
self._file.write(msg)
178+
179+
if flush:
180+
self.flush()
178181

179182
def line(self, s: str = "", **markup: bool) -> None:
180183
self.write(s, **markup)

src/_pytest/assertion/truncate.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from __future__ import annotations
88

9-
from _pytest.assertion import util
9+
from _pytest.compat import running_on_ci
1010
from _pytest.config import Config
1111
from _pytest.nodes import Item
1212

@@ -43,7 +43,7 @@ def _get_truncation_parameters(item: Item) -> tuple[bool, int, int]:
4343

4444
verbose = item.config.get_verbosity(Config.VERBOSITY_ASSERTIONS)
4545

46-
should_truncate = verbose < 2 and not util.running_on_ci()
46+
should_truncate = verbose < 2 and not running_on_ci()
4747
should_truncate = should_truncate and (max_lines > 0 or max_chars > 0)
4848

4949
return should_truncate, max_lines, max_chars

src/_pytest/assertion/util.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
from collections.abc import Mapping
1010
from collections.abc import Sequence
1111
from collections.abc import Set as AbstractSet
12-
import os
1312
import pprint
1413
from typing import Any
1514
from typing import Literal
@@ -21,6 +20,7 @@
2120
from _pytest._io.pprint import PrettyPrinter
2221
from _pytest._io.saferepr import saferepr
2322
from _pytest._io.saferepr import saferepr_unlimited
23+
from _pytest.compat import running_on_ci
2424
from _pytest.config import Config
2525

2626

@@ -613,9 +613,3 @@ def _notin_text(term: str, text: str, verbose: int = 0) -> list[str]:
613613
else:
614614
newdiff.append(line)
615615
return newdiff
616-
617-
618-
def running_on_ci() -> bool:
619-
"""Check if we're currently running on a CI system."""
620-
env_vars = ["CI", "BUILD_NUMBER"]
621-
return any(var in os.environ for var in env_vars)

src/_pytest/cacheprovider.py

100755100644
File mode changed.

src/_pytest/compat.py

Lines changed: 14 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# mypy: allow-untyped-defs
2-
"""Python version compatibility code."""
2+
"""Python version compatibility code and random general utilities."""
33

44
from __future__ import annotations
55

@@ -278,39 +278,12 @@ def get_user_id() -> int | None:
278278
return uid if uid != ERROR else None
279279

280280

281-
# Perform exhaustiveness checking.
282-
#
283-
# Consider this example:
284-
#
285-
# MyUnion = Union[int, str]
286-
#
287-
# def handle(x: MyUnion) -> int {
288-
# if isinstance(x, int):
289-
# return 1
290-
# elif isinstance(x, str):
291-
# return 2
292-
# else:
293-
# raise Exception('unreachable')
294-
#
295-
# Now suppose we add a new variant:
296-
#
297-
# MyUnion = Union[int, str, bytes]
298-
#
299-
# After doing this, we must remember ourselves to go and update the handle
300-
# function to handle the new variant.
301-
#
302-
# With `assert_never` we can do better:
303-
#
304-
# // raise Exception('unreachable')
305-
# return assert_never(x)
306-
#
307-
# Now, if we forget to handle the new variant, the type-checker will emit a
308-
# compile-time error, instead of the runtime error we would have gotten
309-
# previously.
310-
#
311-
# This also work for Enums (if you use `is` to compare) and Literals.
312-
def assert_never(value: NoReturn) -> NoReturn:
313-
assert False, f"Unhandled value: {value} ({type(value).__name__})"
281+
if sys.version_info >= (3, 11):
282+
from typing import assert_never
283+
else:
284+
285+
def assert_never(value: NoReturn) -> NoReturn:
286+
assert False, f"Unhandled value: {value} ({type(value).__name__})"
314287

315288

316289
class CallableBool:
@@ -331,3 +304,10 @@ def __bool__(self) -> bool:
331304

332305
def __call__(self) -> bool:
333306
return self._value
307+
308+
309+
def running_on_ci() -> bool:
310+
"""Check if we're currently running on a CI system."""
311+
# Only enable CI mode if one of these env variables is defined and non-empty.
312+
env_vars = ["CI", "BUILD_NUMBER"]
313+
return any(os.environ.get(var) for var in env_vars)

0 commit comments

Comments
 (0)