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
10 changes: 5 additions & 5 deletions .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,17 @@ environment:
SCONS_CACHE_MSVC_CONFIG: "true"
matrix:
# Test oldest and newest supported Pythons, and a subset in between.
# Skipping 3.8, 3.10, 3.12 at this time
# Skipping 3.10, 3.12 at this time
- WINPYTHON: "Python313"
- WINPYTHON: "Python311"
- WINPYTHON: "Python39"
- WINPYTHON: "Python37"
- WINPYTHON: "Python38"

# remove sets of build jobs based on criteria below
# to fine tune the number and platforms tested
matrix:
exclude:
# test python 3.7 on Visual Studio 2017 image
# test python 3.8 on Visual Studio 2017 image
- image: Visual Studio 2017
WINPYTHON: "Python313"
- image: Visual Studio 2017
Expand All @@ -59,13 +59,13 @@ matrix:
- image: Visual Studio 2019
WINPYTHON: "Python311"
- image: Visual Studio 2019
WINPYTHON: "Python37"
WINPYTHON: "Python38"

# test python 3.11, 3.13 on Visual Studio 2022 image
- image: Visual Studio 2022
WINPYTHON: "Python39"
- image: Visual Studio 2022
WINPYTHON: "Python37"
WINPYTHON: "Python38"

# Remove some binaries we don't want to be found
# Note this is no longer needed, git-windows bin/ is quite minimal now.
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/runtest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
fail-fast: false
matrix:
cfg: [
{os: 'ubuntu-22.04', py: '3.7'},
{os: 'ubuntu-22.04', py: '3.8'},
{os: 'ubuntu-24.04', py: '3.13'},
]

Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:

- &coverage_jobs
dist: bionic
python: 3.7
python: 3.8
name: coverage
before_script:
- ./.travis/coverage_setup.sh
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ SCons is an open-source software construction tool (build tool) implemented in P
## Building and Running

### Prerequisites
* Python 3.7 or higher.
* Python 3.8 or higher.
* Development dependencies: `python -m pip install -r requirements-dev.txt`

### Running SCons (Development)
Expand Down
3 changes: 3 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ NOTE: The 4.0.0 release of SCons dropped Python 2.7 support. Use 3.1.2 if
Python 2.7 support is required (but note old SCons releases are unsupported).
NOTE: Since SCons 4.3.0, Python 3.6.0 or above is required.
NOTE: Since SCons 4.9.0, Python 3.7.0 or above is required.
NOTE: Since SCons NEXT_RELEASE, Python 3.8.0 or above is required.


RELEASE VERSION/DATE TO BE FILLED IN LATER
Expand All @@ -26,6 +27,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
- Purge vim/emac local variable bloat.
- Implement type hints for Node subclasses.
- Ruff: Handle F401 exclusions more granularly, remove per-file exclusions.
- Removed Python 3.7 support.
- Deprecated Python 3.8 support.

From William Deegan:
- Fix SCons Docbook schema to work with lxml > 5
Expand Down
3 changes: 2 additions & 1 deletion README-SF.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,10 @@ version at the SCons download page:
Execution Requirements
======================

Running SCons requires Python 3.7 or higher. There should be no other
Running SCons requires Python 3.8 or higher. There should be no other
dependencies or requirements to run standard SCons.

The last release to support Python 3.7 was NEXT_RELEASE.
The last release to support Python 3.6 was 4.8.1.
The last release to support Python 3.5 was 4.2.0.

Expand Down
3 changes: 2 additions & 1 deletion README-local
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ scons-local package, or any SCons package, at the SCons download page:
EXECUTION REQUIREMENTS
======================

Running SCons requires Python 3.7 or higher. There should be no other
Running SCons requires Python 3.8 or higher. There should be no other
dependencies or requirements to run standard SCons.

The last release to support Python 3.7 was NEXT_RELEASE.
The last release to support Python 3.6 was 4.8.1.
The last release to support Python 3.5 was 4.2.0.

