From a9dd05e844e3e508a57f15862199da53328d47ad Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 20 Aug 2023 06:51:43 -0600 Subject: [PATCH] Allow PathLib objects in sources Changes BuilderBase._adjustixes() to try converting the files arguments to path string - in a way that doesn't flip an existing SCons Node back to a string. Unittest for _adjustixes is added to validate. Fixes #4398 Signed-off-by: Mats Wichmann --- CHANGES.txt | 1 + RELEASE.txt | 1 + SCons/Builder.py | 7 +++++++ SCons/BuilderTests.py | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 43 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index db96df0c29..0acebe6a1d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -131,6 +131,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - More tweaking of test framework overview (which is duplicated onto the website, but not in the regular documentation section). - Extend range of recognized Java versions to 20. + - Builder calls now accept PathLike objects in source lists. Fixes #4398. From Jonathon Reinhart: - Fix another instance of `int main()` in CheckLib() causing failures diff --git a/RELEASE.txt b/RELEASE.txt index f72a2a6819..afe095db8e 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -60,6 +60,7 @@ CHANGED/ENHANCED EXISTING FUNCTIONALITY architecture combination. For example, when using VS2022 on arm64, the arm64 native tools are only installed for the 14.3x toolsets. - Extend range of recognized Java versions to 20. +- Builder calls (like Program()) now accept pathlib objects in source lists. FIXES ----- diff --git a/SCons/Builder.py b/SCons/Builder.py index a11524ed69..16b0cc22de 100644 --- a/SCons/Builder.py +++ b/SCons/Builder.py @@ -99,7 +99,9 @@ """ +import os from collections import UserDict, UserList +from contextlib import suppress import SCons.Action import SCons.Debug @@ -479,6 +481,11 @@ def _adjustixes(self, files, pre, suf, ensure_suffix: bool=False): files = [files] for f in files: + # fspath() is to catch PathLike paths. We avoid the simpler + # str(f) so as not to "lose" files that are already Nodes: + # TypeError: expected str, bytes or os.PathLike object, not File + with suppress(TypeError): + f = os.fspath(f) if SCons.Util.is_String(f): f = SCons.Util.adjustixes(f, pre, suf, ensure_suffix) result.append(f) diff --git a/SCons/BuilderTests.py b/SCons/BuilderTests.py index 379d18b030..344eef4709 100644 --- a/SCons/BuilderTests.py +++ b/SCons/BuilderTests.py @@ -658,6 +658,40 @@ def my_emit(env, sources): tgt = builder(my_env, target = None, source = 'f6.zzz')[0] assert tgt.get_internal_path() == 'f6.emit', tgt.get_internal_path() + def test__adjustixes(self) -> None: + """Test the _adjustixes() method""" + from pathlib import Path + + builder = SCons.Builder.Builder() + + # path without suffix should have both added + with self.subTest(): + r = builder._adjustixes('file', 'pre-', '-suf') + self.assertEqual(r, ['pre-file-suf']) + + # path with a suffix should not have one added + with self.subTest(): + r = builder._adjustixes('file.o', 'pre-', '-suf') + self.assertEqual(r, ['pre-file.o']) + + # unless ensure_suffix is True + with self.subTest(): + r = builder._adjustixes('file.o', 'pre-', '-suf', ensure_suffix=True) + self.assertEqual(r, ['pre-file.o-suf']) + + # a PathLike object should be modified + with self.subTest(): + r = builder._adjustixes(Path('file'), 'pre-', '-suf') + self.assertEqual(r, ['pre-file-suf']) + + # make sure a non-str, non-PathLike is just left alone + with self.subTest(): + env = Environment() + mynode = env.fs.File('file') + r = builder._adjustixes(mynode, 'pre-', '-suf') + self.assertEqual(r, [mynode]) + self.assertEqual(r[0].path, 'file') + def test_single_source(self) -> None: """Test Builder with single_source flag set""" def func(target, source, env) -> None: