Skip to content
Merged
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
12 changes: 5 additions & 7 deletions crates/vm/src/stdlib/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand Down
46 changes: 46 additions & 0 deletions extra_tests/snippets/builtin_compile.py
Original file line number Diff line number Diff line change
@@ -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)
Loading