aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/setuptools/_distutils/tests/test_spawn.py
blob: 3b9fc926f6ffc41673630fbf5775e6f4ad638b18 (about) (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
"""Tests for distutils.spawn."""

import os
import stat
import sys
import unittest.mock as mock
from distutils.errors import DistutilsExecError
from distutils.spawn import find_executable, spawn
from distutils.tests import support

import path
import pytest
from test.support import unix_shell

from .compat import py39 as os_helper


class TestSpawn(support.TempdirManager):
    @pytest.mark.skipif("os.name not in ('nt', 'posix')")
    def test_spawn(self):
        tmpdir = self.mkdtemp()

        # creating something executable
        # through the shell that returns 1
        if sys.platform != 'win32':
            exe = os.path.join(tmpdir, 'foo.sh')
            self.write_file(exe, f'#!{unix_shell}\nexit 1')
        else:
            exe = os.path.join(tmpdir, 'foo.bat')
            self.write_file(exe, 'exit 1')

        os.chmod(exe, 0o777)
        with pytest.raises(DistutilsExecError):
            spawn([exe])

        # now something that works
        if sys.platform != 'win32':
            exe = os.path.join(tmpdir, 'foo.sh')
            self.write_file(exe, f'#!{unix_shell}\nexit 0')
        else:
            exe = os.path.join(tmpdir, 'foo.bat')
            self.write_file(exe, 'exit 0')

        os.chmod(exe, 0o777)
        spawn([exe])  # should work without any error

    def test_find_executable(self, tmp_path):
        program_path = self._make_executable(tmp_path, '.exe')
        program = program_path.name
        program_noeext = program_path.with_suffix('').name
        filename = str(program_path)
        tmp_dir = path.Path(tmp_path)

        # test path parameter
        rv = find_executable(program, path=tmp_dir)
        assert rv == filename

        if sys.platform == 'win32':
            # test without ".exe" extension
            rv = find_executable(program_noeext, path=tmp_dir)
            assert rv == filename

        # test find in the current directory
        with tmp_dir:
            rv = find_executable(program)
            assert rv == program

        # test non-existent program
        dont_exist_program = "dontexist_" + program
        rv = find_executable(dont_exist_program, path=tmp_dir)
        assert rv is None

        # PATH='': no match, except in the current directory
        with os_helper.EnvironmentVarGuard() as env:
            env['PATH'] = ''
            with (
                mock.patch(
                    'distutils.spawn.os.confstr', return_value=tmp_dir, create=True
                ),
                mock.patch('distutils.spawn.os.defpath', tmp_dir),
            ):
                rv = find_executable(program)
                assert rv is None

                # look in current directory
                with tmp_dir:
                    rv = find_executable(program)
                    assert rv == program

        # PATH=':': explicitly looks in the current directory
        with os_helper.EnvironmentVarGuard() as env:
            env['PATH'] = os.pathsep
            with (
                mock.patch('distutils.spawn.os.confstr', return_value='', create=True),
                mock.patch('distutils.spawn.os.defpath', ''),
            ):
                rv = find_executable(program)
                assert rv is None

                # look in current directory
                with tmp_dir:
                    rv = find_executable(program)
                    assert rv == program

        # missing PATH: test os.confstr("CS_PATH") and os.defpath
        with os_helper.EnvironmentVarGuard() as env:
            env.pop('PATH', None)

            # without confstr
            with (
                mock.patch(
                    'distutils.spawn.os.confstr', side_effect=ValueError, create=True
                ),
                mock.patch('distutils.spawn.os.defpath', tmp_dir),
            ):
                rv = find_executable(program)
                assert rv == filename

            # with confstr
            with (
                mock.patch(
                    'distutils.spawn.os.confstr', return_value=tmp_dir, create=True
                ),
                mock.patch('distutils.spawn.os.defpath', ''),
            ):
                rv = find_executable(program)
                assert rv == filename

    @staticmethod
    def _make_executable(tmp_path, ext):
        # Give the temporary program a suffix regardless of platform.
        # It's needed on Windows and not harmful on others.
        program = tmp_path.joinpath('program').with_suffix(ext)
        program.write_text("", encoding='utf-8')
        program.chmod(stat.S_IXUSR)
        return program

    def test_spawn_missing_exe(self):
        with pytest.raises(DistutilsExecError) as ctx:
            spawn(['does-not-exist'])
        assert "command 'does-not-exist' failed" in str(ctx.value)