Expand Down
3 changes: 2 additions & 1 deletion README-package.rst
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,10 @@ https://scons.org/documentation.html.
Execution Requirements
======================

Running SCons requires Python 3.7 or higher. There should be no other
Running SCons requires Python 3.8 or higher. There should be no other
dependencies or requirements to run standard SCons.

The last release to support Python 3.7 was NEXT_RELEASE.
The last release to support Python 3.6 was 4.8.1.
The last release to support Python 3.5 was 4.2.0.

Expand Down
3 changes: 2 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,10 @@ is the latest version at the
Execution Requirements
======================

Running SCons requires Python 3.7 or higher. There should be no other
Running SCons requires Python 3.8 or higher. There should be no other
dependencies or requirements to run standard SCons.

The last release to support Python 3.7 was NEXT_RELEASE.
The last release to support Python 3.6 was 4.8.1.
The last release to support Python 3.5 was 4.2.0.

Expand Down
4 changes: 4 additions & 0 deletions RELEASE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,16 @@ DEPRECATED FUNCTIONALITY

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

- Deprecated Python 3.8 support.

CHANGED/ENHANCED EXISTING FUNCTIONALITY
---------------------------------------

- List modifications to existing features, where the previous behavior
wouldn't actually be considered a bug

- Removed Python 3.7 support.

FIXES
-----

Expand Down
4 changes: 2 additions & 2 deletions ReleaseConfig
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ version_tuple = (4, 10, 2, 'a', 0)
# when that version is used. Python versions prior to deprecate_python_version
# cause a warning to be issued (assuming it's not disabled). These values are
# mandatory and must be present in the configuration file.
unsupported_python_version = (3, 7, 0)
deprecated_python_version = (3, 7, 0)
unsupported_python_version = (3, 8, 0)
deprecated_python_version = (3, 9, 0)

# If release_date is (yyyy, mm, dd, hh, mm, ss), that is used as the release
# date and time. If release_date is (yyyy, mm, dd), it is used for the
Expand Down
34 changes: 0 additions & 34 deletions SCons/ActionTests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1549,7 +1549,6 @@ def LocalFunc() -> None:

