mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Match CPython wording for compile() optimize and flags validation (#7765)
CPython's `builtin_compile_impl` (Python/bltinmodule.c) accepts only
optimize ∈ {-1, 0, 1, 2}; anything else raises
`ValueError("compile(): invalid optimize value")`. The previous logic
only validated via `i32::try_into::<u8>()`, which silently accepts every
value in [0, 255], so `compile(..., optimize=3)`, `optimize=99`, etc.
were silently truncated to a u8. The error wording also had the wrong
word order.
Replace the cast-based check with a `match` against the spec range.
Adjacent: the unrecognised-flags message used American spelling
("unrecognized") and missed the colon separator. CPython uses British
"unrecognised" with a colon — match it.
Verified byte-identical with CPython 3.14.4 across 12 boundary values
for optimize and 4 cases for flags. Preserves the existing OverflowError
path for `optimize=1 << 1000` (raised at the ArgPrimitiveIndex<i32>
conversion layer, before this check).
This commit is contained in:
1 parent
ee5e9d0001
commit
c3c9292c8b
2 files changed
+51
-7
No files matched your search
@@ -268,12 +268,10 @@ mod builtins {
|
||||
let mode_str = args.mode.as_str();
|
||||
|
||||
let optimize: i32 = args.optimize.map_or(-1, |v| v.value);
|
||||
let optimize: u8 = if optimize == -1 {
|
||||
vm.state.config.settings.optimize
|
||||
} else {
|
||||
optimize
|
||||
.try_into()
|
||||
.map_err(|_| vm.new_value_error("compile() optimize value invalid"))?
|
||||
let optimize: u8 = match optimize {
|
||||
-1 => vm.state.config.settings.optimize,
|
||||
0..=2 => optimize as u8,
|
||||
_ => return Err(vm.new_value_error("compile(): invalid optimize value")),
|
||||
};
|
||||
|
||||
if args
|
||||
@@ -348,7 +346,7 @@ mod builtins {
|
||||
let flags: i32 = args.flags.map_or(0, |v| v.value);
|
||||
|
||||
if !(flags & !_ast::PY_COMPILE_FLAGS_MASK).is_zero() {
|
||||
return Err(vm.new_value_error("compile() unrecognized flags"));
|
||||
return Err(vm.new_value_error("compile(): unrecognised flags"));
|
||||
}
|
||||
|
||||
let allow_incomplete = !(flags & _ast::PY_CF_ALLOW_INCOMPLETE_INPUT).is_zero();
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
from testutils import assert_raises
|
||||
|
||||
# compile() basic mode acceptance
|
||||
assert isinstance(
|
||||
compile("x = 1", "<test>", "exec"), type(compile("", "<test>", "exec"))
|
||||
)
|
||||
assert compile("1 + 1", "<test>", "eval") is not None
|
||||
assert compile("1", "<test>", "single") is not None
|
||||
|
||||
# `optimize` accepts -1 (use config default), 0, 1, 2 only.
|
||||
# Anything else raises ValueError with CPython's exact wording.
|
||||
for ok in (-1, 0, 1, 2):
|
||||
compile("x = 1", "<test>", "exec", optimize=ok)
|
||||
|
||||
|
||||
def _check_optimize_error(value):
|
||||
try:
|
||||
compile("x = 1", "<test>", "exec", optimize=value)
|
||||
except ValueError as e:
|
||||
assert str(e) == "compile(): invalid optimize value", repr(e)
|
||||
else:
|
||||
raise AssertionError(f"expected ValueError for optimize={value!r}")
|
||||
|
||||
|
||||
for bad in (3, 4, 99, 255, 256, 1000, -2, -99, -128):
|
||||
_check_optimize_error(bad)
|
||||
|
||||
# Huge `optimize` values raise OverflowError during argument conversion,
|
||||
# not ValueError. The exact wording differs from CPython here (Rust i32
|
||||
# vs C int) — checking the type only, matching test_compile.py.
|
||||
assert_raises(OverflowError, compile, "x = 1", "<test>", "exec", optimize=1 << 1000)
|
||||
|
||||
|
||||
# Unrecognised `flags` bits raise ValueError. CPython uses British spelling
|
||||
# ("unrecognised") so the message must match exactly.
|
||||
def _check_flags_error(flags):
|
||||
try:
|
||||
compile("x = 1", "<test>", "exec", flags=flags)
|
||||
except ValueError as e:
|
||||
assert str(e) == "compile(): unrecognised flags", repr(e)
|
||||
else:
|
||||
raise AssertionError(f"expected ValueError for flags={flags!r}")
|
||||
|
||||
|
||||
_check_flags_error(99999)
|
||||
_check_flags_error(0x10000)
|
||||
Reference in new issue
Block a user