Skip to content

Commit 623ec53

Browse files
dguidoclaude
andcommitted
Fix Python 3.9 compatibility and simplify CI wrapper functions
Two major fixes: 1. Fix entry_points API compatibility for Python 3.9 - Python 3.9's metadata.entry_points() returns a dict, not an EntryPoints object - Added conditional handling for both Python 3.9 (dict) and 3.10+ (with .select()) 2. Simplify CI wrapper functions by activating venv directly - Replace complex wrapper functions with simple venv activation - All tools are now in PATH after activation - Fixes solc-select binary path issues - Much simpler and more maintainable approach as suggested by @elopez This resolves CI failures in path_filtering, printers, and slither_config tests. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent ced194c commit 623ec53

File tree

2 files changed

+46
-142
lines changed

2 files changed

+46
-142
lines changed

scripts/ci_test_common.sh

Lines changed: 21 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,126 +1,25 @@
11
#!/usr/bin/env bash
22

33
# Common setup for CI test scripts
4-
# Use UV_RUN if set (for CI), otherwise run directly (for local dev)
5-
RUN="${UV_RUN:-}"
6-
7-
# Export wrapper functions for commonly used commands
8-
slither() {
9-
$RUN slither "$@"
10-
}
11-
12-
slither-check-upgradeability() {
13-
$RUN slither-check-upgradeability "$@"
14-
}
15-
16-
slither-check-kspec() {
17-
$RUN slither-check-kspec "$@"
18-
}
19-
20-
slither-check-erc() {
21-
$RUN slither-check-erc "$@"
22-
}
23-
24-
slither-flat() {
25-
$RUN slither-flat "$@"
26-
}
27-
28-
slither-simil() {
29-
$RUN slither-simil "$@"
30-
}
31-
32-
slither-interface() {
33-
$RUN slither-interface "$@"
34-
}
35-
36-
slither-find-paths() {
37-
$RUN slither-find-paths "$@"
38-
}
39-
40-
slither-prop() {
41-
$RUN slither-prop "$@"
42-
}
43-
44-
solc-select() {
45-
$RUN solc-select "$@"
46-
}
47-
48-
python() {
49-
$RUN python "$@"
50-
}
51-
52-
pip() {
53-
$RUN pip "$@"
54-
}
55-
56-
# solc is installed by solc-select outside the venv, so we need special handling
57-
solc() {
58-
# If we're in CI with UV_RUN set, we need to ensure solc-select's bin is in PATH
59-
if [ -n "$UV_RUN" ]; then
60-
# Get the current solc version from solc-select
61-
# Use the raw command, not the wrapper function
62-
SOLC_VERSION=$($RUN solc-select versions 2>/dev/null | grep "(current" | cut -d' ' -f1)
63-
64-
# Get the actual virtual environment path from uv
65-
# When uv run executes, it sets up a venv but VIRTUAL_ENV might not be set in our shell context
66-
UV_VENV=$($RUN python -c "import sys; print(sys.prefix)" 2>/dev/null)
67-
68-
# Determine where solc-select would have installed the binary
69-
if [ -n "$UV_VENV" ] && [ -d "$UV_VENV/.solc-select" ]; then
70-
# uv virtual environment exists and has solc-select
71-
SOLC_BASE="$UV_VENV/.solc-select"
72-
elif [ -n "$VIRTUAL_ENV" ]; then
73-
# VIRTUAL_ENV is set in the environment
74-
SOLC_BASE="$VIRTUAL_ENV/.solc-select"
75-
else
76-
# Fall back to HOME directory
77-
SOLC_BASE="$HOME/.solc-select"
78-
fi
79-
80-
# Try multiple possible locations for the solc binary
81-
# Different systems may have different structures
82-
if [ -f "$SOLC_BASE/artifacts/solc-$SOLC_VERSION/solc-$SOLC_VERSION" ]; then
83-
# MacOS/local structure: artifacts/solc-X.Y.Z/solc-X.Y.Z
84-
"$SOLC_BASE/artifacts/solc-$SOLC_VERSION/solc-$SOLC_VERSION" "$@"
85-
elif [ -f "$SOLC_BASE/artifacts/solc-$SOLC_VERSION" ]; then
86-
# Linux/CI structure: artifacts/solc-X.Y.Z (binary directly)
87-
"$SOLC_BASE/artifacts/solc-$SOLC_VERSION" "$@"
88-
elif [ -f "$HOME/.solc-select/artifacts/solc-$SOLC_VERSION/solc-$SOLC_VERSION" ]; then
89-
# Fallback to HOME directory - MacOS/local structure
90-
"$HOME/.solc-select/artifacts/solc-$SOLC_VERSION/solc-$SOLC_VERSION" "$@"
91-
elif [ -f "$HOME/.solc-select/artifacts/solc-$SOLC_VERSION" ]; then
92-
# Fallback to HOME directory - Linux/CI structure (binary directly)
93-
"$HOME/.solc-select/artifacts/solc-$SOLC_VERSION" "$@"
94-
else
95-
echo "Error: solc-$SOLC_VERSION not found in solc-select artifacts" >&2
96-
echo "VIRTUAL_ENV: ${VIRTUAL_ENV:-not set}" >&2
97-
echo "UV_VENV: ${UV_VENV:-not found}" >&2
98-
echo "HOME: $HOME" >&2
99-
echo "SOLC_BASE: $SOLC_BASE" >&2
100-
echo "Searched locations:" >&2
101-
echo " - $SOLC_BASE/artifacts/solc-$SOLC_VERSION/solc-$SOLC_VERSION" >&2
102-
echo " - $SOLC_BASE/artifacts/solc-$SOLC_VERSION" >&2
103-
echo " - $HOME/.solc-select/artifacts/solc-$SOLC_VERSION/solc-$SOLC_VERSION" >&2
104-
echo " - $HOME/.solc-select/artifacts/solc-$SOLC_VERSION" >&2
105-
return 1
106-
fi
107-
else
108-
# Local development - use solc directly
109-
command solc "$@"
4+
# In CI, activate the virtual environment so all tools are in PATH
5+
# In local development, assume the environment is already set up
6+
7+
if [ -n "$UV_RUN" ]; then
8+
# CI environment - activate the virtual environment created by uv
9+
# Find the project root (where .venv is located)
10+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
12+
13+
# Activate the virtual environment
14+
# This puts all installed tools in PATH
15+
if [ -f "$PROJECT_ROOT/.venv/bin/activate" ]; then
16+
source "$PROJECT_ROOT/.venv/bin/activate"
11017
fi
111-
}
112-
113-
# Export the functions
114-
export -f slither
115-
export -f slither-check-upgradeability
116-
export -f slither-check-kspec
117-
export -f slither-check-erc
118-
export -f slither-flat
119-
export -f slither-simil
120-
export -f slither-interface
121-
export -f slither-find-paths
122-
export -f slither-prop
123-
export -f solc-select
124-
export -f python
125-
export -f pip
126-
export -f solc
18+
19+
# Set VIRTUAL_ENV for solc-select to use
20+
# This ensures solc binaries are installed to .venv/.solc-select
21+
export VIRTUAL_ENV="$PROJECT_ROOT/.venv"
22+
fi
23+
24+
# Now all commands work directly without wrappers
25+
# slither, solc-select, python, etc. are all in PATH

