Skip to content

Commit 29dde6b

Browse files
authored
Merge branch 'master' into NinjaAlwaysBuild
2 parents 1794207 + 230f614 commit 29dde6b

31 files changed

Lines changed: 262 additions & 249 deletions

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,6 @@ python -m mypy SCons/ # type check
9494
- Git commits signed off (`git commit -s`). Add `Assisted-by:` to message for AI-generated changes.
9595
- Version in `SCons/__init__.py` (`__version__`) - automatically generated, do not edit.
9696
- CI: GitHub Actions (`runtest.yml` - test suite; `scons-package.yml` — packaging), AppVeyor (Windows, legacy).
97-
- Python >= 3.7 required.
97+
- Python >= 3.9 required.
9898
- Config log for `Configure()` lives at `config.log` in the build dir.
9999
- `.sconsign.dblite` persists across builds; deleting build dirs from disk doesn't clear sconsign entries.

CHANGES.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,17 @@ NOTE: The 4.0.0 release of SCons dropped Python 2.7 support. Use 3.1.2 if
88
Python 2.7 support is required (but note old SCons releases are unsupported).
99
NOTE: Since SCons 4.3.0, Python 3.6.0 or above is required.
1010
NOTE: Since SCons 4.9.0, Python 3.7.0 or above is required.
11-
NOTE: The last release to support Python 3.7 or Python 3.8 is 4.11.0.
11+
NOTE: The last release to support Python 3.7 or Python 3.8 is 4.11.1
1212

1313
RELEASE VERSION/DATE TO BE FILLED IN LATER
1414

15+
From Thaddeus Crews:
16+
- ty: Initial support setup within `pyproject.toml`.
17+
- Removed Python 3.7 & 3.8 support.
18+
19+
20+
RELEASE 4.11.1 - Mon, 26 Aug 2026 21:16:00 -0700
21+
1522
From Mats Wichmann:
1623
- Undo, for now, the 4.11.0 change (from PR 4875) to read a
1724
saved-Variables file using a File node. There were unanticipated

README-SF.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ version at the SCons download page:
4747
Execution Requirements
4848
======================
4949

50-
Running SCons requires Python 3.7 or higher. There should be no other
50+
Running SCons requires Python 3.9 or higher. There should be no other
5151
dependencies or requirements to run standard SCons.
5252

5353
The last release to support Python 3.7 or Python 3.8 is 4.11.0.
@@ -613,4 +613,3 @@ many contributors, including but not at all limited to:
613613
\... and many others.
614614

615615
Copyright (c) 2001 - 2026 The SCons Foundation
616-

README-local

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ scons-local package, or any SCons package, at the SCons download page:
4343
EXECUTION REQUIREMENTS
4444
======================
4545

46-
Running SCons requires Python 3.7 or higher. There should be no other
46+
Running SCons requires Python 3.9 or higher. There should be no other
4747
dependencies or requirements to run standard SCons.
4848

4949
The last release to support Python 3.7 or Python 3.8 is 4.11.0.

README-package.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ https://scons.org/documentation.html.
8080
Execution Requirements
8181
======================
8282

83-
Running SCons requires Python 3.7 or higher. There should be no other
83+
Running SCons requires Python 3.9 or higher. There should be no other
8484
dependencies or requirements to run standard SCons.
8585

8686
The last release to support Python 3.7 or Python 3.8 is 4.11.0.
@@ -196,4 +196,3 @@ Check the SCons web site at https://scons.org
196196

197197

198198
Copyright (c) 2001 - 2026 The SCons Foundation
199-

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ is the latest version at the
8383
Execution Requirements
8484
======================
8585

86-
Running SCons requires Python 3.7 or higher. There should be no other
86+
Running SCons requires Python 3.9 or higher. There should be no other
8787
dependencies or requirements to run standard SCons.
8888

8989
The last release to support Python 3.7 or Python 3.8 is 4.11.0.

RELEASE.txt

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ Past official release announcements appear at:
66

77
==================================================================
88

9-
A new SCons release, 4.11.0, is now available on the SCons download page:
9+
A new SCons release, NEXT_RELEASE, is now available on the SCons download page:
1010

1111
https://scons.org/pages/download.html
1212

1313

14-
Here is a summary of the changes since 4.10.1:
14+
Here is a summary of the changes since PREVIOUS_RELEASE:
1515

1616
NEW FUNCTIONALITY
1717
-----------------
@@ -23,6 +23,13 @@ DEPRECATED FUNCTIONALITY
2323

2424
- List anything that's been deprecated since the last release
2525

