From fa6e2183cdc2d09db9b18f1cb9619116f104dd0e Mon Sep 17 00:00:00 2001 From: Mridul Seth Date: Thu, 29 Feb 2024 13:07:44 +0530 Subject: [PATCH 1/7] ENH: Extension should be able to accept PathLike sources objects --- distutils/extension.py | 11 ++++++++--- distutils/tests/test_extension.py | 5 ++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/distutils/extension.py b/distutils/extension.py index 8f186b72..2d6950fe 100644 --- a/distutils/extension.py +++ b/distutils/extension.py @@ -26,7 +26,7 @@ class Extension: name : string the full name of the extension, including any packages -- ie. *not* a filename or pathname, but Python dotted name - sources : [string] + sources : [string | os.PathLike] list of source filenames, relative to the distribution root (where the setup script lives), in Unix form (slash-separated) for portability. Source files may be C, C++, SWIG (.i), @@ -106,8 +106,13 @@ def __init__( ): if not isinstance(name, str): raise AssertionError("'name' must be a string") - if not (isinstance(sources, list) and all(isinstance(v, str) for v in sources)): - raise AssertionError("'sources' must be a list of strings") + if not ( + isinstance(sources, list) + and all(isinstance(v, (str, os.PathLike)) for v in sources) + ): + raise AssertionError( + "'sources' must be a list of strings or PathLike objects." + ) self.name = name self.sources = sources diff --git a/distutils/tests/test_extension.py b/distutils/tests/test_extension.py index 297ae44b..3fbea21e 100644 --- a/distutils/tests/test_extension.py +++ b/distutils/tests/test_extension.py @@ -2,6 +2,7 @@ import os import warnings +from pathlib import Path from distutils.extension import read_setup_file, Extension @@ -68,13 +69,15 @@ def test_extension_init(self): assert ext.name == 'name' # the second argument, which is the list of files, must - # be a list of strings + # be a list of strings or PathLike objects with pytest.raises(AssertionError): Extension('name', 'file') with pytest.raises(AssertionError): Extension('name', ['file', 1]) ext = Extension('name', ['file1', 'file2']) assert ext.sources == ['file1', 'file2'] + ext = Extension('name', [Path('file1'), Path('file2')]) + assert ext.sources == ['file1', 'file2'] # others arguments have defaults for attr in ( From 45a232ab88198c488bcb0abf0acb9bfd1ecb518c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 2 Mar 2024 16:42:03 -0500 Subject: [PATCH 2/7] Adjust expectation to match behavior. --- distutils/tests/test_extension.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distutils/tests/test_extension.py b/distutils/tests/test_extension.py index 3fbea21e..9a537873 100644 --- a/distutils/tests/test_extension.py +++ b/distutils/tests/test_extension.py @@ -77,7 +77,7 @@ def test_extension_init(self): ext = Extension('name', ['file1', 'file2']) assert ext.sources == ['file1', 'file2'] ext = Extension('name', [Path('file1'), Path('file2')]) - assert ext.sources == ['file1', 'file2'] + assert ext.sources == [Path('file1'), Path('file2')] # others arguments have defaults for attr in ( From 9cc0c93cf19dfbb737a3ae96c08034203aee0a88 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 2 Mar 2024 16:45:05 -0500 Subject: [PATCH 3/7] For consistency, ensure Extension.sources is always a pathlib.Path object and adjust expectations in tests. --- distutils/extension.py | 3 ++- distutils/tests/test_build_ext.py | 3 ++- distutils/tests/test_extension.py | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/distutils/extension.py b/distutils/extension.py index 2d6950fe..3f950d5a 100644 --- a/distutils/extension.py +++ b/distutils/extension.py @@ -4,6 +4,7 @@ modules in setup scripts.""" import os +import pathlib import warnings # This class is really only used by the "build_ext" command, so it might @@ -115,7 +116,7 @@ def __init__( ) self.name = name - self.sources = sources + self.sources = list(map(pathlib.Path, sources)) self.include_dirs = include_dirs or [] self.define_macros = define_macros or [] self.undef_macros = undef_macros or [] diff --git a/distutils/tests/test_build_ext.py b/distutils/tests/test_build_ext.py index ae66bc4e..7e8a4ddb 100644 --- a/distutils/tests/test_build_ext.py +++ b/distutils/tests/test_build_ext.py @@ -4,6 +4,7 @@ import textwrap import site import contextlib +import pathlib import platform import tempfile import importlib @@ -335,7 +336,7 @@ def test_get_source_files(self): dist = Distribution({'name': 'xx', 'ext_modules': modules}) cmd = self.build_ext(dist) cmd.ensure_finalized() - assert cmd.get_source_files() == ['xxx'] + assert cmd.get_source_files() == [pathlib.Path('xxx')] def test_unicode_module_names(self): modules = [ diff --git a/distutils/tests/test_extension.py b/distutils/tests/test_extension.py index 9a537873..023c7f9f 100644 --- a/distutils/tests/test_extension.py +++ b/distutils/tests/test_extension.py @@ -75,7 +75,7 @@ def test_extension_init(self): with pytest.raises(AssertionError): Extension('name', ['file', 1]) ext = Extension('name', ['file1', 'file2']) - assert ext.sources == ['file1', 'file2'] + assert ext.sources == [Path('file1'), Path('file2')] ext = Extension('name', [Path('file1'), Path('file2')]) assert ext.sources == [Path('file1'), Path('file2')] From c489cdc9ac46aeab6f94e3f510c50ac3983782a5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 2 Mar 2024 20:53:25 -0500 Subject: [PATCH 4/7] When computing input_opt, ensure src is a string (when it could be a pathlib Path). --- distutils/_msvccompiler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/distutils/_msvccompiler.py b/distutils/_msvccompiler.py index 4f081c7e..8c6fb5b5 100644 --- a/distutils/_msvccompiler.py +++ b/distutils/_msvccompiler.py @@ -367,9 +367,9 @@ def compile( # noqa: C901 src = os.path.abspath(src) if ext in self._c_extensions: - input_opt = "/Tc" + src + input_opt = "/Tc" + str(src) elif ext in self._cpp_extensions: - input_opt = "/Tp" + src + input_opt = "/Tp" + str(src) add_cpp_opts = True elif ext in self._rc_extensions: # compile .RC to .RES file From f2a85c1c290f75415c9df7dba473756ee62f8581 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 2 Mar 2024 21:47:38 -0500 Subject: [PATCH 5/7] In filelist, allow for self.files to be pathlib objects. --- distutils/filelist.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distutils/filelist.py b/distutils/filelist.py index 32057626..d0ad54ab 100644 --- a/distutils/filelist.py +++ b/distutils/filelist.py @@ -251,7 +251,7 @@ def exclude_pattern(self, pattern, anchor=1, prefix=None, is_regex=0): pattern_re = translate_pattern(pattern, anchor, prefix, is_regex) self.debug_print("exclude_pattern: applying regex r'%s'" % pattern_re.pattern) for i in range(len(self.files) - 1, -1, -1): - if pattern_re.search(self.files[i]): + if pattern_re.search(str(self.files[i])): self.debug_print(" removing " + self.files[i]) del self.files[i] files_found = True From 3debdcc4bcf9904457c9154694b2fcbd1f773886 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 19 Jul 2024 16:21:30 -0400 Subject: [PATCH 6/7] Simply accept pathlib objects and convert them early for compatibilty with upstream. --- distutils/_msvccompiler.py | 4 ++-- distutils/extension.py | 3 +-- distutils/filelist.py | 2 +- distutils/tests/test_build_ext.py | 3 +-- distutils/tests/test_extension.py | 4 ++-- 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/distutils/_msvccompiler.py b/distutils/_msvccompiler.py index 8c6fb5b5..4f081c7e 100644 --- a/distutils/_msvccompiler.py +++ b/distutils/_msvccompiler.py @@ -367,9 +367,9 @@ def compile( # noqa: C901 src = os.path.abspath(src) if ext in self._c_extensions: - input_opt = "/Tc" + str(src) + input_opt = "/Tc" + src elif ext in self._cpp_extensions: - input_opt = "/Tp" + str(src) + input_opt = "/Tp" + src add_cpp_opts = True elif ext in self._rc_extensions: # compile .RC to .RES file diff --git a/distutils/extension.py b/distutils/extension.py index 3f950d5a..6b195598 100644 --- a/distutils/extension.py +++ b/distutils/extension.py @@ -4,7 +4,6 @@ modules in setup scripts.""" import os -import pathlib import warnings # This class is really only used by the "build_ext" command, so it might @@ -116,7 +115,7 @@ def __init__( ) self.name = name - self.sources = list(map(pathlib.Path, sources)) + self.sources = list(map(os.fspath, sources)) self.include_dirs = include_dirs or [] self.define_macros = define_macros or [] self.undef_macros = undef_macros or [] diff --git a/distutils/filelist.py b/distutils/filelist.py index d0ad54ab..32057626 100644 --- a/distutils/filelist.py +++ b/distutils/filelist.py @@ -251,7 +251,7 @@ def exclude_pattern(self, pattern, anchor=1, prefix=None, is_regex=0): pattern_re = translate_pattern(pattern, anchor, prefix, is_regex) self.debug_print("exclude_pattern: applying regex r'%s'" % pattern_re.pattern) for i in range(len(self.files) - 1, -1, -1): - if pattern_re.search(str(self.files[i])): + if pattern_re.search(self.files[i]): self.debug_print(" removing " + self.files[i]) del self.files[i] files_found = True diff --git a/distutils/tests/test_build_ext.py b/distutils/tests/test_build_ext.py index 7e8a4ddb..ae66bc4e 100644 --- a/distutils/tests/test_build_ext.py +++ b/distutils/tests/test_build_ext.py @@ -4,7 +4,6 @@ import textwrap import site import contextlib -import pathlib import platform import tempfile import importlib @@ -336,7 +335,7 @@ def test_get_source_files(self): dist = Distribution({'name': 'xx', 'ext_modules': modules}) cmd = self.build_ext(dist) cmd.ensure_finalized() - assert cmd.get_source_files() == [pathlib.Path('xxx')] + assert cmd.get_source_files() == ['xxx'] def test_unicode_module_names(self): modules = [ diff --git a/distutils/tests/test_extension.py b/distutils/tests/test_extension.py index 023c7f9f..3fbea21e 100644 --- a/distutils/tests/test_extension.py +++ b/distutils/tests/test_extension.py @@ -75,9 +75,9 @@ def test_extension_init(self): with pytest.raises(AssertionError): Extension('name', ['file', 1]) ext = Extension('name', ['file1', 'file2']) - assert ext.sources == [Path('file1'), Path('file2')] + assert ext.sources == ['file1', 'file2'] ext = Extension('name', [Path('file1'), Path('file2')]) - assert ext.sources == [Path('file1'), Path('file2')] + assert ext.sources == ['file1', 'file2'] # others arguments have defaults for attr in ( From a74d28937598eab507a4a6de9e143a4d59bad281 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 20 Jul 2024 18:40:07 -0400 Subject: [PATCH 7/7] Use simple import --- distutils/tests/test_extension.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/distutils/tests/test_extension.py b/distutils/tests/test_extension.py index c5219d7b..73370996 100644 --- a/distutils/tests/test_extension.py +++ b/distutils/tests/test_extension.py @@ -1,8 +1,8 @@ """Tests for distutils.extension.""" import os +import pathlib import warnings -from pathlib import Path from distutils.extension import Extension, read_setup_file @@ -77,7 +77,7 @@ def test_extension_init(self): Extension('name', ['file', 1]) ext = Extension('name', ['file1', 'file2']) assert ext.sources == ['file1', 'file2'] - ext = Extension('name', [Path('file1'), Path('file2')]) + ext = Extension('name', [pathlib.Path('file1'), pathlib.Path('file2')]) assert ext.sources == ['file1', 'file2'] # others arguments have defaults