slither/__main__.py

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,43 +13,42 @@
1313
from importlib import metadata
1414
from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, Type, Union
1515

16-
17-
from crytic_compile import cryticparser, CryticCompile
18-
from crytic_compile.platform.standard import generate_standard_export
16+
from crytic_compile import CryticCompile, compile_all, cryticparser, is_supported
1917
from crytic_compile.platform.etherscan import SUPPORTED_NETWORK
20-
from crytic_compile import compile_all, is_supported
18+
from crytic_compile.platform.standard import generate_standard_export
2119

2220
from slither.detectors import all_detectors
2321
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
22+
from slither.exceptions import SlitherException
2423
from slither.printers import all_printers
2524
from slither.printers.abstract_printer import AbstractPrinter
2625
from slither.slither import Slither
2726
from slither.utils import codex
28-
from slither.utils.output import (
29-
output_to_json,
30-
output_to_zip,
31-
output_to_sarif,
32-
ZIP_TYPES_ACCEPTED,
33-
Output,
34-
)
35-
from slither.utils.output_capture import StandardOutputCapture
3627
from slither.utils.colors import red, set_colorization_enabled
3728
from slither.utils.command_line import (
29+
DEFAULT_JSON_OUTPUT_TYPES,
30+
JSON_OUTPUT_TYPES,
3831
FailOnLevel,
32+
check_and_sanitize_markdown_root,
33+
defaults_flag_in_config,
3934
output_detectors,
40-
output_results_to_markdown,
4135
output_detectors_json,
4236
output_printers,
4337
output_printers_json,
38+
output_results_to_markdown,
4439
output_to_markdown,
4540
output_wiki,
46-
defaults_flag_in_config,
4741
read_config_file,
48-
JSON_OUTPUT_TYPES,
49-
DEFAULT_JSON_OUTPUT_TYPES,
50-
check_and_sanitize_markdown_root,
5142
)
52-
from slither.exceptions import SlitherException
43+
from slither.utils.output import (
44+
ZIP_TYPES_ACCEPTED,
45+
Output,
46+
output_to_json,
47+
output_to_sarif,
48+
output_to_zip,
49+
)
50+
from slither.utils.output_capture import StandardOutputCapture
51+
5352

5453
logging.basicConfig()
5554
logger = logging.getLogger("Slither")
@@ -166,8 +165,14 @@ def get_detectors_and_printers() -> Tuple[
166165
printers = [p for p in printers_ if inspect.isclass(p) and issubclass(p, AbstractPrinter)]
167166

168167
# Handle plugins!
169-
# Python 3.9+ has select() method on entry_points()
170-
entry_points = metadata.entry_points().select(group="slither_analyzer.plugin")
168+
# Python 3.9 returns dict, Python 3.10+ returns EntryPoints object with select()
169+
eps = metadata.entry_points()
170+
if hasattr(eps, 'select'):
171+
# Python 3.10+
172+
entry_points = eps.select(group="slither_analyzer.plugin")
173+
else:
174+
# Python 3.9 - returns dict
175+
entry_points = eps.get("slither_analyzer.plugin", [])
171176

172177
for entry_point in entry_points:
173178
make_plugin = entry_point.load()

0 commit comments

Comments
 (0)