Skip to content

Commit 7770dac

Browse files
committed
pygments themes are customizable
1 parent 2439729 commit 7770dac

File tree

6 files changed

+99
-4
lines changed

6 files changed

+99
-4
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ Edson Tadeu M. Manoel
106106
Eduardo Schettino
107107
Eli Boyarski
108108
Elizaveta Shashkova
109+
Éloi Rivard
109110
Endre Galaczi
110111
Eric Hunsberger
111112
Eric Liu

changelog/7132.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added two environment variables :envvar:`PYTEST_THEME` and :envvar:`PYTEST_THEME_MODE` to let the users customize the pygments theme used.

doc/en/reference/customize.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,3 +239,11 @@ Builtin configuration file options
239239
----------------------------------------------
240240

241241
For the full list of options consult the :ref:`reference documentation <ini options ref>`.
242+
243+
Syntax highlighting theme customization
244+
---------------------------------------
245+
246+
The syntax highlighting themes used by pytest can be customized using two environment variables:
247+
248+
- :envvar:`PYTEST_THEME` sets a `pygment style <https://pygments.org/docs/styles/>`_ to use.
249+
- :envvar:`PYTEST_THEME_MODE` sets this style to *light* or *dark*.

doc/en/reference/reference.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,6 +1075,14 @@ Contains comma-separated list of modules that should be loaded as plugins:
10751075
10761076
export PYTEST_PLUGINS=mymodule.plugin,xdist
10771077
1078+
.. envvar:: PYTEST_THEME
1079+
1080+
Sets a `pygment style <https://pygments.org/docs/styles/>`_ to use for the code output.
1081+
1082+
.. envvar:: PYTEST_THEME_MODE
1083+
1084+
Sets the :envvar:`PYTEST_THEME` to be either *dark* or *light*.
1085+
10781086
.. envvar:: PY_COLORS
10791087

10801088
When set to ``1``, pytest will use color in terminal output.

src/_pytest/_io/terminalwriter.py

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,16 +195,39 @@ def _write_source(self, lines: Sequence[str], indents: Sequence[str] = ()) -> No
195195

196196
def _highlight(self, source: str) -> str:
197197
"""Highlight the given source code if we have markup support."""
198+
from _pytest.config.exceptions import UsageError
199+
198200
if not self.hasmarkup or not self.code_highlight:
199201
return source
200202
try:
201203
from pygments.formatters.terminal import TerminalFormatter
202204
from pygments.lexers.python import PythonLexer
203205
from pygments import highlight
206+
import pygments.util
204207
except ImportError:
205208
return source
206209
else:
207-
highlighted: str = highlight(
208-
source, PythonLexer(), TerminalFormatter(bg="dark")
209-
)
210-
return highlighted
210+
try:
211+
highlighted: str = highlight(
212+
source,
213+
PythonLexer(),
214+
TerminalFormatter(
215+
bg=os.getenv("PYTEST_THEME_MODE", "dark"),
216+
style=os.getenv("PYTEST_THEME"),
217+
),
218+
)
219+
return highlighted
220+
except pygments.util.ClassNotFound:
221+
raise UsageError(
222+
"PYTEST_THEME environment variable had an invalid value: '{}'. "
223+
"Only valid pygment styles are allowed.".format(
224+
os.getenv("PYTEST_THEME")
225+
)
226+
)
227+
except pygments.util.OptionError:
228+
raise UsageError(
229+
"PYTEST_THEME_MODE environment variable had an invalid value: '{}'. "
230+
"The only allowed values are 'dark' and 'light'.".format(
231+
os.getenv("PYTEST_THEME_MODE")
232+
)
233+
)

testing/test_terminal.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2408,6 +2408,60 @@ def test_foo():
24082408
)
24092409
)
24102410

2411+
def test_code_highlight_custom_theme(
2412+
self, pytester: Pytester, color_mapping, monkeypatch: MonkeyPatch
2413+
) -> None:
2414+
pytester.makepyfile(
2415+
"""
2416+
def test_foo():
2417+
assert 1 == 10
2418+
"""
2419+
)
2420+
monkeypatch.setenv("PYTEST_THEME", "solarized-dark")
2421+
monkeypatch.setenv("PYTEST_THEME_MODE", "dark")
2422+
result = pytester.runpytest("--color=yes")
2423+
result.stdout.fnmatch_lines(
2424+
color_mapping.format_for_fnmatch(
2425+
[
2426+
" {kw}def{hl-reset} {function}test_foo{hl-reset}():",
2427+
"> {kw}assert{hl-reset} {number}1{hl-reset} == {number}10{hl-reset}",
2428+
"{bold}{red}E assert 1 == 10{reset}",
2429+
]
2430+
)
2431+
)
2432+
2433+
def test_code_highlight_invalid_theme(
2434+
self, pytester: Pytester, color_mapping, monkeypatch: MonkeyPatch
2435+
) -> None:
2436+
pytester.makepyfile(
2437+
"""
2438+
def test_foo():
2439+
assert 1 == 10
2440+
"""
2441+
)
2442+
monkeypatch.setenv("PYTEST_THEME", "invalid")
2443+
result = pytester.runpytest_subprocess("--color=yes")
2444+
result.stderr.fnmatch_lines(
2445+
"ERROR: PYTEST_THEME environment variable had an invalid value: 'invalid'. "
2446+
"Only valid pygment styles are allowed."
2447+
)
2448+
2449+
def test_code_highlight_invalid_theme_mode(
2450+
self, pytester: Pytester, color_mapping, monkeypatch: MonkeyPatch
2451+
) -> None:
2452+
pytester.makepyfile(
2453+
"""
2454+
def test_foo():
2455+
assert 1 == 10
2456+
"""
2457+
)
2458+
monkeypatch.setenv("PYTEST_THEME_MODE", "invalid")
2459+
result = pytester.runpytest_subprocess("--color=yes")
2460+
result.stderr.fnmatch_lines(
2461+
"ERROR: PYTEST_THEME_MODE environment variable had an invalid value: 'invalid'. "
2462+
"The only allowed values are 'dark' and 'light'."
2463+
)
2464+
24112465

24122466
def test_raw_skip_reason_skipped() -> None:
24132467
report = SimpleNamespace()

0 commit comments

Comments
 (0)