Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions distutils/cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
import re
import sys
from abc import abstractmethod
from collections.abc import Callable, MutableSequence
from typing import TYPE_CHECKING, Any, ClassVar, TypeVar, overload
from collections.abc import Callable, MutableSequence, Sequence
from typing import TYPE_CHECKING, Any, ClassVar, Literal, TypeVar, overload

from . import _modified, archive_util, dir_util, file_util, util
from ._log import log
Expand Down Expand Up @@ -467,6 +467,20 @@ def move_file(
"""Move a file respecting dry-run flag."""
return file_util.move_file(src, dst, dry_run=self.dry_run)

@overload
def spawn(
self,
cmd: Sequence[bytes | os.PathLike[bytes] | str | os.PathLike[str]],
search_path: Literal[False],
level: int = 1,
) -> None: ...
@overload
def spawn(
self,
cmd: Sequence[bytes | os.PathLike[bytes] | str | os.PathLike[str]],
search_path: Literal[True] = True,
level: int = 1,
) -> None: ...
def spawn(
self, cmd: MutableSequence[str], search_path: bool = True, level: int = 1
) -> None:
Expand Down
28 changes: 25 additions & 3 deletions distutils/compilers/C/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import re
import sys
import warnings
from collections.abc import Callable, Iterable, MutableSequence, Sequence
from collections.abc import Callable, Iterable, Sequence
from typing import (
TYPE_CHECKING,
ClassVar,
Expand Down Expand Up @@ -39,6 +39,8 @@
)

if TYPE_CHECKING:
from subprocess import _ENV

from typing_extensions import TypeAlias, TypeVarTuple, Unpack

_Ts = TypeVarTuple("_Ts")
Expand Down Expand Up @@ -70,7 +72,7 @@ class Compiler:
# dictionary (see below -- used by the 'new_compiler()' factory
# function) -- authors of new compiler interface classes are
# responsible for updating 'compiler_class'!
compiler_type: ClassVar[str] = None # type: ignore[assignment]
compiler_type: ClassVar[str] = None
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will be added back in #368 , but tests currently fails with this due to unused type-ignore


# XXX things not handled by this compiler abstraction model:
# * client can't provide additional options for a compiler,
Expand Down Expand Up @@ -1152,8 +1154,28 @@ def execute(
) -> None:
execute(func, args, msg, self.dry_run)

@overload
def spawn(
self,
cmd: Sequence[bytes | os.PathLike[bytes] | str | os.PathLike[str]],
*,
search_path: Literal[False],
verbose: bool = False,
env: _ENV | None = None,
) -> None: ...
@overload
def spawn(
self,
cmd: Sequence[bytes | str | os.PathLike[str]],
*,
search_path: Literal[True] = True,
verbose: bool = False,
env: _ENV | None = None,
) -> None: ...
def spawn(
self, cmd: MutableSequence[bytes | str | os.PathLike[str]], **kwargs
self,
cmd: Sequence[bytes | os.PathLike[bytes] | str | os.PathLike[str]],
**kwargs,
) -> None:
spawn(cmd, dry_run=self.dry_run, **kwargs)

Expand Down
36 changes: 29 additions & 7 deletions distutils/compilers/C/msvc.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
import subprocess
import unittest.mock as mock
import warnings
from collections.abc import Iterable
from collections.abc import Iterable, Sequence
from typing import Literal, overload

with contextlib.suppress(ImportError):
import winreg
Expand Down Expand Up @@ -95,7 +96,8 @@ def _find_vc2017():
subprocess.CalledProcessError, OSError, UnicodeDecodeError
):
path = (
subprocess.check_output([
subprocess
.check_output([
os.path.join(
root, "Microsoft Visual Studio", "Installer", "vswhere.exe"
),
Expand Down Expand Up @@ -557,14 +559,34 @@ def link(
else:
log.debug("skipping %s (up-to-date)", output_filename)

def spawn(self, cmd):
@overload # type: ignore[override] # env param not available
def spawn(
self,
cmd: Sequence[bytes | os.PathLike[bytes] | str | os.PathLike[str]],
*,
search_path: Literal[False],
verbose: bool = False,
) -> None: ...
@overload
def spawn(
self,
cmd: Sequence[bytes | str | os.PathLike[str]],
*,
search_path: Literal[True] = True,
verbose: bool = False,
) -> None: ...
def spawn(
self,
cmd: Sequence[bytes | os.PathLike[bytes] | str | os.PathLike[str]],
**kwargs,
):
env = dict(os.environ, PATH=self._paths)
with self._fallback_spawn(cmd, env) as fallback:
return super().spawn(cmd, env=env)
with self._fallback_spawn(cmd, env, **kwargs) as fallback:
return super().spawn(cmd, env=env, **kwargs)
return fallback.value

@contextlib.contextmanager
def _fallback_spawn(self, cmd, env):
def _fallback_spawn(self, cmd, env, **kwargs):
"""
Discovered in pypa/distutils#15, some tools monkeypatch the compiler,
so the 'env' kwarg causes a TypeError. Detect this condition and
Expand All @@ -580,7 +602,7 @@ def _fallback_spawn(self, cmd, env):
return
warnings.warn("Fallback spawn triggered. Please update distutils monkeypatch.")
with mock.patch.dict('os.environ', env):
bag.value = super().spawn(cmd)
bag.value = super().spawn(cmd, **kwargs)

# -- Miscellaneous methods -----------------------------------------
# These are all used by the 'gen_lib_options() function, in
Expand Down
3 changes: 2 additions & 1 deletion distutils/compilers/C/tests/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ def c_file(tmp_path):
all_headers = gen_headers + plat_headers
headers = '\n'.join(f'#include <{header}>\n' for header in all_headers)
payload = (
textwrap.dedent(
textwrap
.dedent(
"""
#headers
void PyInit_foo(void) {}
Expand Down
24 changes: 20 additions & 4 deletions distutils/spawn.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
import subprocess
import sys
import warnings
from collections.abc import Mapping, MutableSequence
from typing import TYPE_CHECKING, TypeVar, overload
from collections.abc import Mapping, Sequence
from typing import TYPE_CHECKING, Literal, TypeVar, overload

from ._log import log
from .debug import DEBUG
Expand Down Expand Up @@ -52,8 +52,24 @@ def _resolve(env: _MappingT | None) -> _MappingT | os._Environ[str]:
return os.environ if env is None else env


@overload
def spawn(
cmd: Sequence[bytes | os.PathLike[bytes] | str | os.PathLike[str]],
search_path: Literal[False],
verbose: bool = False,
dry_run: bool = False,
env: _ENV | None = None,
) -> None: ...
@overload
def spawn(
cmd: Sequence[bytes | str | os.PathLike[str]],
search_path: Literal[True] = True,
verbose: bool = False,
dry_run: bool = False,
env: _ENV | None = None,
) -> None: ...
def spawn(
cmd: MutableSequence[bytes | str | os.PathLike[str]],
cmd: Sequence[bytes | os.PathLike[bytes] | str | os.PathLike[str]],
search_path: bool = True,
verbose: bool = False,
dry_run: bool = False,
Expand Down Expand Up @@ -81,7 +97,7 @@ def spawn(
if search_path:
executable = shutil.which(cmd[0])
if executable is not None:
cmd[0] = executable
cmd = [executable, *cmd[1:]]

try:
subprocess.check_call(cmd, env=_inject_macos_ver(env))
Expand Down
Loading