summaryrefslogtreecommitdiff
path: root/setuptools/_distutils/tests/test_spawn.py
blob: 08a34ee2b8e35af6e9f9dbe6d983449a88a4a32c (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
"""Tests for distutils.spawn."""
import os
import stat
import sys
import unittest.mock as mock

from test.support import unix_shell

import path

from . import py38compat as os_helper

from distutils.spawn import find_executable
from distutils.spawn import spawn
from distutils.errors import DistutilsExecError
from distutils.tests import support
import pytest


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, '#!%s\nexit 1' % unix_shell)
        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, '#!%s\nexit 0' % unix_shell)
        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_noeext = 'program'
        # Give the temporary program an ".exe" suffix for all.
        # It's needed on Windows and not harmful on other platforms.
        program = program_noeext + ".exe"

        program_path = tmp_path / program
        program_path.write_text("")
        program_path.chmod(stat.S_IXUSR)
        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

    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)