26+
REMOVED FUNCTIONALITY
27+
------------------------
28+
29+
- List anything that's been outright removed since the last release
30+
31+
- Removed Python 3.7 & 3.8 support.
32+
2633
CHANGED/ENHANCED EXISTING FUNCTIONALITY
2734
---------------------------------------
2835

@@ -64,10 +71,12 @@ DOCUMENTATION
6471
DEVELOPMENT
6572
-----------
6673

67-
- List visible changes in the way SCons is developed
74+
- List visible changes in the way SCons is
75+
76+
- ty: Initial support setup within `pyproject.toml`.
6877

6978
Thanks to the following contributors listed below for their contributions to this release.
7079
==========================================================================================
7180
.. code-block:: text
7281

73-
git shortlog --no-merges -ns 4.10.1..HEAD
82+
git shortlog --no-merges -ns PREVIOUS_RELEASE..HEAD

ReleaseConfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@
3131
# If the release type is not 'final', the patchlevel is set to the
3232
# release date. This value is mandatory and must be present in this file.
3333
#version_tuple = (2, 2, 0, 'final', 0)
34-
version_tuple = (4, 12, 0, 'a', 0)
34+
version_tuple = (4, 11, 2, 'a', 0)
3535

3636
# Python versions prior to unsupported_python_version cause a fatal error
3737
# when that version is used. Python versions prior to deprecate_python_version
3838
# cause a warning to be issued (assuming it's not disabled). These values are
3939
# mandatory and must be present in the configuration file.
40-
unsupported_python_version = (3, 7, 0)
40+
unsupported_python_version = (3, 9, 0)
4141
deprecated_python_version = (3, 9, 0)
4242

4343
# If release_date is (yyyy, mm, dd, hh, mm, ss), that is used as the release

SCons/ActionTests.py

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1553,8 +1553,6 @@ def LocalFunc() -> None:
15531553

