File: conftest.py

package info (click to toggle)
python-blessed 1.25-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 8,812 kB
  • sloc: python: 14,645; makefile: 13; sh: 7
file content (139 lines) | stat: -rw-r--r-- 4,132 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
"""Configure test fixtures"""

# std imports
import os
import platform
import subprocess

# 3rd party
import pytest

IS_WINDOWS = platform.system() == 'Windows'

all_terms_params = 'xterm screen ansi vt220 rxvt cons25 linux'.split()
many_lines_params = [40, 80]
# we must test a '1' column for conditional in _handle_long_word
many_columns_params = [1, 10]


def envvar_enabled(envvar):
    """
    Return True if environment variable is set and enabled

    unset values, 'no', 0, and 'false' and treated as False regardless of case
    All other values are considered True
    """

    value = os.environ.get(envvar, False)

    if value is False:
        return value

    if value.lower() in {'no', 'false'}:
        return False

    try:
        return bool(int(value))
    except ValueError:
        return True


TEST_FULL = envvar_enabled('TEST_FULL')
TEST_KEYBOARD = envvar_enabled('TEST_KEYBOARD')
TEST_QUICK = envvar_enabled('TEST_QUICK')
TEST_RAW = envvar_enabled('TEST_RAW')


if TEST_FULL:
    try:
        all_terms_params = [
            # use all values of the first column of data in output of 'toe -a'
            _term.split(None, 1)[0] for _term in
            subprocess.Popen(('toe', '-a'),  # pylint: disable=consider-using-with
                             stdout=subprocess.PIPE,
                             close_fds=True)
            .communicate()[0].splitlines()]
    except OSError:
        pass
elif IS_WINDOWS:
    all_terms_params = ['vtwin10', ]
elif TEST_QUICK:
    all_terms_params = 'xterm screen ansi linux'.split()


if TEST_QUICK:
    many_lines_params = [80, ]
    many_columns_params = [25, ]


@pytest.fixture(autouse=True)
def detect_curses_contamination(request):
    """
    Detect when Terminal() is instantiated in parent pytest process.

    The curses module can only call setupterm() once per process. If a test
    instantiates Terminal() in the parent pytest process (instead of within
    @as_subprocess), it contaminates all subsequent tests that try to use
    a different terminal kind.

    This fixture runs automatically for all tests and fails any test that
    initializes curses in the parent process.
    """
    if IS_WINDOWS:
        # Windows doesn't have the curses singleton limitation
        yield
        return

    # Import here to avoid issues if module not yet imported
    import blessed.terminal  # pylint: disable=import-outside-toplevel

    # Record the state before the test
    before = blessed.terminal._CUR_TERM

    # Run the test
    yield

    # Check if curses was initialized during the test
    after = blessed.terminal._CUR_TERM

    if before is None and after is not None:
        # Curses was initialized during this test in the parent process
        test_name = request.node.nodeid
        pytest.fail(
            f"\n{'=' * 70}\n"
            f"CURSES CONTAMINATION DETECTED in parent pytest process!\n"
            f"Test: {test_name}\n"
            f"Terminal kind initialized: {after}\n"
            f"\n"
            f"This test instantiated Terminal() or TestTerminal() in the parent\n"
            f"pytest process instead of within @as_subprocess. This causes curses\n"
            f"to be initialized with a specific terminal kind, which cannot be\n"
            f"changed for the remainder of the test session, breaking later tests!\n"
            f"\n"
            f"FIX: Ensure Terminal() instantiation is within @as_subprocess:\n"
            f"  @as_subprocess\n"
            f"  def child():\n"
            f"      term = TestTerminal(...)\n"
            f"      ...\n"
            f"      assert ..\n"
            f"  child()\n"
            f"{'=' * 70}\n"
        )


@pytest.fixture(params=all_terms_params)
def all_terms(request):
    """Common kind values for all kinds of terminals."""
    return request.param


@pytest.fixture(params=many_lines_params)
def many_lines(request):
    """Various number of lines for screen height."""
    return request.param


@pytest.fixture(params=many_columns_params)
def many_columns(request):
    """Various number of columns for screen width."""
    return request.param