summaryrefslogtreecommitdiffstats
path: root/tests/languages/python_test.py
blob: c419ad621b97aecf4bd694486001aa62b8ebd9af (plain)
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
140
141
142
143
import os.path
import sys
from unittest import mock

import pytest

import pre_commit.constants as C
from pre_commit.envcontext import envcontext
from pre_commit.languages import python
from pre_commit.prefix import Prefix


def test_read_pyvenv_cfg(tmpdir):
    pyvenv_cfg = tmpdir.join('pyvenv.cfg')
    pyvenv_cfg.write(
        '# I am a comment\n'
        '\n'
        'foo = bar\n'
        'version-info=123\n',
    )
    expected = {'foo': 'bar', 'version-info': '123'}
    assert python._read_pyvenv_cfg(pyvenv_cfg) == expected


def test_norm_version_expanduser():
    home = os.path.expanduser('~')
    if os.name == 'nt':  # pragma: nt cover
        path = r'~\python343'
        expected_path = fr'{home}\python343'
    else:  # pragma: nt no cover
        path = '~/.pyenv/versions/3.4.3/bin/python'
        expected_path = f'{home}/.pyenv/versions/3.4.3/bin/python'
    result = python.norm_version(path)
    assert result == expected_path


def test_norm_version_of_default_is_sys_executable():
    assert python.norm_version('default') == os.path.realpath(sys.executable)


@pytest.mark.parametrize('v', ('python3.6', 'python3', 'python'))
def test_sys_executable_matches(v):
    with mock.patch.object(sys, 'version_info', (3, 6, 7)):
        assert python._sys_executable_matches(v)


@pytest.mark.parametrize('v', ('notpython', 'python3.x'))
def test_sys_executable_matches_does_not_match(v):
    with mock.patch.object(sys, 'version_info', (3, 6, 7)):
        assert not python._sys_executable_matches(v)


@pytest.mark.parametrize(
    ('exe', 'realpath', 'expected'), (
        ('/usr/bin/python3', '/usr/bin/python3.7', 'python3'),
        ('/usr/bin/python', '/usr/bin/python3.7', 'python3.7'),
        ('/usr/bin/python', '/usr/bin/python', None),
        ('/usr/bin/python3.6m', '/usr/bin/python3.6m', 'python3.6m'),
        ('v/bin/python', 'v/bin/pypy', 'pypy'),
    ),
)
def test_find_by_sys_executable(exe, realpath, expected):
    with mock.patch.object(sys, 'executable', exe):
        with mock.patch.object(os.path, 'realpath', return_value=realpath):
            with mock.patch.object(python, 'find_executable', lambda x: x):
                assert python._find_by_sys_executable() == expected


@pytest.fixture
def python_dir(tmpdir):
    with tmpdir.as_cwd():
        prefix = tmpdir.join('prefix').ensure_dir()
        prefix.join('setup.py').write('import setuptools; setuptools.setup()')
        prefix = Prefix(str(prefix))
        yield prefix, tmpdir


def test_healthy_default_creator(python_dir):
    prefix, tmpdir = python_dir

    python.install_environment(prefix, C.DEFAULT, ())

    # should be healthy right after creation
    assert python.healthy(prefix, C.DEFAULT) is True

    # even if a `types.py` file exists, should still be healthy
    tmpdir.join('types.py').ensure()
    assert python.healthy(prefix, C.DEFAULT) is True


def test_healthy_venv_creator(python_dir):
    # venv creator produces slightly different pyvenv.cfg
    prefix, tmpdir = python_dir

    with envcontext((('VIRTUALENV_CREATOR', 'venv'),)):
        python.install_environment(prefix, C.DEFAULT, ())

    assert python.healthy(prefix, C.DEFAULT) is True


def test_unhealthy_python_goes_missing(python_dir):
    prefix, tmpdir = python_dir

    python.install_environment(prefix, C.DEFAULT, ())

    exe_name = 'python' if sys.platform != 'win32' else 'python.exe'
    py_exe = prefix.path(python.bin_dir('py_env-default'), exe_name)
    os.remove(py_exe)

    assert python.healthy(prefix, C.DEFAULT) is False


def test_unhealthy_with_version_change(python_dir):
    prefix, tmpdir = python_dir

    python.install_environment(prefix, C.DEFAULT, ())

    with open(prefix.path('py_env-default/pyvenv.cfg'), 'w') as f:
        f.write('version_info = 1.2.3\n')

    assert python.healthy(prefix, C.DEFAULT) is False


def test_unhealthy_system_version_changes(python_dir):
    prefix, tmpdir = python_dir

    python.install_environment(prefix, C.DEFAULT, ())

    with open(prefix.path('py_env-default/pyvenv.cfg'), 'a') as f:
        f.write('base-executable = /does/not/exist\n')

    assert python.healthy(prefix, C.DEFAULT) is False


def test_unhealthy_old_virtualenv(python_dir):
    prefix, tmpdir = python_dir

    python.install_environment(prefix, C.DEFAULT, ())

    # simulate "old" virtualenv by deleting this file
    os.remove(prefix.path('py_env-default/pyvenv.cfg'))

    assert python.healthy(prefix, C.DEFAULT) is False