# Since the python bytecode has per version differences, we need different expected results per version
func_matches = {
(3, 7): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
(3, 8): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
(3, 9): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
(3, 10): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
Expand Down Expand Up @@ -1730,7 +1729,6 @@ def LocalFunc() -> None:
pass

func_matches = {
(3, 7): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
(3, 8): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
(3, 9): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
(3, 10): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
Expand All @@ -1742,7 +1740,6 @@ def LocalFunc() -> None:
}

meth_matches = {
(3, 7): bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'),
(3, 8): bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'),
(3, 9): bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'),
(3, 10): bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'),
Expand Down Expand Up @@ -1983,7 +1980,6 @@ def LocalFunc() -> None:
pass

func_matches = {
(3, 7): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
(3, 8): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
(3, 9): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
(3, 10): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
Expand Down Expand Up @@ -2046,7 +2042,6 @@ def LocalFunc() -> None:
pass

matches = {
(3, 7): b'd\x00S\x00',
(3, 8): b'd\x00S\x00',
(3, 9): b'd\x00S\x00',
(3, 10): b'd\x00S\x00',
Expand Down Expand Up @@ -2249,7 +2244,6 @@ def func1(a, b, c):
# we need different expected results per version
# Note unlike the others, this result is a tuple, use assertIn
expected = {
(3, 7): (bytearray(b"3, 3, 0, 0,(),(),(|\x00S\x00),(),()"),),
(3, 8): (bytearray(b"3, 3, 0, 0,(),(),(|\x00S\x00),(),()"),),
(3, 9): (bytearray(b"3, 3, 0, 0,(),(),(|\x00S\x00),(),()"),),
(3, 10): ( # 3.10.1, 3.10.2
Expand Down Expand Up @@ -2277,9 +2271,6 @@ def test_object_contents(self) -> None:
# Since the python bytecode has per version differences,
# we need different expected results per version
expected = {
(3, 7): bytearray(
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}}}"
),
(3, 8): bytearray(
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}}}"
),
Expand Down Expand Up @@ -2312,9 +2303,6 @@ def test_code_contents(self) -> None:

# Since the python bytecode has per version differences, we need different expected results per version
expected = {
(3, 7): bytearray(
b"0, 0, 0, 0,(Hello, World!),(print),(e\x00d\x00\x83\x01\x01\x00d\x01S\x00)"
),
(3, 8): bytearray(
b"0, 0, 0, 0,(Hello, World!),(print),(e\x00d\x00\x83\x01\x01\x00d\x01S\x00)"
),
Expand Down Expand Up @@ -2360,9 +2348,6 @@ def mock_subprocess_run(*args, **kwargs):
@mock.patch("subprocess.run", mock_subprocess_run)
def test_scons_subproc_run(self):
"""Test the argument remapping options."""
# set phony Python versions to trigger the logic in scons_subproc_run:
# any version greater than 3.6, really
save_info, sys.version_info = sys.version_info, (3, 11, 1)
env = Environment()
self.assertEqual(scons_subproc_run(env), {"check": False})
with self.subTest():
Expand All @@ -2381,25 +2366,6 @@ def test_scons_subproc_run(self):
{"text": True, "check": False},
)

# 3.7:
sys.version_info = (3, 7, 2)
with self.subTest():
self.assertEqual(
scons_subproc_run(env, capture_output=True),
{"capture_output": True, "check": False},
)
with self.subTest():
self.assertEqual(
scons_subproc_run(env, text=True),
{"check": False, "text": True},
)
with self.subTest():
self.assertEqual(
scons_subproc_run(env, universal_newlines=True),
{"universal_newlines": True, "check": False},
)
sys.version_info = save_info


if __name__ == "__main__":
unittest.main()
46 changes: 12 additions & 34 deletions SCons/CacheDir.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,44 +210,22 @@ def _mkdir_atomic(self, path: str) -> bool:
return False

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

# TODO: Python 3.7: the context manager raises exception on cleanup
# if the temporary was moved successfully (File Not Found).
# Fixed in 3.8+. In the replacement below we manually clean up if
# the move failed as mkdtemp() does not. TemporaryDirectory's
# cleanup is more sophisitcated so prefer when we can use it.
# self._add_config(tempdir.name)
# with tempdir:
# try:
# os.replace(tempdir.name, directory)
# return True
# except OSError as e:
# # did someone else get there first?
# if os.path.isdir(directory):
# return False # context manager cleans up
# msg = "Failed to create cache directory " + path
# raise SCons.Errors.SConsEnvironmentError(msg) from e

self._add_config(tempdir)
try:
os.replace(tempdir, directory)
return True
except OSError as e:
# did someone else get there first? attempt cleanup.
if os.path.isdir(directory):
try:
shutil.rmtree(tempdir)
except Exception: # we tried, don't worry about it
pass
return False
msg = "Failed to create cache directory " + path
raise SCons.Errors.SConsEnvironmentError(msg) from e
self._add_config(tempdir.name)
with tempdir:
try:
os.replace(tempdir.name, directory)
return True
except OSError as e:
# did someone else get there first?
if os.path.isdir(directory):
return False # context manager cleans up
msg = "Failed to create cache directory " + path
raise SCons.Errors.SConsEnvironmentError(msg) from e

def _readconfig(self, path: str) -> None:
"""Read the cache config from *path*.
Expand Down
4 changes: 2 additions & 2 deletions SCons/Script/Main.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@
from SCons import __version__ as SConsVersion

# these define the range of versions SCons supports
minimum_python_version = (3, 7, 0)
deprecated_python_version = (3, 7, 0)
minimum_python_version = (3, 8, 0)
deprecated_python_version = (3, 8, 0)

# ordered list of SConstruct names to look for if there is no -f flag
KNOWN_SCONSTRUCT_NAMES = [
Expand Down
Loading
Loading