15541554
# Since the python bytecode has per version differences, we need different expected results per version
15551555
func_matches = {
1556-
(3, 7): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
1557-
(3, 8): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
15581556
(3, 9): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
15591557
(3, 10): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
15601558
(3, 11): bytearray(b'0, 0, 0, 0,(),(),(\x97\x00d\x00S\x00),(),()'),
@@ -1735,8 +1733,6 @@ def LocalFunc() -> None:
17351733
pass
17361734

17371735
func_matches = {
1738-
(3, 7): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
1739-
(3, 8): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
17401736
(3, 9): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
17411737
(3, 10): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
17421738
(3, 11): bytearray(b'0, 0, 0, 0,(),(),(\x97\x00d\x00S\x00),(),()'),
@@ -1748,8 +1744,6 @@ def LocalFunc() -> None:
17481744
}
17491745

17501746
meth_matches = {
1751-
(3, 7): bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'),
1752-
(3, 8): bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'),
17531747
(3, 9): bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'),
17541748
(3, 10): bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'),
17551749
(3, 11): bytearray(b'1, 1, 0, 0,(),(),(\x97\x00d\x00S\x00),(),()'),
@@ -1991,8 +1985,6 @@ def LocalFunc() -> None:
19911985
pass
19921986

19931987
func_matches = {
1994-
(3, 7): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
1995-
(3, 8): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
19961988
(3, 9): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
19971989
(3, 10): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
19981990
(3, 11): bytearray(b'0, 0, 0, 0,(),(),(\x97\x00d\x00S\x00),(),()'),
@@ -2055,8 +2047,6 @@ def LocalFunc() -> None:
20552047
pass
20562048

20572049
matches = {
2058-
(3, 7): b'd\x00S\x00',
2059-
(3, 8): b'd\x00S\x00',
20602050
(3, 9): b'd\x00S\x00',
20612051
(3, 10): b'd\x00S\x00',
20622052
(3, 11): b'\x97\x00d\x00S\x00',
@@ -2259,8 +2249,6 @@ def func1(a, b, c):
22592249
# we need different expected results per version
22602250
# Note unlike the others, this result is a tuple, use assertIn
22612251
expected = {
2262-
(3, 7): (bytearray(b"3, 3, 0, 0,(),(),(|\x00S\x00),(),()"),),
2263-
(3, 8): (bytearray(b"3, 3, 0, 0,(),(),(|\x00S\x00),(),()"),),
22642252
(3, 9): (bytearray(b"3, 3, 0, 0,(),(),(|\x00S\x00),(),()"),),
22652253
(3, 10): ( # 3.10.1, 3.10.2
22662254
bytearray(b"3, 3, 0, 0,(N.),(),(|\x00S\x00),(),()"),
@@ -2288,12 +2276,6 @@ def test_object_contents(self) -> None:
22882276
# Since the python bytecode has per version differences,
22892277
# we need different expected results per version
22902278
expected = {
2291-
(3, 7): bytearray(
2292-
b"{TestClass:__main__}[[[(<class 'object'>, ()), [(<class '__main__.TestClass'>, (<class 'object'>,))]]]]{{1, 1, 0, 0,(a,b),(a,b),(d\x01|\x00_\x00d\x02|\x00_\x01d\x00S\x00),(),(),2, 2, 0, 0,(),(),(d\x00S\x00),(),()}}{{{a=a,b=b}}}"
2293-
),
2294-
(3, 8): bytearray(
2295-
b"{TestClass:__main__}[[[(<class 'object'>, ()), [(<class '__main__.TestClass'>, (<class 'object'>,))]]]]{{1, 1, 0, 0,(a,b),(a,b),(d\x01|\x00_\x00d\x02|\x00_\x01d\x00S\x00),(),(),2, 2, 0, 0,(),(),(d\x00S\x00),(),()}}{{{a=a,b=b}}}"
2296-
),
22972279
(3, 9): bytearray(
22982280
b"{TestClass:__main__}[[[(<class 'object'>, ()), [(<class '__main__.TestClass'>, (<class 'object'>,))]]]]{{1, 1, 0, 0,(a,b),(a,b),(d\x01|\x00_\x00d\x02|\x00_\x01d\x00S\x00),(),(),2, 2, 0, 0,(),(),(d\x00S\x00),(),()}}{{{a=a,b=b}}}"
22992281
),
@@ -2326,12 +2308,6 @@ def test_code_contents(self) -> None:
23262308

23272309
# Since the python bytecode has per version differences, we need different expected results per version
23282310
expected = {
2329-
(3, 7): bytearray(
2330-
b"0, 0, 0, 0,(Hello, World!),(print),(e\x00d\x00\x83\x01\x01\x00d\x01S\x00)"
2331-
),
2332-
(3, 8): bytearray(
2333-
b"0, 0, 0, 0,(Hello, World!),(print),(e\x00d\x00\x83\x01\x01\x00d\x01S\x00)"
2334-
),
23352311
(3, 9): bytearray(
23362312
b"0, 0, 0, 0,(Hello, World!),(print),(e\x00d\x00\x83\x01\x01\x00d\x01S\x00)"
23372313
),

SCons/CacheDir.py

Lines changed: 12 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -210,44 +210,22 @@ def _mkdir_atomic(self, path: str) -> bool:
210210
return False
211211

212212
try:
213-
# TODO: Python 3.7. See comment below.
214-
# tempdir = tempfile.TemporaryDirectory(dir=os.path.dirname(directory))
215-
tempdir = tempfile.mkdtemp(dir=os.path.dirname(directory))
213+
tempdir = tempfile.TemporaryDirectory(dir=os.path.dirname(directory))
216214
except OSError as e:
217215
msg = "Failed to create cache directory " + path
218216
raise SCons.Errors.SConsEnvironmentError(msg) from e
219217

220-
# TODO: Python 3.7: the context manager raises exception on cleanup
221-
# if the temporary was moved successfully (File Not Found).
222-
# Fixed in 3.8+. In the replacement below we manually clean up if
223-
# the move failed as mkdtemp() does not. TemporaryDirectory's
224-
# cleanup is more sophisitcated so prefer when we can use it.
225-
# self._add_config(tempdir.name)
226-
# with tempdir:
227-
# try:
228-
# os.replace(tempdir.name, directory)
229-
# return True
230-
# except OSError as e:
231-
# # did someone else get there first?
232-
# if os.path.isdir(directory):
233-
# return False # context manager cleans up
234-
# msg = "Failed to create cache directory " + path
235-
# raise SCons.Errors.SConsEnvironmentError(msg) from e
236-
237-
self._add_config(tempdir)
238-
try:
239-
os.replace(tempdir, directory)
240-
return True
241-
except OSError as e:
242-
# did someone else get there first? attempt cleanup.
243-
if os.path.isdir(directory):
244-
try:
245-
shutil.rmtree(tempdir)
246-
except Exception: # we tried, don't worry about it
247-
pass
248-
return False
249-
msg = "Failed to create cache directory " + path
250-
raise SCons.Errors.SConsEnvironmentError(msg) from e
218+
self._add_config(tempdir.name)
219+
with tempdir:
220+
try:
221+
os.replace(tempdir.name, directory)
222+
return True
223+
except OSError as e:
224+
# did someone else get there first?
225+
if os.path.isdir(directory):
226+
return False # context manager cleans up
227+
msg = "Failed to create cache directory " + path
228+
raise SCons.Errors.SConsEnvironmentError(msg) from e
251229

252230
def _readconfig(self, path: str) -> None:
253231
"""Read the cache config from *path*.

0 commit comments

Comments
 (0)