diff --git a/conftest.py b/conftest.py index 3b9444f78c..578b7aac59 100644 --- a/conftest.py +++ b/conftest.py @@ -92,7 +92,7 @@ def monkeysession(request): mpatch.undo() -@pytest.fixture(autouse=True, scope="session") +@pytest.fixture(scope="module") def suppress_path_mangle(monkeysession): """ Disable the path mangling in CCompiler. Workaround for #169. diff --git a/distutils/ccompiler.py b/distutils/ccompiler.py index 5e73e56d02..714f13d8d3 100644 --- a/distutils/ccompiler.py +++ b/distutils/ccompiler.py @@ -4,6 +4,7 @@ for the Distutils compiler abstraction model.""" import os +import pathlib import re import sys import types @@ -969,27 +970,33 @@ def out_extensions(self): return dict.fromkeys(self.src_extensions, self.obj_extension) def _make_out_path(self, output_dir, strip_dir, src_name): - base, ext = os.path.splitext(src_name) - base = self._make_relative(base) + return self._make_out_path_exts( + output_dir, strip_dir, src_name, self.out_extensions + ) + + @classmethod + def _make_out_path_exts(cls, output_dir, strip_dir, src_name, extensions): + r""" + >>> exts = {'.c': '.o'} + >>> CCompiler._make_out_path_exts('.', False, '/foo/bar.c', exts).replace('\\', '/') + './foo/bar.o' + >>> CCompiler._make_out_path_exts('.', True, '/foo/bar.c', exts).replace('\\', '/') + './bar.o' + """ + src = pathlib.PurePath(src_name) + # Ensure base is relative to honor output_dir (python/cpython#37775). + base = cls._make_relative(src) try: - new_ext = self.out_extensions[ext] + new_ext = extensions[src.suffix] except LookupError: - raise UnknownFileError(f"unknown file type '{ext}' (from '{src_name}')") + raise UnknownFileError(f"unknown file type '{src.suffix}' (from '{src}')") if strip_dir: - base = os.path.basename(base) - return os.path.join(output_dir, base + new_ext) + base = pathlib.PurePath(base.name) + return os.path.join(output_dir, base.with_suffix(new_ext)) @staticmethod - def _make_relative(base): - """ - In order to ensure that a filename always honors the - indicated output_dir, make sure it's relative. - Ref python/cpython#37775. - """ - # Chop off the drive - no_drive = os.path.splitdrive(base)[1] - # If abs, chop off leading / - return no_drive[os.path.isabs(no_drive) :] + def _make_relative(base: pathlib.Path): + return base.relative_to(base.anchor) def shared_object_filename(self, basename, strip_dir=False, output_dir=''): assert output_dir is not None diff --git a/distutils/tests/test_ccompiler.py b/distutils/tests/test_ccompiler.py index d23b907cad..7ebfed56be 100644 --- a/distutils/tests/test_ccompiler.py +++ b/distutils/tests/test_ccompiler.py @@ -7,6 +7,8 @@ import pytest +pytestmark = pytest.mark.usefixtures('suppress_path_mangle') + def _make_strs(paths): """