Skip to content

Commit e790c69

Browse files
dguidoclaude
andcommitted
Upgrade minimum Python version to 3.9
- Update requires-python to >=3.9 in pyproject.toml - Simplify entry points code using Python 3.9+ select() method - Remove Python 3.8 from all CI test matrices - Update documentation to reflect Python 3.9 requirement - Remove outdated version compatibility code - Set ruff target-version to py39 This simplification was prompted by CI issues after the PEP 735 migration, where maintaining Python 3.8 compatibility added unnecessary complexity. Python 3.8 reaches EOL in October 2024. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 347d4b1 commit e790c69

File tree

12 files changed

+198
-1920
lines changed

12 files changed

+198
-1920
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ jobs:
2929
${{ (github.event_name == 'pull_request' && fromJSON('["ubuntu-latest"]'))
3030
|| fromJSON('["ubuntu-latest", "windows-2025"]') }}
3131
python: >-
32-
${{ (github.event_name == 'pull_request' && fromJSON('["3.8", "3.12"]'))
33-
|| fromJSON('["3.8", "3.9", "3.10", "3.11", "3.12"]') }}
32+
${{ (github.event_name == 'pull_request' && fromJSON('["3.9", "3.12"]'))
33+
|| fromJSON('["3.9", "3.10", "3.11", "3.12"]') }}
3434
type: >-
3535
${{ (github.event_name == 'pull_request' &&
3636
fromJSON('["data_dependency", "path_filtering","erc","find_paths","flat","interface",
@@ -39,9 +39,6 @@ jobs:
3939
"printers","slither_config","upgradability", "cli", "dapp", "etherscan", "kspec",
4040
"simil", "truffle"]') }}
4141
exclude:
42-
# Python 3.8 is not available on Windows Server 2025
43-
- os: windows-2025
44-
python: 3.8
4542
# Requires nix
4643
- os: windows-2025
4744
type: dapp

.github/workflows/docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
uses: actions/configure-pages@v5
3434
- uses: actions/setup-python@v5
3535
with:
36-
python-version: '3.8'
36+
python-version: '3.9'
3737
- run: |
3838
pip install uv
3939
uv sync --group dev

.github/workflows/doctor.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,7 @@ jobs:
2323
fail-fast: false
2424
matrix:
2525
os: ["ubuntu-latest", "windows-2025"]
26-
python: ["3.8", "3.9", "3.10", "3.11", "3.12"]
27-
exclude:
28-
# strange failure
29-
- os: windows-2025
30-
python: 3.8
26+
python: ["3.9", "3.10", "3.11", "3.12"]
3127
steps:
3228
- uses: actions/checkout@v5
3329

.github/workflows/test.yml

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,8 @@ jobs:
2626
os: ["ubuntu-latest", "windows-2025"]
2727
type: ["unit", "integration", "tool"]
2828
python: >-
29-
${{ (github.event_name == 'pull_request' && fromJSON('["3.8", "3.12"]'))
30-
|| fromJSON('["3.8", "3.9", "3.10", "3.11", "3.12"]') }}
31-
exclude:
32-
# Python 3.8 is not available on Windows Server 2025
33-
- os: windows-2025
34-
python: 3.8
29+
${{ (github.event_name == 'pull_request' && fromJSON('["3.9", "3.12"]'))
30+
|| fromJSON('["3.9", "3.10", "3.11", "3.12"]') }}
3531
steps:
3632
- uses: actions/checkout@v5
3733
- name: Set up Python ${{ matrix.python }}
@@ -96,7 +92,7 @@ jobs:
9692
uses: ./.github/actions/upload-coverage
9793
# only aggregate test coverage over linux-based tests to avoid any OS-specific filesystem information stored in
9894
# coverage metadata.
99-
if: ${{ matrix.os == 'ubuntu-latest' && matrix.python == '3.8' }}
95+
if: ${{ matrix.os == 'ubuntu-latest' && matrix.python == '3.9' }}
10096

10197
coverage:
10298
needs:
@@ -106,10 +102,10 @@ jobs:
106102

107103
steps:
108104
- uses: actions/checkout@v5
109-
- name: Set up Python 3.8
105+
- name: Set up Python 3.9
110106
uses: actions/setup-python@v5
111107
with:
112-
python-version: 3.8
108+
python-version: 3.9
113109

114110
- run: pip install coverage[toml]
115111

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ slither tests/uninitialized.sol
6868
## How to install
6969

7070
> **Note** <br />
71-
> Slither requires Python 3.8+.
71+
> Slither requires Python 3.9+.
7272
If you're **not** going to use one of the [supported compilation frameworks](https://github.com/crytic/crytic-compile), you need [solc](https://github.com/ethereum/solidity/), the Solidity compiler; we recommend using [solc-select](https://github.com/crytic/solc-select) to conveniently switch between solc versions.
7373

7474
### Using uv

docs/src/tutorials/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Watch Slither's [code walkthrough](https://www.youtube.com/watch?v=EUl3UlYSluU),
1717

1818
## Installation
1919

20-
Slither requires Python >= 3.8. You can install it through pip or by using Docker.
20+
Slither requires Python >= 3.9. You can install it through pip or by using Docker.
2121

2222
Installing Slither through pip:
2323

plugin_example/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
author="Trail of Bits",
88
version="0.0",
99
packages=find_packages(),
10-
python_requires=">=3.8",
10+
python_requires=">=3.9",
1111
install_requires=["slither-analyzer>=0.6.0"],
1212
entry_points={
1313
"slither_analyzer.plugin": "slither my-plugin=slither_my_plugin:make_plugin",

pyproject.toml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ name = "slither-analyzer"
77
version = "0.11.3"
88
description = "Slither is a Solidity and Vyper static analysis framework written in Python 3."
99
readme = "README.md"
10-
requires-python = ">=3.8"
10+
requires-python = ">=3.9"
1111
license = {text = "AGPL-3.0"}
1212
authors = [
1313
{name = "Trail of Bits"},
@@ -22,7 +22,6 @@ classifiers = [
2222
"Intended Audience :: Developers",
2323
"License :: OSI Approved :: GNU Affero General Public License v3",
2424
"Programming Language :: Python :: 3",
25-
"Programming Language :: Python :: 3.8",
2625
"Programming Language :: Python :: 3.9",
2726
"Programming Language :: Python :: 3.10",
2827
"Programming Language :: Python :: 3.11",
@@ -84,8 +83,8 @@ packages = ["slither"]
8483
[tool.ruff]
8584
# Match black's line length
8685
line-length = 100
87-
# Target Python 3.8+ (minimum version required by project)
88-
target-version = "py38"
86+
# Target Python 3.9+ (minimum version required by project)
87+
target-version = "py39"
8988
# Additional exclusions beyond defaults and .gitignore
9089
extend-exclude = [
9190
"docs/",

slither/__main__.py

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -166,23 +166,8 @@ def get_detectors_and_printers() -> Tuple[
166166
printers = [p for p in printers_ if inspect.isclass(p) and issubclass(p, AbstractPrinter)]
167167

168168
# Handle plugins!
169-
# In Python 3.10+, entry_points() accepts a group parameter directly
170-
# In Python 3.8-3.9, we need to use select() or dict lookup
171-
try:
172-
# Try the Python 3.10+ API with group parameter
173-
entry_points = metadata.entry_points(group="slither_analyzer.plugin")
174-
except TypeError:
175-
# Fall back to Python 3.8-3.9 API
176-
eps = metadata.entry_points()
177-
if hasattr(eps, 'select'):
178-
# Python 3.9+ with select method
179-
entry_points = eps.select(group="slither_analyzer.plugin")
180-
elif isinstance(eps, dict):
181-
# Python 3.8 returns a dict
182-
entry_points = eps.get("slither_analyzer.plugin", [])
183-
else:
184-
# Fallback
185-
entry_points = []
169+
# Python 3.9+ has select() method on entry_points()
170+
entry_points = metadata.entry_points().select(group="slither_analyzer.plugin")
186171

187172
for entry_point in entry_points:
188173
make_plugin = entry_point.load()

slither/tools/doctor/checks/paths.py

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,7 @@ def path_is_relative_to(path: Path, relative_to: Path) -> bool:
1313
1414
Compatibility wrapper for Path.is_relative_to
1515
"""
16-
if sys.version_info >= (3, 9, 0):
17-
return path.is_relative_to(relative_to)
18-
19-
path_parts = path.resolve().parts
20-
relative_to_parts = relative_to.resolve().parts
21-
22-
if len(path_parts) < len(relative_to_parts):
23-
return False
24-
25-
for (a, b) in zip(path_parts, relative_to_parts):
26-
if a != b:
27-
return False
28-
29-
return True
16+
return path.is_relative_to(relative_to)
3017

3118

3219
def check_path_config(name: str) -> Tuple[bool, Optional[Path], List[Path]]:

0 commit comments

Comments
 (0)