Clippy warn on unnecessary wraps (#7869)

This commit is contained in:
Shahar Naveh authored and GitHub committed 2026-05-13 23:14:33 +09:00
1 parent f8e0eeb579
commit e8711edd2d
72 files changed
+625 -650

No files matched your search

+1
View File
@@ -358,3 +358,4 @@ inconsistent_struct_constructor = "warn"
manual_is_variant_and = "warn"
map_unwrap_or = "warn"
must_use_candidate = "warn"
unnecessary_wraps = "warn"
+67 -75
View File
@@ -1231,37 +1231,37 @@ impl Compiler {
/// Get the cell-relative index of a free variable.
/// Returns ncells + freevar_idx. Fixed up to localsplus index during finalize.
fn get_free_var_index(&mut self, name: &str) -> CompileResult<oparg::VarNum> {
fn get_free_var_index(&mut self, name: &str) -> oparg::VarNum {
let info = self.code_stack.last_mut().unwrap();
let idx = info
.metadata
.freevars
.get_index_of(name)
.unwrap_or_else(|| info.metadata.freevars.insert_full(name.to_owned()).0);
Ok((idx + info.metadata.cellvars.len()).to_u32().into())
(idx + info.metadata.cellvars.len()).to_u32().into()
}
/// Get the cell-relative index of a cell variable.
/// Returns cellvar_idx. Fixed up to localsplus index during finalize.
fn get_cell_var_index(&mut self, name: &str) -> CompileResult<oparg::VarNum> {
fn get_cell_var_index(&mut self, name: &str) -> oparg::VarNum {
let info = self.code_stack.last_mut().unwrap();
let idx = info
.metadata
.cellvars
.get_index_of(name)
.unwrap_or_else(|| info.metadata.cellvars.insert_full(name.to_owned()).0);
Ok(idx.to_u32().into())
idx.to_u32().into()
}
/// Get the index of a local variable.
fn get_local_var_index(&mut self, name: &str) -> CompileResult<oparg::VarNum> {
fn get_local_var_index(&mut self, name: &str) -> oparg::VarNum {
let info = self.code_stack.last_mut().unwrap();
let idx = info
.metadata
.varnames
.get_index_of(name)
.unwrap_or_else(|| info.metadata.varnames.insert_full(name.to_owned()).0);
Ok(idx.to_u32().into())
idx.to_u32().into()
}
/// Get the index of a global name.
@@ -1479,8 +1479,8 @@ impl Compiler {
// Load __class__ from cell/free variable
let scope = self.get_ref_type("__class__").map_err(|e| self.error(e))?;
let idx = match scope {
SymbolScope::Cell => self.get_cell_var_index("__class__")?,
SymbolScope::Free => self.get_free_var_index("__class__")?,
SymbolScope::Cell => self.get_cell_var_index("__class__"),
SymbolScope::Free => self.get_free_var_index("__class__"),
_ => {
return Err(self.error(CodegenErrorType::SyntaxError(
"super(): __class__ cell not found".to_owned(),
@@ -1929,14 +1929,14 @@ impl Compiler {
// Emit format validation: if format > VALUE_WITH_FAKE_GLOBALS: raise NotImplementedError
// VALUE_WITH_FAKE_GLOBALS = 2 (from annotationlib.Format)
self.emit_format_validation()?;
self.emit_format_validation();
Ok(Some(saved_ctx))
}
/// Emit format parameter validation for annotation scope
/// if format > VALUE_WITH_FAKE_GLOBALS (2): raise NotImplementedError
fn emit_format_validation(&mut self) -> CompileResult<()> {
fn emit_format_validation(&mut self) {
// Load format parameter (first local variable, index 0)
emit!(
self,
@@ -1976,8 +1976,6 @@ impl Compiler {
// Body label - continue with annotation evaluation
self.switch_to_block(body_block);
Ok(())
}
/// Push a new fblock
@@ -2228,11 +2226,9 @@ impl Compiler {
self._name_inner(name, |i| &mut i.metadata.names)
}
fn varname(&mut self, name: &str) -> CompileResult<oparg::VarNum> {
// Note: __debug__ checks are now handled in symboltable phase
Ok(oparg::VarNum::from_u32(
self._name_inner(name, |i| &mut i.metadata.varnames),
))
fn varname(&mut self, name: &str) -> oparg::VarNum {
// NOTE: __debug__ checks are now handled in symboltable phase
oparg::VarNum::from_u32(self._name_inner(name, |i| &mut i.metadata.varnames))
}
fn _name_inner(
@@ -2784,8 +2780,8 @@ impl Compiler {
match op_type {
NameOp::Deref => {
let i = match actual_scope {
SymbolScope::Free => self.get_free_var_index(&name)?,
SymbolScope::Cell => self.get_cell_var_index(&name)?,
SymbolScope::Free => self.get_free_var_index(&name),
SymbolScope::Cell => self.get_cell_var_index(&name),
_ => unreachable!("Invalid scope for Deref operation"),
};
@@ -2800,7 +2796,7 @@ impl Compiler {
emit!(self, Instruction::LoadFromDictOrDeref { i });
// can_see_class_scope: LOAD_DEREF(__classdict__) first
} else if can_see_class_scope {
let classdict_idx = self.get_free_var_index("__classdict__")?;
let classdict_idx = self.get_free_var_index("__classdict__");
emit!(self, Instruction::LoadDeref { i: classdict_idx });
emit!(self, Instruction::LoadFromDictOrDeref { i });
} else {
@@ -2812,7 +2808,7 @@ impl Compiler {
};
}
NameOp::Fast => {
let var_num = self.get_local_var_index(&name)?;
let var_num = self.get_local_var_index(&name);
match usage {
NameUsage::Load => emit!(self, Instruction::LoadFast { var_num }),
NameUsage::Store => emit!(self, Instruction::StoreFast { var_num }),
@@ -2852,7 +2848,7 @@ impl Compiler {
match usage {
NameUsage::Load => {
// Load __classdict__ first (it's a free variable in annotation scope)
let classdict_idx = self.get_free_var_index("__classdict__")?;
let classdict_idx = self.get_free_var_index("__classdict__");
emit!(self, Instruction::LoadDeref { i: classdict_idx });
emit!(self, Instruction::LoadFromDictOrGlobals { i: idx });
}
@@ -3414,16 +3410,16 @@ impl Compiler {
.chain(kw_without_defaults)
.chain(kw_with_defaults.into_iter().map(|(arg, _)| arg));
for name in args_iter {
self.varname(name.name.as_str())?;
self.varname(name.name.as_str());
}
if let Some(name) = parameters.vararg.as_deref() {
self.current_code_info().flags |= bytecode::CodeFlags::VARARGS;
self.varname(name.name.as_str())?;
self.varname(name.name.as_str());
}
if let Some(name) = parameters.kwarg.as_deref() {
self.current_code_info().flags |= bytecode::CodeFlags::VARKEYWORDS;
self.varname(name.name.as_str())?;
self.varname(name.name.as_str());
}
Ok(())
@@ -3472,7 +3468,7 @@ impl Compiler {
.varnames
.insert(".format".to_owned());
self.emit_format_validation()?;
self.emit_format_validation();
// TypeParams scope is function-like
let prev_ctx = self.ctx;
@@ -3525,7 +3521,7 @@ impl Compiler {
.metadata
.varnames
.insert(".format".to_owned());
self.emit_format_validation()?;
self.emit_format_validation();
let prev_ctx = self.ctx;
self.ctx = CompileContext {
@@ -5108,7 +5104,7 @@ impl Compiler {
.insert("format".to_owned());
// Emit format validation: if format > VALUE_WITH_FAKE_GLOBALS: raise NotImplementedError
self.emit_format_validation()?;
self.emit_format_validation();
emit!(self, Instruction::BuildMap { count: 0 });
@@ -5147,7 +5143,7 @@ impl Compiler {
value: simple_idx.into(),
});
if parent_scope_type == CompilerScope::Class {
let idx = self.get_free_var_index("__conditional_annotations__")?;
let idx = self.get_free_var_index("__conditional_annotations__");
emit!(self, Instruction::LoadDeref { i: idx });
} else {
let cond_annotations_name = self.name("__conditional_annotations__");
@@ -5681,7 +5677,7 @@ impl Compiler {
// setup so nested generic classes match CPython's prologue order.
if self.current_symbol_table().needs_classdict {
emit!(self, Instruction::LoadLocals);
let classdict_idx = self.get_cell_var_index("__classdict__")?;
let classdict_idx = self.get_cell_var_index("__classdict__");
emit!(self, Instruction::StoreDeref { i: classdict_idx });
}
@@ -5751,7 +5747,7 @@ impl Compiler {
// Store __classdictcell__ if __classdict__ is a cell variable
if self.current_symbol_table().needs_classdict {
let classdict_idx = u32::from(self.get_cell_var_index("__classdict__")?);
let classdict_idx = u32::from(self.get_cell_var_index("__classdict__"));
emit!(self, PseudoInstruction::LoadClosure { i: classdict_idx });
self.set_no_location();
let classdictcell = self.name("__classdictcell__");
@@ -6596,24 +6592,23 @@ impl Compiler {
/// Ensures that `pc.fail_pop` has at least `n + 1` entries.
/// If not, new labels are generated and pushed until the required size is reached.
fn ensure_fail_pop(&mut self, pc: &mut PatternContext, n: usize) -> CompileResult<()> {
fn ensure_fail_pop(&mut self, pc: &mut PatternContext, n: usize) {
let required_size = n + 1;
if required_size <= pc.fail_pop.len() {
return Ok(());
return;
}
while pc.fail_pop.len() < required_size {
let new_block = self.new_block();
pc.fail_pop.push(new_block);
}
Ok(())
}
fn jump_to_fail_pop(&mut self, pc: &mut PatternContext, op: JumpOp) -> CompileResult<()> {
fn jump_to_fail_pop(&mut self, pc: &mut PatternContext, op: JumpOp) {
// Compute the total number of items to pop:
// items on top plus the captured objects.
let pops = pc.on_top + pc.stores.len();
// Ensure that the fail_pop vector has at least `pops + 1` elements.
self.ensure_fail_pop(pc, pops)?;
self.ensure_fail_pop(pc, pops);
// Emit a jump using the jump target stored at index `pops`.
match op {
JumpOp::Jump => {
@@ -6622,7 +6617,7 @@ impl Compiler {
PseudoInstruction::Jump {
delta: pc.fail_pop[pops]
}
);
)
}
JumpOp::PopJumpIfFalse => {
emit!(
@@ -6630,19 +6625,18 @@ impl Compiler {
Instruction::PopJumpIfFalse {
delta: pc.fail_pop[pops]
}
);
)
}
}
Ok(())
};
}
/// Emits the necessary POP instructions for all failure targets in the pattern context,
/// then resets the fail_pop vector.
fn emit_and_reset_fail_pop(&mut self, pc: &mut PatternContext) -> CompileResult<()> {
fn emit_and_reset_fail_pop(&mut self, pc: &mut PatternContext) {
// If the fail_pop vector is empty, nothing needs to be done.
if pc.fail_pop.is_empty() {
debug_assert!(pc.fail_pop.is_empty());
return Ok(());
return;
}
// Iterate over the fail_pop vector in reverse order, skipping the first label.
for &label in pc.fail_pop.iter().skip(1).rev() {
@@ -6655,11 +6649,10 @@ impl Compiler {
pc.fail_pop.clear();
// Free the memory used by the vector.
pc.fail_pop.shrink_to_fit();
Ok(())
}
/// Duplicate the effect of Python 3.10's ROT_* instructions using SWAPs.
fn pattern_helper_rotate(&mut self, mut count: usize) -> CompileResult<()> {
fn pattern_helper_rotate(&mut self, mut count: usize) {
// Rotate TOS (top of stack) to position `count` down
// This is done by a series of swaps
// For count=1, no rotation needed (already at top)
@@ -6675,7 +6668,6 @@ impl Compiler {
);
count -= 1;
}
Ok(())
}
/// Helper to store a captured name for a star pattern.
@@ -6711,7 +6703,7 @@ impl Compiler {
// Calculate how many items to rotate:
let rotations = pc.on_top + pc.stores.len() + 1;
self.pattern_helper_rotate(rotations)?;
self.pattern_helper_rotate(rotations);
// Append the name to the captured stores.
pc.stores.push(name.to_string());
@@ -6993,7 +6985,7 @@ impl Compiler {
// At this point the TOS is a tuple of (nargs + n_attrs) attributes (or None).
pc.on_top += 1;
self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse)?;
self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse);
// Unpack the tuple into (nargs + n_attrs) items.
let total = nargs + n_attrs;
@@ -7065,7 +7057,7 @@ impl Compiler {
emit!(self, Instruction::MatchMapping);
// Stack: [subject, is_mapping]
self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse)?;
self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse);
// Stack: [subject]
// Special case: empty pattern {} with no rest
@@ -7088,7 +7080,7 @@ impl Compiler {
opname: ComparisonOperator::GreaterOrEqual
}
);
self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse)?;
self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse);
// Stack: [subject]
}
@@ -7163,7 +7155,7 @@ impl Compiler {
);
// Stack: [subject, keys_tuple, values_tuple, bool]
self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse)?;
self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse);
// Stack: [subject, keys_tuple, values_tuple]
// Unpack values (the original values_tuple)
@@ -7302,7 +7294,7 @@ impl Compiler {
// Also perform the same rotation on the evaluation stack.
self.set_source_range(alt.range());
for _ in 0..=i_stores {
self.pattern_helper_rotate(i_control + 1)?;
self.pattern_helper_rotate(i_control + 1);
}
}
}
@@ -7312,7 +7304,7 @@ impl Compiler {
self.set_source_range(alt.range());
emit!(self, PseudoInstruction::Jump { delta: end });
self.set_source_range(alt.range());
self.emit_and_reset_fail_pop(pc)?;
self.emit_and_reset_fail_pop(pc);
}
// Restore the original pattern context.
@@ -7325,7 +7317,7 @@ impl Compiler {
// No alternative matched: pop the subject and fail.
self.set_source_range(p.range());
emit!(self, Instruction::PopTop);
self.jump_to_fail_pop(pc, JumpOp::Jump)?;
self.jump_to_fail_pop(pc, JumpOp::Jump);
// Use the label "end".
self.switch_to_block(end);
@@ -7336,7 +7328,7 @@ impl Compiler {
for i in 0..n_stores {
// Rotate the capture to its proper place.
self.set_source_range(p.range());
self.pattern_helper_rotate(n_rots)?;
self.pattern_helper_rotate(n_rots);
let name = &control.as_ref().unwrap()[i];
// Check for duplicate binding.
if pc.stores.contains(name) {
@@ -7384,7 +7376,7 @@ impl Compiler {
// Keep the subject on top during the sequence and length checks.
pc.on_top += 1;
emit!(self, Instruction::MatchSequence);
self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse)?;
self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse);
if star.is_none() {
// No star: len(subject) == size
@@ -7396,7 +7388,7 @@ impl Compiler {
opname: ComparisonOperator::Equal
}
);
self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse)?;
self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse);
} else if size > 1 {
// Star exists: len(subject) >= size - 1
emit!(self, Instruction::GetLen);
@@ -7409,7 +7401,7 @@ impl Compiler {
opname: ComparisonOperator::GreaterOrEqual
}
);
self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse)?;
self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse);
}
// Whatever comes next should consume the subject.
@@ -7441,7 +7433,7 @@ impl Compiler {
}
);
emit!(self, Instruction::ToBool);
self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse)?;
self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse);
Ok(())
}
@@ -7449,7 +7441,7 @@ impl Compiler {
&mut self,
p: &ast::PatternMatchSingleton,
pc: &mut PatternContext,
) -> CompileResult<()> {
) {
// Load the singleton constant value.
self.emit_load_const(match p.value {
ast::Singleton::None => ConstantData::None,
@@ -7459,8 +7451,7 @@ impl Compiler {
// Compare using the "Is" operator.
emit!(self, Instruction::IsOp { invert: Invert::No });
// Jump to the failure label if the comparison is false.
self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse)?;
Ok(())
self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse);
}
fn compile_pattern(
@@ -7475,7 +7466,8 @@ impl Compiler {
self.compile_pattern_value(pattern_type, pattern_context)
}
ast::Pattern::MatchSingleton(pattern_type) => {
self.compile_pattern_singleton(pattern_type, pattern_context)
self.compile_pattern_singleton(pattern_type, pattern_context);
Ok(())
}
ast::Pattern::MatchSequence(pattern_type) => {
self.compile_pattern_sequence(pattern_type, pattern_context)
@@ -7544,7 +7536,7 @@ impl Compiler {
}
if let Some(ref guard) = m.guard {
self.ensure_fail_pop(pattern_context, 0)?;
self.ensure_fail_pop(pattern_context, 0);
self.compile_jump_if_inner(
guard,
false,
@@ -7573,7 +7565,7 @@ impl Compiler {
last.match_success_jump = true;
}
self.set_source_range(m.pattern.range());
self.emit_and_reset_fail_pop(pattern_context)?;
self.emit_and_reset_fail_pop(pattern_context);
}
if has_default {
@@ -9834,7 +9826,7 @@ impl Compiler {
// Set qualname for comprehension
self.set_qualname();
let arg0 = self.varname(".0")?;
let arg0 = self.varname(".0");
let return_none = init_collection.is_none();
@@ -10184,7 +10176,7 @@ impl Compiler {
self.set_source_range(comprehension_range);
let mut total_stack_items: usize = 0;
for name in &pushed_locals {
let var_num = self.varname(name)?;
let var_num = self.varname(name);
emit!(self, Instruction::LoadFastAndClear { var_num });
total_stack_items += 1;
// If the comp symbol is CELL, emit MAKE_CELL to create fresh cell
@@ -10197,9 +10189,9 @@ impl Compiler {
.get(name)
.is_some_and(|s| s.scope == SymbolScope::Free)
{
self.get_free_var_index(name)?
self.get_free_var_index(name)
} else {
self.get_cell_var_index(name)?
self.get_cell_var_index(name)
};
emit!(self, Instruction::MakeCell { i });
}
@@ -10375,7 +10367,7 @@ impl Compiler {
}
);
for name in pushed_locals.iter().rev() {
let var_num = self.varname(name)?.as_u32();
let var_num = self.varname(name).as_u32();
emit!(self, PseudoInstruction::StoreFastMaybeNull { var_num });
}
// Re-raise the exception
@@ -10397,7 +10389,7 @@ impl Compiler {
// Restore saved locals (StoreFast restores the saved cell object for merged cells)
for name in pushed_locals.iter().rev() {
let var_num = self.varname(name)?.as_u32();
let var_num = self.varname(name).as_u32();
emit!(self, PseudoInstruction::StoreFastMaybeNull { var_num });
}
self.set_source_range(saved_source_range);
@@ -11481,7 +11473,8 @@ impl Compiler {
)?;
}
self.set_source_range(fstring_range);
self.finish_fstring(pending_literal, pending_literal_no_location, element_count)
self.finish_fstring(pending_literal, pending_literal_no_location, element_count);
Ok(())
}
fn compile_fstring_parts_joined(&mut self, fstring: &[ast::FStringPart]) -> CompileResult<()> {
@@ -11545,7 +11538,7 @@ impl Compiler {
mut pending_literal: Option<Wtf8Buf>,
mut pending_literal_no_location: bool,
mut element_count: u32,
) -> CompileResult<()> {
) {
let keep_empty = element_count == 0;
self.emit_pending_fstring_literal(
&mut pending_literal,
@@ -11567,8 +11560,6 @@ impl Compiler {
}
);
}
Ok(())
}
fn finish_fstring_join(
@@ -11690,7 +11681,8 @@ impl Compiler {
&mut element_count,
false,
)?;
self.finish_fstring(pending_literal, pending_literal_no_location, element_count)
self.finish_fstring(pending_literal, pending_literal_no_location, element_count);
Ok(())
}
fn compile_fstring_elements_joined(
+5 -5
View File
@@ -68,7 +68,7 @@ impl StringParser {
self.source[self.cursor..].as_bytes().first().copied()
}
fn parse_unicode_literal(&mut self, literal_number: usize) -> Result<CodePoint, LexicalError> {
fn parse_unicode_literal(&mut self, literal_number: usize) -> CodePoint {
let mut p: u32 = 0u32;
for i in 1..=literal_number {
match self.next_char() {
@@ -79,7 +79,7 @@ impl StringParser {
None => unreachable!(),
}
}
Ok(CodePoint::from_u32(p).unwrap())
CodePoint::from_u32(p).unwrap()
}
fn parse_octet(&mut self, o: u8) -> char {
@@ -134,9 +134,9 @@ impl StringParser {
't' => '\t'.into(),
'v' => '\x0b'.into(),
o @ '0'..='7' => self.parse_octet(o as u8).into(),
'x' => self.parse_unicode_literal(2)?,
'u' if !self.flags.is_byte_string() => self.parse_unicode_literal(4)?,
'U' if !self.flags.is_byte_string() => self.parse_unicode_literal(8)?,
'x' => self.parse_unicode_literal(2),
'u' if !self.flags.is_byte_string() => self.parse_unicode_literal(4),
'U' if !self.flags.is_byte_string() => self.parse_unicode_literal(8),
'N' if !self.flags.is_byte_string() => self.parse_unicode_name()?.into(),
// Special cases where the escape sequence is not a single character
'\n' => return Ok(None),
+33 -11
View File
@@ -580,7 +580,13 @@ impl FormatSpec {
},
};
self.format_sign_and_align(&AsciiStr::new(&magnitude_str), sign_str, FormatAlign::Right)
Ok(
self.format_sign_and_align(
&AsciiStr::new(&magnitude_str),
sign_str,
FormatAlign::Right,
),
)
}
/// Format a float with locale-aware 'n' format.
@@ -620,7 +626,13 @@ impl FormatSpec {
}
};
self.format_sign_and_align(&AsciiStr::new(&magnitude_str), sign_str, FormatAlign::Right)
Ok(
self.format_sign_and_align(
&AsciiStr::new(&magnitude_str),
sign_str,
FormatAlign::Right,
),
)
}
/// Format a complex number with locale-aware 'n' format.
@@ -672,7 +684,7 @@ impl FormatSpec {
// No parentheses for 'n' format (CPython: add_parens=0)
let magnitude_str = format!("{grouped_re}{grouped_im}");
self.format_sign_and_align(&AsciiStr::new(&magnitude_str), "", FormatAlign::Right)
Ok(self.format_sign_and_align(&AsciiStr::new(&magnitude_str), "", FormatAlign::Right))
}
pub fn format_bool(&self, input: bool) -> Result<String, FormatSpecError> {
@@ -789,7 +801,13 @@ impl FormatSpec {
}
};
let magnitude_str = self.add_magnitude_separators(raw_magnitude_str?, sign_str);
self.format_sign_and_align(&AsciiStr::new(&magnitude_str), sign_str, FormatAlign::Right)
Ok(
self.format_sign_and_align(
&AsciiStr::new(&magnitude_str),
sign_str,
FormatAlign::Right,
),
)
}
#[inline]
@@ -863,11 +881,11 @@ impl FormatSpec {
};
let sign_prefix = format!("{sign_str}{prefix}");
let magnitude_str = self.add_magnitude_separators(raw_magnitude_str, &sign_prefix);
self.format_sign_and_align(
Ok(self.format_sign_and_align(
&AsciiStr::new(&magnitude_str),
&sign_prefix,
FormatAlign::Right,
)
))
}
pub fn format_string<T>(&self, s: &T) -> Result<String, FormatSpecError>
@@ -883,7 +901,7 @@ impl FormatSpec {
Some(p) => s.deref().chars().take(p).collect(),
None => s.deref().to_owned(),
};
self.format_sign_and_align(&truncated, "", FormatAlign::Left)
Ok(self.format_sign_and_align(&truncated, "", FormatAlign::Left))
}
_ => {
let ch = char::from(self.format_type.as_ref().unwrap());
@@ -905,7 +923,11 @@ impl FormatSpec {
}
match &self.fill.unwrap_or_else(|| ' '.into()).to_char() {
Some('0') => Err(FormatSpecError::ZeroPadding),
_ => self.format_sign_and_align(&AsciiStr::new(&magnitude_str), "", FormatAlign::Right),
_ => Ok(self.format_sign_and_align(
&AsciiStr::new(&magnitude_str),
"",
FormatAlign::Right,
)),
}
}
@@ -1017,7 +1039,7 @@ impl FormatSpec {
magnitude_str: &T,
sign_str: &str,
default_align: FormatAlign,
) -> Result<String, FormatSpecError>
) -> String
where
T: CharLen + Deref<Target = str>,
{
@@ -1030,7 +1052,7 @@ impl FormatSpec {
});
let magnitude_str = magnitude_str.deref();
Ok(match align {
match align {
FormatAlign::Left => format!(
"{}{}{}",
sign_str,
@@ -1057,7 +1079,7 @@ impl FormatSpec {
Self::compute_fill_string(fill_char, right_fill_chars_needed);
format!("{left_fill_string}{sign_str}{magnitude_str}{right_fill_string}")
}
})
}
}
}
+2 -2
View File
@@ -53,7 +53,7 @@ pub fn pyclass(attr: PunctuatedNestedMeta, item: Item) -> TokenStream {
#[must_use]
pub fn pyexception(attr: PunctuatedNestedMeta, item: Item) -> TokenStream {
if matches!(item, syn::Item::Impl(_)) {
result_to_tokens(pyclass::impl_pyexception_impl(attr, item))
pyclass::impl_pyexception_impl(attr, item)
} else {
result_to_tokens(pyclass::impl_pyexception(attr, item))
}
@@ -84,7 +84,7 @@ pub fn py_freeze(input: TokenStream, compiler: &dyn Compiler) -> TokenStream {
#[must_use]
pub fn pypayload(input: DeriveInput) -> TokenStream {
result_to_tokens(pypayload::impl_pypayload(input))
pypayload::impl_pypayload(input)
}
#[must_use]
+13 -13
View File
@@ -644,8 +644,8 @@ pub(crate) fn impl_pyclass(attr: PunctuatedNestedMeta, item: Item) -> Result<Tok
// 1. no `clear`: HAS_CLEAR = HAS_TRAVERSE (default: same as traverse)
// 2. `clear` or `clear = true`: HAS_CLEAR = true, try_clear calls Traverse::clear
// 3. `clear = false`: HAS_CLEAR = false (rare: traverse without clear)
let has_traverse = class_meta.inner()._has_key("traverse")?;
let has_clear = if class_meta.inner()._has_key("clear")? {
let has_traverse = class_meta.inner()._has_key("traverse");
let has_clear = if class_meta.inner()._has_key("clear") {
// If clear attribute is present, use its value
class_meta.inner()._bool("clear")?
} else {
@@ -804,9 +804,9 @@ pub(crate) fn impl_pyexception(attr: PunctuatedNestedMeta, item: Item) -> Result
Ok(ret)
}
pub(crate) fn impl_pyexception_impl(attr: PunctuatedNestedMeta, item: Item) -> Result<TokenStream> {
pub(crate) fn impl_pyexception_impl(attr: PunctuatedNestedMeta, item: Item) -> TokenStream {
let Item::Impl(imp) = item else {
return Ok(item.into_token_stream());
return item.into_token_stream();
};
// Check if with(Constructor) is specified. If Constructor trait is used, don't generate slot_new
@@ -878,7 +878,7 @@ pub(crate) fn impl_pyexception_impl(attr: PunctuatedNestedMeta, item: Item) -> R
quote!(, #(#extra_attrs),*)
};
Ok(quote! {
quote! {
#[pyclass(flags(BASETYPE, HAS_DICT), with(#(#with_items),*) #extra_attrs_tokens)]
impl #generics #self_ty {
#(#items)*
@@ -886,7 +886,7 @@ pub(crate) fn impl_pyexception_impl(attr: PunctuatedNestedMeta, item: Item) -> R
#slot_new
#slot_init
})
}
}
macro_rules! define_content_item {
@@ -1189,7 +1189,7 @@ where
args.cfgs.to_vec(),
tokens,
2,
)?;
);
Ok(())
}
@@ -1235,7 +1235,7 @@ where
args.context
.attribute_items
.add_item(ident.clone(), vec![py_name], cfgs, tokens, 1)?;
.add_item(ident.clone(), vec![py_name], cfgs, tokens, 1);
Ok(())
}
@@ -1944,12 +1944,12 @@ fn extract_impl_attrs(attr: PunctuatedNestedMeta, item: &Ident) -> Result<Extrac
fn impl_item_new<Item>(
index: usize,
attr_name: AttrName,
) -> Result<Box<dyn ImplItem<Item, AttrName = AttrName>>>
) -> Box<dyn ImplItem<Item, AttrName = AttrName>>
where
Item: ItemLike + ToTokens + GetIdent,
{
use AttrName::*;
Ok(match attr_name {
match attr_name {
attr_name @ (Method | ClassMethod | StaticMethod) => Box::new(MethodItem {
inner: ContentItemInner { index, attr_name },
}),
@@ -1968,7 +1968,7 @@ where
Member => Box::new(MemberItem {
inner: ContentItemInner { index, attr_name },
}),
})
}
}
fn attrs_to_content_items<F, R>(
@@ -1976,7 +1976,7 @@ fn attrs_to_content_items<F, R>(
item_new: F,
) -> Result<(Vec<R>, Vec<Attribute>)>
where
F: Fn(usize, AttrName) -> Result<R>,
F: Fn(usize, AttrName) -> R,
{
let mut cfgs: Vec<Attribute> = Vec::new();
let mut result = Vec::new();
@@ -2018,7 +2018,7 @@ where
}
};
result.push(item_new(i, attr_name)?);
result.push(item_new(i, attr_name));
}
Ok((result, cfgs))
}
+5 -5
View File
@@ -816,7 +816,7 @@ impl ModuleItem for ClassItem {
#set_attr
},
0,
)?;
);
Ok(())
}
}
@@ -910,7 +910,7 @@ impl ModuleItem for StructSequenceItem {
#set_attr
},
0,
)?;
);
Ok(())
}
}
@@ -995,9 +995,9 @@ impl ModuleItem for AttributeItem {
cfgs.clone(),
tokens,
1,
)?;
);
Ok(())
})?;
});
return Ok(());
}
other => {
@@ -1053,7 +1053,7 @@ impl ModuleItem for AttributeItem {
args.context
.attribute_items
.add_item(ident, py_names, cfgs, tokens, 1)?;
.add_item(ident, py_names, cfgs, tokens, 1);
Ok(())
}
+4 -5
View File
@@ -1,17 +1,16 @@
use proc_macro2::TokenStream;
use quote::quote;
use syn::{DeriveInput, Result};
use syn::DeriveInput;
pub(crate) fn impl_pypayload(input: DeriveInput) -> Result<TokenStream> {
pub(crate) fn impl_pypayload(input: DeriveInput) -> TokenStream {
let ty = &input.ident;
let ret = quote! {
quote! {
impl ::rustpython_vm::PyPayload for #ty {
#[inline]
fn class(_ctx: &::rustpython_vm::vm::Context) -> &'static rustpython_vm::Py<::rustpython_vm::builtins::PyType> {
<Self as ::rustpython_vm::class::StaticType>::static_type()
}
}
};
Ok(ret)
}
}
+3 -4
View File
@@ -45,7 +45,7 @@ impl ItemNursery {
cfgs: Vec<Attribute>,
tokens: TokenStream,
sort_order: usize,
) -> Result<()> {
) {
self.0.push(NurseryItem {
attr_name,
py_names,
@@ -53,7 +53,6 @@ impl ItemNursery {
tokens,
sort_order,
});
Ok(())
}
pub(crate) fn validate(self) -> Result<ValidatedItemNursery> {
@@ -216,8 +215,8 @@ impl ItemMetaInner {
Ok(value)
}
pub(crate) fn _has_key(&self, key: &str) -> Result<bool> {
Ok(matches!(self.meta_map.get(key), Some((_, _))))
pub(crate) fn _has_key(&self, key: &str) -> bool {
matches!(self.meta_map.get(key), Some((_, _)))
}
pub(crate) fn _bool(&self, key: &str) -> Result<bool> {
+25 -21
View File
@@ -609,7 +609,7 @@ pub(crate) mod _asyncio {
}
#[pygetset]
fn _callbacks(&self, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
fn _callbacks(&self, vm: &VirtualMachine) -> PyObjectRef {
let mut result = Vec::new();
if let Some(cb0) = self.fut_callback0.read().clone() {
@@ -630,9 +630,9 @@ pub(crate) mod _asyncio {
// Return None if no callbacks
if result.is_empty() {
Ok(vm.ctx.none())
vm.ctx.none()
} else {
Ok(vm.ctx.new_list(result).into())
vm.ctx.new_list(result).into()
}
}
@@ -764,10 +764,10 @@ pub(crate) mod _asyncio {
}
#[pymethod]
fn __await__(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyResult<PyFutureIter> {
Ok(PyFutureIter {
fn __await__(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyFutureIter {
PyFutureIter {
future: PyRwLock::new(Some(zelf.into())),
})
}
}
#[pyclassmethod]
@@ -861,23 +861,23 @@ pub(crate) mod _asyncio {
.and_then(|asyncio| asyncio.get_attr(vm.ctx.intern_str("base_futures"), vm))
{
Ok(m) => m,
Err(_) => return get_future_repr_info_fallback(future, vm),
Err(_) => return Ok(get_future_repr_info_fallback(future, vm)),
}
};
let func = match vm.get_attribute_opt(module, vm.ctx.intern_str("_future_repr_info")) {
Ok(Some(f)) => f,
_ => return get_future_repr_info_fallback(future, vm),
_ => return Ok(get_future_repr_info_fallback(future, vm)),
};
let info = match func.call((future.to_owned(),), vm) {
Ok(i) => i,
Err(_) => return get_future_repr_info_fallback(future, vm),
Err(_) => return Ok(get_future_repr_info_fallback(future, vm)),
};
let list: PyListRef = match info.downcast() {
Ok(l) => l,
Err(_) => return get_future_repr_info_fallback(future, vm),
Err(_) => return Ok(get_future_repr_info_fallback(future, vm)),
};
let mut result = Wtf8Buf::new();
@@ -893,17 +893,17 @@ pub(crate) mod _asyncio {
Ok(result)
}
fn get_future_repr_info_fallback(future: &PyObject, vm: &VirtualMachine) -> PyResult<Wtf8Buf> {
fn get_future_repr_info_fallback(future: &PyObject, vm: &VirtualMachine) -> Wtf8Buf {
// Fallback: build repr from properties directly
if let Ok(Some(state)) =
vm.get_attribute_opt(future.to_owned(), vm.ctx.intern_str("_state"))
{
let s = state
state
.str(vm)
.map_or_else(|_| Wtf8Buf::from("unknown"), |s| s.as_wtf8().to_lowercase());
return Ok(s);
.map_or_else(|_| Wtf8Buf::from("unknown"), |s| s.as_wtf8().to_lowercase())
} else {
Wtf8Buf::from("state=unknown")
}
Ok(Wtf8Buf::from("state=unknown"))
}
fn get_task_repr_info(task: &PyObject, vm: &VirtualMachine) -> PyResult<Wtf8Buf> {
@@ -1820,10 +1820,10 @@ pub(crate) mod _asyncio {
}
#[pymethod]
fn __await__(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyResult<PyFutureIter> {
Ok(PyFutureIter {
fn __await__(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyFutureIter {
PyFutureIter {
future: PyRwLock::new(Some(zelf.into())),
})
}
}
#[pyclassmethod]
@@ -1960,7 +1960,7 @@ pub(crate) mod _asyncio {
_register_eager_task(task_obj.clone(), vm)?;
// Swap current task - save previous task
let prev_task = _swap_current_task(loop_obj.clone(), task_obj.clone(), vm)?;
let prev_task = _swap_current_task(loop_obj.clone(), task_obj.clone(), vm);
// Get coro and context
let coro = zelf.task_coro.read().clone();
@@ -2525,7 +2525,11 @@ pub(crate) mod _asyncio {
}
#[pyfunction]
fn _swap_current_task(loop_: PyObjectRef, task: PyObjectRef, vm: &VirtualMachine) -> PyResult {
fn _swap_current_task(
loop_: PyObjectRef,
task: PyObjectRef,
vm: &VirtualMachine,
) -> PyObjectRef {
// Per-thread swap, matching CPython's swap_current_task
let prev = vm
.asyncio_running_task
@@ -2550,7 +2554,7 @@ pub(crate) mod _asyncio {
}
}
Ok(prev)
prev
}
/// Reset task state after fork in child process.
+3 -6
View File
@@ -165,12 +165,9 @@ mod _opcode {
}
#[pyfunction]
fn get_executor(
_code: PyObjectRef,
_offset: i32,
vm: &VirtualMachine,
) -> PyResult<PyObjectRef> {
Ok(vm.ctx.none())
fn get_executor(_code: PyObjectRef, _offset: i32, vm: &VirtualMachine) -> PyObjectRef {
// TODO
vm.ctx.none()
}
#[pyfunction]
+3 -4
View File
@@ -2211,12 +2211,11 @@ mod _sqlite3 {
)]
impl Row {
#[pymethod]
fn keys(&self, _vm: &VirtualMachine) -> PyResult<Vec<PyObjectRef>> {
Ok(self
.description
fn keys(&self, _vm: &VirtualMachine) -> Vec<PyObjectRef> {
self.description
.iter()
.map(|x| x.downcast_ref::<PyTuple>().unwrap().as_slice()[0].clone())
.collect())
.collect()
}
fn subscript(&self, needle: &PyObject, vm: &VirtualMachine) -> PyResult {
+11 -17
View File
@@ -140,9 +140,9 @@ mod _contextvars {
})
}
fn contains(&self, needle: &Py<ContextVar>) -> PyResult<bool> {
fn contains(&self, needle: &Py<ContextVar>) -> bool {
let vars = self.borrow_vars();
Ok(vars.get(needle).is_some())
vars.get(needle).is_some()
}
fn get_inner(&self, needle: &Py<ContextVar>) -> Option<PyObjectRef> {
@@ -202,13 +202,13 @@ mod _contextvars {
&self,
key: PyRef<ContextVar>,
default: OptionalArg<PyObjectRef>,
) -> PyResult<Option<PyObjectRef>> {
) -> Option<PyObjectRef> {
let found = self.get_inner(&key);
Ok(if found.is_some() {
if found.is_some() {
found
} else {
default.into_option()
})
}
}
// TODO: wrong return type
@@ -265,7 +265,7 @@ mod _contextvars {
static AS_SEQUENCE: LazyLock<PySequenceMethods> = LazyLock::new(|| PySequenceMethods {
contains: atomic_func!(|seq, target, vm| {
let target = target.try_to_value(vm)?;
PyContext::sequence_downcast(seq).contains(target)
Ok(PyContext::sequence_downcast(seq).contains(target))
}),
..PySequenceMethods::NOT_IMPLEMENTED
});
@@ -335,7 +335,7 @@ mod _contextvars {
}
// contextvar_set in CPython
fn set_inner(zelf: &Py<Self>, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
fn set_inner(zelf: &Py<Self>, value: PyObjectRef, vm: &VirtualMachine) {
let ctx = PyContext::current(vm);
let mut vars = ctx.borrow_vars_mut();
@@ -348,8 +348,6 @@ mod _contextvars {
idx: ctx.inner.idx.get(),
};
zelf.cached.store(Some(cache));
Ok(())
}
fn generate_hash(zelf: &Py<Self>, vm: &VirtualMachine) -> PyHash {
@@ -408,11 +406,7 @@ mod _contextvars {
}
#[pymethod]
fn set(
zelf: &Py<Self>,
value: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<PyRef<ContextToken>> {
fn set(zelf: &Py<Self>, value: PyObjectRef, vm: &VirtualMachine) -> PyRef<ContextToken> {
let ctx = PyContext::current(vm);
let old_value = ctx.borrow_vars().get(zelf).map(|v| v.to_owned());
@@ -424,9 +418,9 @@ mod _contextvars {
};
// ctx.vars borrow must be released
Self::set_inner(zelf, value, vm)?;
Self::set_inner(zelf, value, vm);
Ok(token.into_ref(&vm.ctx))
token.into_ref(&vm.ctx)
}
#[pymethod]
@@ -456,7 +450,7 @@ mod _contextvars {
token.used.set(true);
if let Some(old_value) = &token.old_value {
Self::set_inner(zelf, old_value.clone(), vm)?;
Self::set_inner(zelf, old_value.clone(), vm);
} else {
Self::delete(zelf, vm)?;
}
+2 -2
View File
@@ -84,7 +84,7 @@ mod grp {
}
#[pyfunction]
fn getgrall(vm: &VirtualMachine) -> PyResult<Vec<PyObjectRef>> {
fn getgrall(vm: &VirtualMachine) -> Vec<PyObjectRef> {
// setgrent, getgrent, etc are not thread safe. Could use fgetgrent_r, but this is easier
static GETGRALL: parking_lot::Mutex<()> = parking_lot::Mutex::new(());
let _guard = GETGRALL.lock();
@@ -98,6 +98,6 @@ mod grp {
}
unsafe { libc::endgrent() };
Ok(list)
list
}
}
+12 -6
View File
@@ -99,12 +99,15 @@ mod _locale {
vm.ctx.new_list(group_vec)
}
unsafe fn pystr_from_raw_cstr(vm: &VirtualMachine, raw_ptr: *const libc::c_char) -> PyResult {
unsafe fn pystr_from_raw_cstr(
vm: &VirtualMachine,
raw_ptr: *const libc::c_char,
) -> PyObjectRef {
let slice = unsafe { CStr::from_ptr(raw_ptr) };
// Fast path: ASCII/UTF-8
if let Ok(s) = slice.to_str() {
return Ok(vm.new_pyobj(s));
return vm.new_pyobj(s);
}
// On Windows, locale strings use the ANSI code page encoding
@@ -131,12 +134,12 @@ mod _locale {
wide.as_mut_ptr(),
len,
);
return Ok(vm.new_pyobj(String::from_utf16_lossy(&wide)));
return vm.new_pyobj(String::from_utf16_lossy(&wide));
}
}
}
Ok(vm.new_pyobj(String::from_utf8_lossy(slice.to_bytes()).into_owned()))
vm.new_pyobj(String::from_utf8_lossy(slice.to_bytes()).into_owned())
}
#[pyattr(name = "Error", once)]
@@ -179,7 +182,7 @@ mod _locale {
($lc:expr, $field:ident) => {{
result.set_item(
stringify!($field),
pystr_from_raw_cstr(vm, (*$lc).$field)?,
pystr_from_raw_cstr(vm, (*$lc).$field),
vm,
)?
}};
@@ -264,6 +267,7 @@ mod _locale {
if cfg!(windows) && (args.category < LC_ALL || args.category > LC_TIME) {
return Err(vm.new_exception_msg(error, "unsupported locale setting".into()));
}
unsafe {
let result = match args.locale.flatten() {
None => libc::setlocale(args.category, ptr::null()),
@@ -288,10 +292,12 @@ mod _locale {
libc::setlocale(args.category, c_locale.as_ptr())
}
};
if result.is_null() {
return Err(vm.new_exception_msg(error, "unsupported locale setting".into()));
}
pystr_from_raw_cstr(vm, result)
Ok(pystr_from_raw_cstr(vm, result))
}
}
+2 -2
View File
@@ -1345,8 +1345,8 @@ mod mmap {
}
#[pymethod]
fn tell(&self) -> PyResult<usize> {
Ok(self.pos())
fn tell(&self) -> usize {
self.pos()
}
#[pymethod]
+3 -3
View File
@@ -1867,7 +1867,7 @@ mod _overlapped {
}
#[pyfunction]
fn FormatMessage(error_code: u32, _vm: &VirtualMachine) -> PyResult<String> {
fn FormatMessage(error_code: u32, _vm: &VirtualMachine) -> String {
use windows_sys::Win32::Foundation::LocalFree;
use windows_sys::Win32::System::Diagnostics::Debug::{
FORMAT_MESSAGE_ALLOCATE_BUFFER, FORMAT_MESSAGE_FROM_SYSTEM,
@@ -1898,7 +1898,7 @@ mod _overlapped {
if !buffer.is_null() {
unsafe { LocalFree(buffer as *mut _) };
}
return Ok(format!("unknown error code {}", error_code));
return format!("unknown error code {error_code}");
}
// Convert to Rust string, trimming trailing whitespace
@@ -1907,7 +1907,7 @@ mod _overlapped {
unsafe { LocalFree(buffer as *mut _) };
Ok(msg)
msg
}
#[pyfunction]
+7 -7
View File
@@ -124,9 +124,9 @@ mod _pyexpat {
namespace_separator: Option<String>,
intern: Option<PyObjectRef>,
vm: &VirtualMachine,
) -> PyResult<PyExpatLikeXmlParserRef> {
) -> PyExpatLikeXmlParserRef {
let intern_dict = intern.unwrap_or_else(|| vm.ctx.new_dict().into());
Ok(Self {
Self {
namespace_separator,
start_element: MutableObject::new(vm.ctx.none()),
end_element: MutableObject::new(vm.ctx.none()),
@@ -157,7 +157,7 @@ mod _pyexpat {
attlist_decl: MutableObject::new(vm.ctx.none()),
skipped_entity: MutableObject::new(vm.ctx.none()),
}
.into_ref(&vm.ctx))
.into_ref(&vm.ctx)
}
#[extend_class]
@@ -353,21 +353,21 @@ mod _pyexpat {
data: Either<PyStrRef, PyBytesRef>,
_isfinal: OptionalArg<bool>,
vm: &VirtualMachine,
) -> PyResult<i32> {
) -> i32 {
let bytes = match data {
Either::A(s) => s.as_bytes().to_vec(),
Either::B(b) => b.as_bytes().to_vec(),
};
// Empty data is valid - used to finalize parsing
if bytes.is_empty() {
return Ok(1);
return 1;
}
let reader = Cursor::<Vec<u8>>::new(bytes);
let parser = self.create_config().create_reader(reader);
// Note: xml-rs is stricter than libexpat; some errors are silently ignored
// to maintain compatibility with existing Python code
let _ = self.do_parse(vm, parser);
Ok(1)
1
}
#[pymethod(name = "ParseFile")]
@@ -417,7 +417,7 @@ mod _pyexpat {
// encoding parameter is currently not used (xml-rs handles encoding from XML declaration)
let _ = args.encoding;
PyExpatLikeXmlParser::new(ns_sep, args.intern, vm)
Ok(PyExpatLikeXmlParser::new(ns_sep, args.intern, vm))
}
// TODO: Tie this exception to the module's state.
+2 -6
View File
@@ -40,6 +40,7 @@ mod decl {
stdlib::time,
};
#[expect(clippy::unnecessary_wraps, reason = "Needs to comply with a signature")]
pub(crate) fn module_exec(vm: &VirtualMachine, module: &Py<PyModule>) -> PyResult<()> {
#[cfg(windows)]
crate::vm::windows::init_winsock();
@@ -275,17 +276,12 @@ mod decl {
#[pyclass]
impl PyPoll {
#[pymethod]
fn register(
&self,
Fildes(fd): Fildes,
eventmask: OptionalArg<EventMask>,
) -> PyResult<()> {
fn register(&self, Fildes(fd): Fildes, eventmask: OptionalArg<EventMask>) {
let mask = match eventmask {
OptionalArg::Present(event_mask) => event_mask.0,
OptionalArg::Missing => DEFAULT_EVENTS,
};
insert_fd(&mut self.fds.lock(), fd, mask);
Ok(())
}
#[pymethod]
+1
View File
@@ -13,6 +13,7 @@ mod _sha256 {
Ok(local_sha256(args, vm)?.into_pyobject(vm))
}
#[expect(clippy::unnecessary_wraps, reason = "Needs to comply with a signature")]
pub(crate) fn module_exec(vm: &VirtualMachine, module: &Py<PyModule>) -> PyResult<()> {
let _ = vm.import("_hashlib", 0);
__module_exec(vm, module);
+1
View File
@@ -13,6 +13,7 @@ mod _sha512 {
Ok(local_sha512(args, vm)?.into_pyobject(vm))
}
#[expect(clippy::unnecessary_wraps, reason = "Needs to comply with a signature")]
pub(crate) fn module_exec(vm: &VirtualMachine, module: &Py<PyModule>) -> PyResult<()> {
let _ = vm.import("_hashlib", 0);
__module_exec(vm, module);
+5 -3
View File
@@ -24,6 +24,7 @@ mod _socket {
};
use rustpython_host_env::os::ErrorExt;
#[expect(clippy::unnecessary_wraps, reason = "Needs to comply with a signature")]
pub(crate) fn module_exec(vm: &VirtualMachine, module: &Py<PyModule>) -> PyResult<()> {
#[cfg(windows)]
crate::vm::windows::init_winsock();
@@ -31,6 +32,7 @@ mod _socket {
__module_exec(vm, module);
Ok(())
}
use core::{
mem::MaybeUninit,
net::{Ipv4Addr, Ipv6Addr, SocketAddr},
@@ -2067,7 +2069,7 @@ mod _socket {
};
// Build ancdata list
let ancdata = Self::parse_ancillary_data(&msg, vm)?;
let ancdata = Self::parse_ancillary_data(&msg, vm);
// Build address tuple
let address = if msg.msg_namelen > 0 {
@@ -2089,7 +2091,7 @@ mod _socket {
/// Parse ancillary data from a received message header
#[cfg(all(unix, not(target_os = "redox")))]
fn parse_ancillary_data(msg: &libc::msghdr, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
fn parse_ancillary_data(msg: &libc::msghdr, vm: &VirtualMachine) -> PyObjectRef {
let mut result = Vec::new();
// Calculate buffer end for truncation handling
@@ -2120,7 +2122,7 @@ mod _socket {
cmsg = unsafe { libc::CMSG_NXTHDR(msg, cmsg) };
}
Ok(vm.ctx.new_list(result).into())
vm.ctx.new_list(result).into()
}
// based on nix's implementation
+25 -41
View File
@@ -1517,7 +1517,7 @@ mod _ssl {
}
#[pymethod]
fn get_ciphers(&self, vm: &VirtualMachine) -> PyResult<PyListRef> {
fn get_ciphers(&self, vm: &VirtualMachine) -> PyListRef {
// Dynamically generate cipher list from rustls ALL_CIPHER_SUITES
// This automatically includes all cipher suites supported by the current rustls version
@@ -1575,7 +1575,7 @@ mod _ssl {
})
.collect::<Vec<_>>();
Ok(PyListRef::from(vm.ctx.new_list(cipher_list)))
PyListRef::from(vm.ctx.new_list(cipher_list))
}
#[pymethod]
@@ -2427,10 +2427,10 @@ mod _ssl {
}
// Create and store a session object after successful handshake
fn create_session_after_handshake(&self, vm: &VirtualMachine) -> PyResult<()> {
fn create_session_after_handshake(&self, vm: &VirtualMachine) {
// Only create session for client-side connections
if self.server_side {
return Ok(());
return;
}
// Check if session already exists
@@ -2438,7 +2438,7 @@ mod _ssl {
if let Some(ref s) = session_opt {
if vm.is_none(s) {
} else {
return Ok(());
return;
}
}
@@ -2489,8 +2489,6 @@ mod _ssl {
let py_session = session.into_pyobject(vm);
*self.session.write() = Some(py_session);
Ok(())
}
// Complete handshake and create session
@@ -2550,7 +2548,7 @@ mod _ssl {
Ok(())
}
fn complete_handshake(&self, vm: &VirtualMachine) -> PyResult<()> {
fn complete_handshake(&self, vm: &VirtualMachine) {
*self.handshake_done.lock() = true;
// Check if session was resumed - get value and release lock immediately
@@ -2580,8 +2578,7 @@ mod _ssl {
let _ = self.track_used_ca_from_capath();
}
self.create_session_after_handshake(vm)?;
Ok(())
self.create_session_after_handshake(vm);
}
// Internal implementation with timeout control
@@ -3435,7 +3432,7 @@ mod _ssl {
if is_client {
// CLIENT is simple - no SNI callback handling needed
handshake_result.map_err(|e| e.into_py_err(vm))?;
self.complete_handshake(vm)?;
self.complete_handshake(vm);
Ok(())
} else {
// Use OpenSSL-compatible handshake for server
@@ -3443,7 +3440,7 @@ mod _ssl {
match handshake_result {
Ok(()) => {
// Handshake completed successfully
self.complete_handshake(vm)?;
self.complete_handshake(vm);
Ok(())
}
Err(SslError::SniCallbackRestart) => {
@@ -3662,13 +3659,13 @@ mod _ssl {
}
#[pymethod]
fn pending(&self) -> PyResult<usize> {
fn pending(&self) -> usize {
// Returns the number of already decrypted bytes available for read
// This is critical for asyncore's readable() method which checks socket.pending() > 0
let mut conn_guard = self.connection.lock();
let conn = match conn_guard.as_mut() {
Some(c) => c,
None => return Ok(0), // No connection established yet
None => return 0, // No connection established yet
};
// Use rustls Reader's fill_buf() to check buffered plaintext
@@ -3676,11 +3673,11 @@ mod _ssl {
// This matches OpenSSL's SSL_pending() behavior
let mut reader = conn.reader();
match reader.fill_buf() {
Ok(buf) => Ok(buf.len()),
Ok(buf) => buf.len(),
Err(_) => {
// WouldBlock or other errors mean no data available
// Return 0 like OpenSSL does when buffer is empty
Ok(0)
0
}
}
}
@@ -3857,9 +3854,8 @@ mod _ssl {
}
#[pygetset(setter)]
fn set_owner(&self, owner: PyObjectRef, _vm: &VirtualMachine) -> PyResult<()> {
fn set_owner(&self, owner: PyObjectRef, _vm: &VirtualMachine) {
*self.owner.write() = Some(owner);
Ok(())
}
#[pygetset]
@@ -3873,7 +3869,7 @@ mod _ssl {
}
#[pygetset(setter)]
fn set_context(&self, value: PyRef<PySSLContext>, _vm: &VirtualMachine) -> PyResult<()> {
fn set_context(&self, value: PyRef<PySSLContext>, _vm: &VirtualMachine) {
// Update context reference immediately
// SSL_set_SSL_CTX allows context changes at any time,
// even after handshake completion
@@ -3881,8 +3877,6 @@ mod _ssl {
// Clear pending context as we've applied the change
*self.pending_context.write() = None;
Ok(())
}
#[pygetset]
@@ -3916,14 +3910,10 @@ mod _ssl {
}
#[pygetset]
fn session(&self, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
fn session(&self, vm: &VirtualMachine) -> PyObjectRef {
// Return the stored session object if any
let sess = self.session.read().clone();
if let Some(s) = sess {
Ok(s)
} else {
Ok(vm.ctx.none())
}
sess.unwrap_or_else(|| vm.ctx.none())
}
#[pygetset(setter)]
@@ -3999,18 +3989,12 @@ mod _ssl {
}
#[pymethod]
fn get_verified_chain(&self, vm: &VirtualMachine) -> PyResult<Option<PyListRef>> {
fn get_verified_chain(&self, vm: &VirtualMachine) -> Option<PyListRef> {
// Get peer certificates (what peer sent during handshake)
let conn_guard = self.connection.lock();
let Some(ref conn) = *conn_guard else {
return Ok(None);
};
let conn = (*conn_guard).as_ref()?;
let peer_certs = conn.peer_certificates();
let Some(peer_certs_slice) = peer_certs else {
return Ok(None);
};
let peer_certs_slice = peer_certs?;
// Build the verified chain using cert module
let ctx_guard = self.context.read();
@@ -4024,7 +4008,7 @@ mod _ssl {
.map(|der_bytes| PySSLCertificate { der_bytes }.into_ref(&vm.ctx).into())
.collect();
Ok(Some(vm.ctx.new_list(cert_list)))
Some(vm.ctx.new_list(cert_list))
}
#[pymethod]
@@ -4655,9 +4639,8 @@ mod _ssl {
}
#[pymethod]
fn write_eof(&self, _vm: &VirtualMachine) -> PyResult<()> {
fn write_eof(&self, _vm: &VirtualMachine) {
*self.eof.write() = true;
Ok(())
}
#[pygetset]
@@ -4816,7 +4799,7 @@ mod _ssl {
}
#[pyfunction]
fn get_default_verify_paths(vm: &VirtualMachine) -> PyResult<PyObjectRef> {
fn get_default_verify_paths(vm: &VirtualMachine) -> PyObjectRef {
// Return default certificate paths as a tuple
// Lib/ssl.py expects: (openssl_cafile_env, openssl_cafile, openssl_capath_env, openssl_capath)
// parts[0] = environment variable name for cafile
@@ -4846,7 +4829,8 @@ mod _ssl {
vm.ctx.new_str("SSL_CERT_DIR").into(), // openssl_capath_env
default_capath.map_or_else(|| vm.ctx.none(), |s| vm.ctx.new_str(s).into()), // openssl_capath
]);
Ok(tuple.into())
tuple.into()
}
#[pyfunction]
+6 -6
View File
@@ -292,8 +292,8 @@ pub(super) fn is_ca_certificate(cert_der: &[u8]) -> bool {
/// Convert an X509Name to Python nested tuple format for SSL certificate dicts
///
/// Format: ((('CN', 'example.com'),), (('O', 'Example Org'),), ...)
fn name_to_py(vm: &VirtualMachine, name: &x509_parser::x509::X509Name<'_>) -> PyResult {
let list: Vec<PyObjectRef> = name
fn name_to_py(vm: &VirtualMachine, name: &x509_parser::x509::X509Name<'_>) -> PyObjectRef {
let list = name
.iter()
.flat_map(|rdn| {
// Each RDN can have multiple attributes
@@ -308,9 +308,9 @@ fn name_to_py(vm: &VirtualMachine, name: &x509_parser::x509::X509Name<'_>) -> Py
})
.collect::<Vec<_>>()
})
.collect();
.collect::<Vec<PyObjectRef>>();
Ok(vm.ctx.new_tuple(list).into())
vm.ctx.new_tuple(list).into()
}
/// Convert DER-encoded certificate to Python dict (for getpeercert with binary_form=False)
@@ -324,8 +324,8 @@ pub(super) fn cert_to_dict(
let dict = vm.ctx.new_dict();
// Subject and Issuer
dict.set_item("subject", name_to_py(vm, cert.subject())?, vm)?;
dict.set_item("issuer", name_to_py(vm, cert.issuer())?, vm)?;
dict.set_item("subject", name_to_py(vm, cert.subject()), vm)?;
dict.set_item("issuer", name_to_py(vm, cert.issuer()), vm)?;
// Version (X.509 v3 = version 2 in the cert, but Python uses 3)
dict.set_item(
+5 -6
View File
@@ -191,9 +191,9 @@ mod unicodedata {
}
#[pymethod]
fn normalize(&self, form: super::NormalizeForm, unistr: PyStrRef) -> PyResult<Wtf8Buf> {
fn normalize(&self, form: super::NormalizeForm, unistr: PyStrRef) -> Wtf8Buf {
let text = unistr.as_wtf8();
let normalized_text = match form {
match form {
Nfc => {
let normalizer = ComposingNormalizerBorrowed::new_nfc();
text.map_utf8(|s| normalizer.normalize_iter(s.chars()))
@@ -214,12 +214,11 @@ mod unicodedata {
text.map_utf8(|s| normalizer.normalize_iter(s.chars()))
.collect()
}
};
Ok(normalized_text)
}
}
#[pymethod]
fn is_normalized(&self, form: super::NormalizeForm, unistr: PyStrRef) -> PyResult<bool> {
fn is_normalized(&self, form: super::NormalizeForm, unistr: PyStrRef) -> bool {
let text = unistr.as_wtf8();
let normalized: Wtf8Buf = match form {
Nfc => {
@@ -243,7 +242,7 @@ mod unicodedata {
.collect()
}
};
Ok(text == &*normalized)
text == &*normalized
}
#[pymethod]
+1 -2
View File
@@ -766,12 +766,11 @@ impl PyAnextAwaitable {
}
#[pymethod]
fn close(&self, vm: &VirtualMachine) -> PyResult<()> {
fn close(&self, vm: &VirtualMachine) {
self.state.store(AwaitableState::Closed);
if let Ok(awaitable) = self.get_awaitable_iter(vm) {
let _ = vm.call_method(&awaitable, "close", ());
}
Ok(())
}
/// Convert StopAsyncIteration to StopIteration(default_value)
+2
View File
@@ -595,6 +595,7 @@ impl Frame {
*storage = value.unwrap_or_none(vm);
}
#[expect(clippy::unnecessary_wraps, reason = "Needs to comply with a signature")]
#[pymember(type = "bool")]
fn f_trace_lines(vm: &VirtualMachine, zelf: PyObjectRef) -> PyResult {
let zelf: FrameRef = zelf.downcast().unwrap_or_else(|_| unreachable!());
@@ -626,6 +627,7 @@ impl Frame {
}
}
#[expect(clippy::unnecessary_wraps, reason = "Needs to comply with a signature")]
#[pymember(type = "bool")]
fn f_trace_opcodes(vm: &VirtualMachine, zelf: PyObjectRef) -> PyResult {
let zelf: FrameRef = zelf.downcast().unwrap_or_else(|_| unreachable!());
+2
View File
@@ -867,6 +867,7 @@ impl PyFunction {
*self.name.lock() = name;
}
#[expect(clippy::unnecessary_wraps, reason = "Needs to comply with a signature")]
#[pymember]
fn __doc__(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult {
// When accessed from instance, obj is the PyFunction instance
@@ -879,6 +880,7 @@ impl PyFunction {
}
}
#[expect(clippy::unnecessary_wraps, reason = "Needs to comply with a signature")]
#[pymember(setter)]
fn set___doc__(vm: &VirtualMachine, zelf: PyObjectRef, value: PySetterValue) -> PyResult<()> {
let zelf: PyRef<Self> = zelf.downcast().unwrap_or_else(|_| unreachable!());
+3 -3
View File
@@ -402,7 +402,7 @@ fn subs_tvars(
}
// CPython's _unpack_args equivalent
fn unpack_args(item: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
fn unpack_args(item: PyObjectRef, vm: &VirtualMachine) -> PyTupleRef {
let mut new_args = Vec::new();
let arg_items = if let Ok(tuple) = item.try_to_ref::<PyTuple>(vm) {
@@ -442,7 +442,7 @@ fn unpack_args(item: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
new_args.push(item);
}
Ok(PyTuple::new_ref(new_args, &vm.ctx))
PyTuple::new_ref(new_args, &vm.ctx)
}
// _Py_subs_parameters
@@ -459,7 +459,7 @@ pub(crate) fn subs_parameters(
}
// Step 1: Unpack args
let mut item: PyObjectRef = unpack_args(item, vm)?.into();
let mut item: PyObjectRef = unpack_args(item, vm).into();
// Step 2: Call __typing_prepare_subst__ on each parameter
for param in parameters.iter() {
+3 -3
View File
@@ -446,7 +446,7 @@ impl PyInt {
zelf: PyRef<Self>,
ndigits: OptionalOption<PyIntRef>,
vm: &VirtualMachine,
) -> PyResult<PyRef<Self>> {
) -> PyRef<Self> {
if let Some(ndigits) = ndigits.flatten() {
let ndigits = ndigits.as_bigint();
// round(12345, -2) == 12300
@@ -477,10 +477,10 @@ impl PyInt {
BigInt::from(0)
};
let rounded = (rounded + correction) * sign;
return Ok(vm.ctx.new_int(rounded));
return vm.ctx.new_int(rounded);
}
}
Ok(zelf)
zelf
}
#[pymethod]
+4 -5
View File
@@ -61,24 +61,23 @@ impl PyMap {
}
#[pymethod]
fn __reduce__(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
fn __reduce__(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyTupleRef {
let cls = zelf.class().to_owned();
let mut vec = vec![zelf.mapper.clone()];
vec.extend(zelf.iterators.iter().map(|o| o.clone().into()));
let tuple_args = vm.ctx.new_tuple(vec);
Ok(if zelf.strict.load(atomic::Ordering::Acquire) {
if zelf.strict.load(atomic::Ordering::Acquire) {
vm.new_tuple((cls, tuple_args, true))
} else {
vm.new_tuple((cls, tuple_args))
})
}
}
#[pymethod]
fn __setstate__(zelf: PyRef<Self>, state: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
fn __setstate__(zelf: PyRef<Self>, state: PyObjectRef, vm: &VirtualMachine) {
if let Ok(obj) = ArgIntoBool::try_from_object(vm, state) {
zelf.strict.store(obj.into(), atomic::Ordering::Release);
}
Ok(())
}
}
+2
View File
@@ -104,6 +104,7 @@ impl Constructor for PyBaseObject {
}
}
#[expect(clippy::unnecessary_wraps, reason = "Needs to comply with a signature")]
pub(crate) fn generic_alloc(cls: PyTypeRef, _nitems: usize, vm: &VirtualMachine) -> PyResult {
// Only create dict if the class has HAS_DICT flag (i.e., __slots__ was not defined
// or __dict__ is in __slots__)
@@ -542,6 +543,7 @@ impl PyBaseObject {
common_reduce(obj, proto, vm)
}
#[expect(clippy::unnecessary_wraps, reason = "Needs to comply with a signature")]
#[pyslot]
fn slot_hash(zelf: &PyObject, _vm: &VirtualMachine) -> PyResult<PyHash> {
Ok(zelf.get_id() as _)
+26 -28
View File
@@ -275,7 +275,7 @@ impl PyRange {
}
#[pymethod]
fn __reversed__(&self, vm: &VirtualMachine) -> PyResult {
fn __reversed__(&self, vm: &VirtualMachine) -> PyObjectRef {
let start = self.start.as_bigint();
let step = self.step.as_bigint();
@@ -285,29 +285,27 @@ impl PyRange {
let start = &new_stop + length.clone() * step;
let step = -step;
Ok(
if let (Some(start), Some(step), Some(_)) =
(start.to_isize(), step.to_isize(), new_stop.to_isize())
{
PyRangeIterator {
index: AtomicCell::new(0),
start,
step,
// Cannot fail. If start, stop and step all successfully convert to isize, then result of zelf.len will
// always fit in a usize.
length: length.to_usize().unwrap_or(0),
}
.into_pyobject(vm)
} else {
PyLongRangeIterator {
index: AtomicCell::new(0),
start,
step,
length,
}
.into_pyobject(vm)
},
)
if let (Some(start), Some(step), Some(_)) =
(start.to_isize(), step.to_isize(), new_stop.to_isize())
{
PyRangeIterator {
index: AtomicCell::new(0),
start,
step,
// Cannot fail. If start, stop and step all successfully convert to isize, then result of zelf.len will
// always fit in a usize.
length: length.to_usize().unwrap_or(0),
}
.into_pyobject(vm)
} else {
PyLongRangeIterator {
index: AtomicCell::new(0),
start,
step,
length,
}
.into_pyobject(vm)
}
}
fn __len__(&self) -> BigInt {
@@ -618,7 +616,7 @@ impl PyLongRangeIterator {
}
#[pymethod]
fn __reduce__(&self, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
fn __reduce__(&self, vm: &VirtualMachine) -> PyTupleRef {
range_iter_reduce(
self.start.clone(),
self.length.clone(),
@@ -680,7 +678,7 @@ impl PyRangeIterator {
}
#[pymethod]
fn __reduce__(&self, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
fn __reduce__(&self, vm: &VirtualMachine) -> PyTupleRef {
range_iter_reduce(
BigInt::from(self.start),
BigInt::from(self.length),
@@ -721,7 +719,7 @@ fn range_iter_reduce(
step: BigInt,
index: usize,
vm: &VirtualMachine,
) -> PyResult<PyTupleRef> {
) -> PyTupleRef {
let iter = builtins_iter(vm);
let stop = start.clone() + length * step.clone();
let range = PyRange {
@@ -729,7 +727,7 @@ fn range_iter_reduce(
stop: PyInt::from(stop).into_ref(&vm.ctx),
step: PyInt::from(step).into_ref(&vm.ctx),
};
Ok(vm.new_tuple((iter, (range,), index)))
vm.new_tuple((iter, (range,), index))
}
// Silently clips state (i.e index) in range [0, usize::MAX].
+8 -14
View File
@@ -509,18 +509,15 @@ fn extract_set(obj: &PyObject) -> Option<&PySetInner> {
})
}
fn reduce_set(
zelf: &PyObject,
vm: &VirtualMachine,
) -> PyResult<(PyTypeRef, PyTupleRef, Option<PyDictRef>)> {
Ok((
fn reduce_set(zelf: &PyObject, vm: &VirtualMachine) -> (PyTypeRef, PyTupleRef, Option<PyDictRef>) {
(
zelf.class().to_owned(),
#[expect(clippy::or_fun_call, reason = "changing this won't compile")]
vm.new_tuple((extract_set(zelf)
.unwrap_or(&PySetInner::default())
.elements(),)),
zelf.dict(),
))
)
}
#[pyclass(
@@ -766,7 +763,7 @@ impl PySet {
fn __reduce__(
zelf: PyRef<Self>,
vm: &VirtualMachine,
) -> PyResult<(PyTypeRef, PyTupleRef, Option<PyDictRef>)> {
) -> (PyTypeRef, PyTupleRef, Option<PyDictRef>) {
reduce_set(zelf.as_ref(), vm)
}
@@ -1140,7 +1137,7 @@ impl PyFrozenSet {
fn __reduce__(
zelf: PyRef<Self>,
vm: &VirtualMachine,
) -> PyResult<(PyTypeRef, PyTupleRef, Option<PyDictRef>)> {
) -> (PyTypeRef, PyTupleRef, Option<PyDictRef>) {
reduce_set(zelf.as_ref(), vm)
}
@@ -1362,12 +1359,9 @@ impl PySetIterator {
}
#[pymethod]
fn __reduce__(
zelf: PyRef<Self>,
vm: &VirtualMachine,
) -> PyResult<(PyObjectRef, (PyObjectRef,))> {
fn __reduce__(zelf: PyRef<Self>, vm: &VirtualMachine) -> (PyObjectRef, (PyObjectRef,)) {
let internal = zelf.internal.lock();
Ok((
(
builtins_iter(vm),
(vm.ctx
.new_list(match &internal.status {
@@ -1377,7 +1371,7 @@ impl PySetIterator {
}
})
.into(),),
))
)
}
}
+4 -4
View File
@@ -248,14 +248,14 @@ impl PySlice {
#[pymethod]
fn __reduce__(
zelf: PyRef<Self>,
) -> PyResult<(
) -> (
PyTypeRef,
(Option<PyObjectRef>, PyObjectRef, Option<PyObjectRef>),
)> {
Ok((
) {
(
zelf.class().to_owned(),
(zelf.start.clone(), zelf.stop.clone(), zelf.step.clone()),
))
)
}
// TODO: Uncomment when Python adds __class_getitem__ to slice
+3 -3
View File
@@ -1559,13 +1559,13 @@ impl PyStr {
}
#[pymethod]
fn __str__(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
fn __str__(zelf: &Py<Self>, vm: &VirtualMachine) -> PyStrRef {
if zelf.class().is(vm.ctx.types.str_type) {
// Already exact str, just return a reference
Ok(zelf.to_owned())
zelf.to_owned()
} else {
// Subclass, create a new exact str
Ok(PyStr::from(zelf.data.clone()).into_ref(&vm.ctx))
PyStr::from(zelf.data.clone()).into_ref(&vm.ctx)
}
}
}
+2 -2
View File
@@ -2667,10 +2667,10 @@ fn subtype_set_dict(obj: PyObjectRef, value: PySetterValue, vm: &VirtualMachine)
}
// subtype_get_weakref
fn subtype_get_weakref(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
fn subtype_get_weakref(obj: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
// Return the first weakref in the weakref list, or None
let weakref = obj.get_weakrefs();
Ok(weakref.unwrap_or_else(|| vm.ctx.none()))
weakref.unwrap_or_else(|| vm.ctx.none())
}
// subtype_set_weakref: __weakref__ is read-only
+5 -5
View File
@@ -47,7 +47,7 @@ impl Constructor for PyZip {
#[pyclass(with(IterNext, Iterable, Constructor), flags(BASETYPE))]
impl PyZip {
#[pymethod]
fn __reduce__(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
fn __reduce__(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyTupleRef {
let cls = zelf.class().to_owned();
let iterators = zelf
.iterators
@@ -55,23 +55,23 @@ impl PyZip {
.map(|obj| obj.clone().into())
.collect::<Vec<_>>();
let tuple_iter = vm.ctx.new_tuple(iterators);
Ok(if zelf.strict.load(atomic::Ordering::Acquire) {
if zelf.strict.load(atomic::Ordering::Acquire) {
vm.new_tuple((cls, tuple_iter, true))
} else {
vm.new_tuple((cls, tuple_iter))
})
}
}
#[pymethod]
fn __setstate__(zelf: PyRef<Self>, state: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
fn __setstate__(zelf: PyRef<Self>, state: PyObjectRef, vm: &VirtualMachine) {
if let Ok(obj) = ArgIntoBool::try_from_object(vm, state) {
zelf.strict.store(obj.into(), atomic::Ordering::Release);
}
Ok(())
}
}
impl SelfIter for PyZip {}
impl IterNext for PyZip {
fn next(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
if zelf.iterators.is_empty() {
+5 -6
View File
@@ -214,31 +214,30 @@ impl CodecsRegistry {
Ok(())
}
pub fn unregister(&self, search_function: PyObjectRef) -> PyResult<()> {
pub fn unregister(&self, search_function: PyObjectRef) {
let mut inner = self.inner.write();
// Do nothing if search_path is not created yet or was cleared.
if inner.search_path.is_empty() {
return Ok(());
return;
}
for (i, item) in inner.search_path.iter().enumerate() {
if item.get_id() == search_function.get_id() {
if !inner.search_cache.is_empty() {
inner.search_cache.clear();
}
inner.search_path.remove(i);
return Ok(());
return;
}
}
Ok(())
}
pub(crate) fn register_manual(&self, name: &str, codec: PyCodec) -> PyResult<()> {
pub(crate) fn register_manual(&self, name: &str, codec: PyCodec) {
let name = normalize_encoding_name(name);
self.inner
.write()
.search_cache
.insert(name.into_owned(), codec);
Ok(())
}
pub fn lookup(&self, encoding: &str, vm: &VirtualMachine) -> PyResult<PyCodec> {
+20 -32
View File
@@ -392,15 +392,6 @@ fn print_source_line<W: Write>(
Ok(())
}
#[cfg(not(feature = "host_env"))]
fn print_source_line<W: Write>(
_output: &mut W,
_filename: &str,
_lineno: usize,
) -> Result<(), W::Error> {
Ok(())
}
/// Print exception occurrence location from traceback element
fn write_traceback_entry<W: Write>(
output: &mut W,
@@ -414,6 +405,8 @@ fn write_traceback_entry<W: Write>(
tb_entry.lineno,
tb_entry.frame.code.obj_name
)?;
#[cfg(feature = "host_env")]
print_source_line(output, filename, tb_entry.lineno.get())?;
Ok(())
@@ -674,22 +667,22 @@ impl PyBaseException {
#[pyclass]
impl Py<PyBaseException> {
#[pymethod]
pub(super) fn __str__(&self, vm: &VirtualMachine) -> PyResult<PyStrRef> {
pub(super) fn __str__(&self, vm: &VirtualMachine) -> PyStrRef {
let str_args = vm.exception_args_as_string(self.args(), true);
Ok(match str_args.into_iter().exactly_one() {
match str_args.into_iter().exactly_one() {
Err(i) if i.len() == 0 => vm.ctx.empty_str.to_owned(),
Ok(s) => s,
Err(i) => PyStr::from(format!("({})", i.format(", "))).into_ref(&vm.ctx),
})
}
}
}
#[pyclass]
impl PyRef<PyBaseException> {
#[pymethod]
fn with_traceback(self, tb: Option<PyTracebackRef>) -> PyResult<Self> {
fn with_traceback(self, tb: Option<PyTracebackRef>) -> Self {
*self.traceback.write() = tb;
Ok(self)
self
}
#[pymethod]
@@ -1092,11 +1085,7 @@ fn make_arg_getter(idx: usize) -> impl Fn(PyBaseExceptionRef) -> Option<PyObject
move |exc| exc.get_arg(idx)
}
fn syntax_error_set_msg(
exc: PyBaseExceptionRef,
value: PySetterValue,
vm: &VirtualMachine,
) -> PyResult<()> {
fn syntax_error_set_msg(exc: PyBaseExceptionRef, value: PySetterValue, vm: &VirtualMachine) {
let mut args = exc.args.write();
let mut new_args = args.as_slice().to_vec();
// Ensure the message slot at index 0 always exists for SyntaxError.args.
@@ -1108,7 +1097,6 @@ fn syntax_error_set_msg(
PySetterValue::Delete => new_args[0] = vm.ctx.none(),
}
*args = PyTuple::new_ref(new_args, &vm.ctx);
Ok(())
}
fn system_exit_code(exc: PyBaseExceptionRef) -> Option<PyObjectRef> {
@@ -1117,11 +1105,11 @@ fn system_exit_code(exc: PyBaseExceptionRef) -> Option<PyObjectRef> {
// - size == 1: code is args[0]
// - size > 1: code is args (the whole tuple)
let args = exc.args.read();
match args.len() {
0 => None,
1 => Some(args.first().unwrap().clone()),
_ => Some(args.as_object().to_owned()),
}
Some(match args.len() {
0 => return None,
1 => args.first().unwrap().clone(),
_ => args.as_object().to_owned(),
})
}
#[cfg(feature = "serde")]
@@ -1712,16 +1700,16 @@ pub(super) mod types {
#[pyexception]
impl PyKeyError {
#[pymethod]
fn __str__(zelf: &Py<PyBaseException>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
fn __str__(zelf: &Py<PyBaseException>, vm: &VirtualMachine) -> PyStrRef {
let args = zelf.args();
Ok(if args.len() == 1 {
if args.len() == 1 {
vm.exception_args_as_string(args, false)
.into_iter()
.exactly_one()
.unwrap()
} else {
zelf.__str__(vm)?
})
zelf.__str__(vm)
}
}
}
@@ -2065,7 +2053,7 @@ pub(super) mod types {
}
// fallback to BaseException.__str__
zelf.__str__(vm)
Ok(zelf.__str__(vm))
}
#[pymethod]
@@ -2334,7 +2322,7 @@ pub(super) mod types {
#[pyexception(with(Initializer))]
impl PySyntaxError {
#[pymethod]
fn __str__(zelf: &Py<PyBaseException>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
fn __str__(zelf: &Py<PyBaseException>, vm: &VirtualMachine) -> PyStrRef {
fn basename(filename: &Wtf8) -> &Wtf8 {
let bytes = filename.as_bytes();
let pos = if cfg!(windows) {
@@ -2387,7 +2375,7 @@ pub(super) mod types {
(None, None) => msg.as_wtf8().to_owned(),
};
Ok(vm.ctx.new_str(msg_with_location_info))
vm.ctx.new_str(msg_with_location_info)
}
}
+3 -3
View File
@@ -2194,7 +2194,7 @@ impl ExecutingFrame<'_> {
self.push_value(set.into());
Ok(None)
}
Instruction::BuildSlice { argc } => self.execute_build_slice(vm, argc.get(arg)),
Instruction::BuildSlice { argc } => Ok(self.execute_build_slice(vm, argc.get(arg))),
/*
Instruction::ToBool => {
dbg!("Shouldn't be called outside of match statements for now")
@@ -6471,7 +6471,7 @@ impl ExecutingFrame<'_> {
&mut self,
vm: &VirtualMachine,
argc: bytecode::BuildSliceArgCount,
) -> FrameResult {
) -> Option<ExecutionResult> {
let step = match argc {
bytecode::BuildSliceArgCount::Two => None,
bytecode::BuildSliceArgCount::Three => Some(self.pop_value()),
@@ -6486,7 +6486,7 @@ impl ExecutingFrame<'_> {
}
.into_ref(&vm.ctx);
self.push_value(obj.into());
Ok(None)
None
}
fn collect_positional_args(&mut self, nargs: u32) -> FuncArgs {
+3 -6
View File
@@ -414,7 +414,7 @@ pub(crate) fn parse(
};
let obj = top.ast_to_object(vm, &source_file);
if type_comments && obj.class().is(pyast::NodeModModule::static_type()) {
let type_ignores = type_ignores_from_source(vm, source)?;
let type_ignores = type_ignores_from_source(vm, source);
let dict = obj.as_object().dict().unwrap();
dict.set_item("type_ignores", vm.ctx.new_list(type_ignores).into(), vm)
.unwrap();
@@ -512,10 +512,7 @@ pub(crate) fn parse_func_type(
Ok(func_type.ast_to_object(vm, &source_file))
}
fn type_ignores_from_source(
vm: &VirtualMachine,
source: &str,
) -> Result<Vec<PyObjectRef>, CompileError> {
fn type_ignores_from_source(vm: &VirtualMachine, source: &str) -> Vec<PyObjectRef> {
let mut ignores = Vec::new();
for (idx, line) in source.lines().enumerate() {
let Some(pos) = line.find("#") else {
@@ -542,7 +539,7 @@ fn type_ignores_from_source(
.unwrap();
ignores.push(node.into());
}
Ok(ignores)
ignores
}
#[cfg(feature = "parser")]
+2 -2
View File
@@ -23,8 +23,8 @@ mod _codecs {
}
#[pyfunction]
fn unregister(search_function: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
vm.state.codec_registry.unregister(search_function)
fn unregister(search_function: PyObjectRef, vm: &VirtualMachine) {
vm.state.codec_registry.unregister(search_function);
}
#[pyfunction]
+8 -7
View File
@@ -251,11 +251,11 @@ mod _collections {
}
#[pymethod]
fn __reversed__(zelf: PyRef<Self>) -> PyResult<PyReverseDequeIterator> {
Ok(PyReverseDequeIterator {
fn __reversed__(zelf: PyRef<Self>) -> PyReverseDequeIterator {
PyReverseDequeIterator {
state: zelf.state.load(),
internal: PyMutex::new(PositionIterInternal::new(zelf, 0)),
})
}
}
#[pymethod]
@@ -688,7 +688,7 @@ mod _collections {
(DequeIterArgs { deque, index }, _kwargs): Self::Args,
_vm: &VirtualMachine,
) -> PyResult<Self> {
let iter = PyDeque::__reversed__(deque)?;
let iter = PyDeque::__reversed__(deque);
if let OptionalArg::Present(index) = index {
let index = max(index, 0) as usize;
iter.internal.lock().position = index;
@@ -708,20 +708,21 @@ mod _collections {
fn __reduce__(
zelf: PyRef<Self>,
vm: &VirtualMachine,
) -> PyResult<(PyTypeRef, (PyDequeRef, PyObjectRef))> {
) -> (PyTypeRef, (PyDequeRef, PyObjectRef)) {
let internal = zelf.internal.lock();
let deque = match &internal.status {
Active(obj) => obj.clone(),
Exhausted => PyDeque::default().into_ref(&vm.ctx),
};
Ok((
(
zelf.class().to_owned(),
(deque, vm.ctx.new_int(internal.position).into()),
))
)
}
}
impl SelfIter for PyReverseDequeIterator {}
impl IterNext for PyReverseDequeIterator {
fn next(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
zelf.internal.lock().next(|deque, pos| {
+21 -28
View File
@@ -547,13 +547,13 @@ pub(crate) mod _ctypes {
name: String,
_load_flags: OptionalArg<i32>,
vm: &VirtualMachine,
) -> PyResult<usize> {
) -> usize {
// TODO: audit functions first
// TODO: load_flags
let cache = library::libcache();
let mut cache_write = cache.write();
let (id, _) = cache_write.get_or_insert_lib(&name, vm).unwrap();
Ok(id)
id
}
#[cfg(not(windows))]
@@ -585,13 +585,9 @@ pub(crate) mod _ctypes {
if handle.is_null() {
let err = unsafe { libc::dlerror() };
let msg = if err.is_null() {
"dlopen() error".to_string()
"dlopen() error"
} else {
unsafe {
core::ffi::CStr::from_ptr(err)
.to_string_lossy()
.into_owned()
}
unsafe { &core::ffi::CStr::from_ptr(err).to_string_lossy() }
};
return Err(vm.new_os_error(msg));
}
@@ -605,22 +601,20 @@ pub(crate) mod _ctypes {
}
#[pyfunction(name = "FreeLibrary")]
fn free_library(handle: usize) -> PyResult<()> {
fn free_library(handle: usize) {
let cache = library::libcache();
let mut cache_write = cache.write();
cache_write.drop_lib(handle);
Ok(())
}
#[cfg(not(windows))]
#[pyfunction]
fn dlclose(handle: usize, _vm: &VirtualMachine) -> PyResult<()> {
fn dlclose(handle: usize, _vm: &VirtualMachine) {
// Remove from cache, which triggers SharedLibrary drop.
// libloading::Library calls dlclose automatically on Drop.
let cache = library::libcache();
let mut cache_write = cache.write();
cache_write.drop_lib(handle);
Ok(())
}
#[cfg(not(windows))]
@@ -747,13 +741,13 @@ pub(crate) mod _ctypes {
#[cfg(target_os = "windows")]
#[pyfunction(name = "_check_HRESULT")]
fn check_hresult(_self: PyObjectRef, hr: i32, _vm: &VirtualMachine) -> PyResult<i32> {
fn check_hresult(_self: PyObjectRef, hr: i32, _vm: &VirtualMachine) -> i32 {
// TODO: fixme
if hr < 0 {
// vm.ctx.new_windows_error(hr)
todo!();
} else {
Ok(hr)
hr
}
}
@@ -963,8 +957,8 @@ pub(crate) mod _ctypes {
#[cfg(windows)]
#[pyfunction]
fn get_last_error() -> PyResult<u32> {
Ok(super::function::get_last_error_value())
fn get_last_error() -> u32 {
super::function::get_last_error_value()
}
#[cfg(windows)]
@@ -1195,7 +1189,7 @@ pub(crate) mod _ctypes {
#[cfg(windows)]
#[pyfunction(name = "FormatError")]
fn format_error_func(code: OptionalArg<u32>, _vm: &VirtualMachine) -> PyResult<String> {
fn format_error_func(code: OptionalArg<u32>, _vm: &VirtualMachine) -> String {
use windows_sys::Win32::Foundation::{GetLastError, LocalFree};
use windows_sys::Win32::System::Diagnostics::Debug::{
FORMAT_MESSAGE_ALLOCATE_BUFFER, FORMAT_MESSAGE_FROM_SYSTEM,
@@ -1220,22 +1214,20 @@ pub(crate) mod _ctypes {
};
if len == 0 || buffer.is_null() {
return Ok("<no description>".to_string());
return "<no description>".to_string();
}
let message = unsafe {
unsafe {
let slice = core::slice::from_raw_parts(buffer, len as usize);
let msg = String::from_utf16_lossy(slice).trim_end().to_string();
LocalFree(buffer as *mut _);
msg
};
Ok(message)
}
}
#[cfg(windows)]
#[pyfunction(name = "CopyComPointer")]
fn copy_com_pointer(src: PyObjectRef, dst: PyObjectRef, vm: &VirtualMachine) -> PyResult<i32> {
fn copy_com_pointer(src: PyObjectRef, dst: PyObjectRef, vm: &VirtualMachine) -> i32 {
use windows_sys::Win32::Foundation::{E_POINTER, S_OK};
// 1. Extract pointer-to-pointer address from dst (byref() result)
@@ -1244,15 +1236,15 @@ pub(crate) mod _ctypes {
let base = if let Some(cdata) = carg.obj.downcast_ref::<PyCData>() {
cdata.buffer.read().as_ptr() as usize
} else {
return Ok(E_POINTER);
return E_POINTER;
};
(base as isize + carg.offset) as usize
} else {
return Ok(E_POINTER);
return E_POINTER;
};
if pdst == 0 {
return Ok(E_POINTER);
return E_POINTER;
}
// 2. Extract COM pointer value from src
@@ -1271,7 +1263,7 @@ pub(crate) mod _ctypes {
0
}
} else {
return Ok(E_POINTER);
return E_POINTER;
};
// 3. Call IUnknown::AddRef if src is non-NULL
@@ -1292,9 +1284,10 @@ pub(crate) mod _ctypes {
*(pdst as *mut usize) = src_ptr;
}
Ok(S_OK)
S_OK
}
#[expect(clippy::unnecessary_wraps, reason = "Needs to comply with a signature")]
pub(crate) fn module_exec(
vm: &VirtualMachine,
module: &Py<crate::builtins::PyModule>,
+30 -23
View File
@@ -613,13 +613,13 @@ impl PyCArray {
};
let buffer = buffer_lock.read();
Self::read_element_from_buffer(
Ok(Self::read_element_from_buffer(
&buffer,
final_offset,
element_size,
type_code.as_deref(),
vm,
)
))
}
/// Helper to read an element value from a buffer at given offset
@@ -629,14 +629,14 @@ impl PyCArray {
element_size: usize,
type_code: Option<&str>,
vm: &VirtualMachine,
) -> PyResult {
) -> PyObjectRef {
match type_code {
Some("c") => {
// Return single byte as bytes
if offset < buffer.len() {
Ok(vm.ctx.new_bytes(vec![buffer[offset]]).into())
vm.ctx.new_bytes(vec![buffer[offset]]).into()
} else {
Ok(vm.ctx.new_bytes(vec![0]).into())
vm.ctx.new_bytes(vec![0]).into()
}
}
Some("u") => {
@@ -645,25 +645,28 @@ impl PyCArray {
let s = char::from_u32(code)
.map(|c| c.to_string())
.unwrap_or_default();
Ok(vm.ctx.new_str(s).into())
vm.ctx.new_str(s).into()
} else {
Ok(vm.ctx.new_str("").into())
vm.ctx.new_str("").into()
}
}
Some("z") => {
// c_char_p: pointer to bytes - dereference to get string
if offset + element_size > buffer.len() {
return Ok(vm.ctx.none());
return vm.ctx.none();
}
let ptr_bytes = &buffer[offset..offset + element_size];
let ptr_val = usize::from_ne_bytes(
ptr_bytes
.try_into()
.unwrap_or([0; core::mem::size_of::<usize>()]),
);
if ptr_val == 0 {
return Ok(vm.ctx.none());
return vm.ctx.none();
}
// Read null-terminated string from pointer address
unsafe {
let ptr = ptr_val as *const u8;
@@ -672,23 +675,26 @@ impl PyCArray {
len += 1;
}
let bytes = core::slice::from_raw_parts(ptr, len);
Ok(vm.ctx.new_bytes(bytes.to_vec()).into())
vm.ctx.new_bytes(bytes.to_vec()).into()
}
}
Some("Z") => {
// c_wchar_p: pointer to wchar_t - dereference to get string
if offset + element_size > buffer.len() {
return Ok(vm.ctx.none());
return vm.ctx.none();
}
let ptr_bytes = &buffer[offset..offset + element_size];
let ptr_val = usize::from_ne_bytes(
ptr_bytes
.try_into()
.unwrap_or([0; core::mem::size_of::<usize>()]),
);
if ptr_val == 0 {
return Ok(vm.ctx.none());
return vm.ctx.none();
}
// Read null-terminated wide string using WCHAR_SIZE
unsafe {
let ptr = ptr_val as *const u8;
@@ -710,8 +716,9 @@ impl PyCArray {
}
pos += WCHAR_SIZE;
}
let s: String = chars.into_iter().collect();
Ok(vm.ctx.new_str(s).into())
vm.ctx.new_str(s).into()
}
}
Some("f") => {
@@ -720,7 +727,7 @@ impl PyCArray {
.first_chunk::<4>()
.copied()
.map_or(0.0, f32::from_ne_bytes);
Ok(vm.ctx.new_float(val as f64).into())
vm.ctx.new_float(val as f64).into()
}
Some("d" | "g") => {
// c_double / c_longdouble - read f64 from first 8 bytes
@@ -728,13 +735,13 @@ impl PyCArray {
.first_chunk::<8>()
.copied()
.map_or(0.0, f64::from_ne_bytes);
Ok(vm.ctx.new_float(val).into())
vm.ctx.new_float(val).into()
}
_ => {
if let Some(bytes) = buffer[offset..].get(..element_size) {
Ok(Self::bytes_to_int(bytes, element_size, type_code, vm))
Self::bytes_to_int(bytes, element_size, type_code, vm)
} else {
Ok(vm.ctx.new_int(0).into())
vm.ctx.new_int(0).into()
}
}
}
@@ -1169,11 +1176,11 @@ impl AsBuffer for PyCArray {
// CharArray and WCharArray getsets - added dynamically via add_getset
// CharArray_get_value
fn char_array_get_value(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
fn char_array_get_value(obj: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
let zelf = obj.downcast_ref::<PyCArray>().unwrap();
let buffer = zelf.0.buffer.read();
let len = buffer.iter().position(|&b| b == 0).unwrap_or(buffer.len());
Ok(vm.ctx.new_bytes(buffer[..len].to_vec()).into())
vm.ctx.new_bytes(buffer[..len].to_vec()).into()
}
// CharArray_set_value
@@ -1197,10 +1204,10 @@ fn char_array_set_value(obj: PyObjectRef, value: PyObjectRef, vm: &VirtualMachin
}
// CharArray_get_raw
fn char_array_get_raw(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
fn char_array_get_raw(obj: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
let zelf = obj.downcast_ref::<PyCArray>().unwrap();
let buffer = zelf.0.buffer.read();
Ok(vm.ctx.new_bytes(buffer.to_vec()).into())
vm.ctx.new_bytes(buffer.to_vec()).into()
}
// CharArray_set_raw
@@ -1222,10 +1229,10 @@ fn char_array_set_raw(
}
// WCharArray_get_value
fn wchar_array_get_value(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
fn wchar_array_get_value(obj: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
let zelf = obj.downcast_ref::<PyCArray>().unwrap();
let buffer = zelf.0.buffer.read();
Ok(vm.ctx.new_str(wstring_from_bytes(&buffer)).into())
vm.ctx.new_str(wstring_from_bytes(&buffer)).into()
}
// WCharArray_set_value
+29 -34
View File
@@ -1072,7 +1072,7 @@ impl PyCData {
let (mut bytes, converted_value) = if let Some(type_code) = &field_type_code {
PyCField::value_to_bytes_for_type(type_code, &value, size, vm)?
} else {
(PyCField::value_to_bytes(&value, size, vm)?, None)
(PyCField::value_to_bytes(&value, size, vm), None)
};
// Swap bytes for opposite endianness
@@ -1479,11 +1479,10 @@ impl Constructor for PyCField {
.try_to_value(vm)?;
// Validate byte_size matches the type
let type_size = super::base::get_field_size(field_type.as_object(), vm)? as isize;
let type_size = super::base::get_field_size(field_type.as_object(), vm) as isize;
if byte_size != type_size {
return Err(vm.new_value_error(format!(
"byte_size {} does not match type size {}",
byte_size, type_size
"byte_size {byte_size} does not match type size {type_size}"
)));
}
@@ -1588,14 +1587,14 @@ impl GetDescriptor for PyCField {
impl PyCField {
/// Convert a Python value to bytes
fn value_to_bytes(value: &PyObject, size: usize, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
fn value_to_bytes(value: &PyObject, size: usize, vm: &VirtualMachine) -> Vec<u8> {
// 1. Handle bytes objects
if let Some(bytes) = value.downcast_ref::<PyBytes>() {
let src = bytes.as_bytes();
let mut result = vec![0u8; size];
let len = core::cmp::min(src.len(), size);
result[..len].copy_from_slice(&src[..len]);
Ok(result)
result
}
// 2. Handle ctypes array instances (copy their buffer)
else if let Some(cdata) = value.downcast_ref::<super::PyCData>() {
@@ -1603,7 +1602,7 @@ impl PyCField {
let mut result = vec![0u8; size];
let len = core::cmp::min(buffer.len(), size);
result[..len].copy_from_slice(&buffer[..len]);
Ok(result)
result
}
// 4. Handle float values (check before int, since float.try_int would truncate)
else if let Some(float_val) = value.downcast_ref::<crate::builtins::PyFloat>() {
@@ -1611,9 +1610,9 @@ impl PyCField {
match size {
4 => {
let val = f as f32;
Ok(val.to_ne_bytes().to_vec())
val.to_ne_bytes().to_vec()
}
8 => Ok(f.to_ne_bytes().to_vec()),
8 => f.to_ne_bytes().to_vec(),
_ => unreachable!("wrong payload size"),
}
}
@@ -1623,24 +1622,24 @@ impl PyCField {
match size {
1 => {
let val = i.to_i8().unwrap_or(0);
Ok(val.to_ne_bytes().to_vec())
val.to_ne_bytes().to_vec()
}
2 => {
let val = i.to_i16().unwrap_or(0);
Ok(val.to_ne_bytes().to_vec())
val.to_ne_bytes().to_vec()
}
4 => {
let val = i.to_i32().unwrap_or(0);
Ok(val.to_ne_bytes().to_vec())
val.to_ne_bytes().to_vec()
}
8 => {
let val = i.to_i64().unwrap_or(0);
Ok(val.to_ne_bytes().to_vec())
val.to_ne_bytes().to_vec()
}
_ => Ok(vec![0u8; size]),
_ => vec![0u8; size],
}
} else {
Ok(vec![0u8; size])
vec![0u8; size]
}
}
@@ -1712,7 +1711,7 @@ impl PyCField {
if vm.is_none(value) {
return Ok((vec![0u8; size], None));
}
Ok((PyCField::value_to_bytes(value, size, vm)?, None))
Ok((PyCField::value_to_bytes(value, size, vm), None))
}
"Z" => {
// c_wchar_p: store pointer to null-terminated wchar_t buffer
@@ -1737,7 +1736,7 @@ impl PyCField {
if vm.is_none(value) {
return Ok((vec![0u8; size], None));
}
Ok((PyCField::value_to_bytes(value, size, vm)?, None))
Ok((PyCField::value_to_bytes(value, size, vm), None))
}
"P" => {
// c_void_p: store integer as pointer
@@ -1753,9 +1752,9 @@ impl PyCField {
if vm.is_none(value) {
return Ok((vec![0u8; size], None));
}
Ok((PyCField::value_to_bytes(value, size, vm)?, None))
Ok((PyCField::value_to_bytes(value, size, vm), None))
}
_ => Ok((PyCField::value_to_bytes(value, size, vm)?, None)),
_ => Ok((PyCField::value_to_bytes(value, size, vm), None)),
}
}
@@ -1947,7 +1946,7 @@ pub(super) fn call_paramfunc(obj: &PyObject, vm: &VirtualMachine) -> PyResult<CA
ParamFunc::Simple => simple_paramfunc(obj, vm),
ParamFunc::Array => array_paramfunc(obj, vm),
ParamFunc::Pointer => pointer_paramfunc(obj, vm),
ParamFunc::Structure | ParamFunc::Union => struct_union_paramfunc(obj, &stg_info, vm),
ParamFunc::Structure | ParamFunc::Union => Ok(struct_union_paramfunc(obj, &stg_info, vm)),
ParamFunc::None => Err(vm.new_type_error("no paramfunc")),
}
}
@@ -2022,36 +2021,32 @@ fn pointer_paramfunc(obj: &PyObject, vm: &VirtualMachine) -> PyResult<CArgObject
}
/// StructUnionType_paramfunc (for both Structure and Union)
fn struct_union_paramfunc(
obj: &PyObject,
stg_info: &StgInfo,
_vm: &VirtualMachine,
) -> PyResult<CArgObject> {
fn struct_union_paramfunc(obj: &PyObject, stg_info: &StgInfo, _vm: &VirtualMachine) -> CArgObject {
// Get buffer pointer
// For large structs (> sizeof(void*)), we'd need to allocate and copy.
// For now, just point to buffer directly and keep obj reference for memory safety.
let buffer = if let Some(cdata) = obj.downcast_ref::<PyCData>() {
cdata.buffer.read()
} else {
return Ok(CArgObject {
return CArgObject {
tag: b'V',
value: FfiArgValue::Pointer(0),
obj: obj.to_owned(),
size: stg_info.size,
offset: 0,
});
};
};
let ptr_val = buffer.as_ptr() as usize;
let size = buffer.len();
Ok(CArgObject {
CArgObject {
tag: b'V',
value: FfiArgValue::Pointer(ptr_val),
obj: obj.to_owned(),
size,
offset: 0,
})
}
}
// FfiArgValue - Owned FFI argument value
@@ -2467,11 +2462,11 @@ pub(super) fn check_other_endian_support(
}
/// Get the size of a ctypes field type
pub(super) fn get_field_size(field_type: &PyObject, vm: &VirtualMachine) -> PyResult<usize> {
pub(super) fn get_field_size(field_type: &PyObject, vm: &VirtualMachine) -> usize {
if let Some(type_obj) = field_type.downcast_ref::<PyType>()
&& let Some(stg_info) = type_obj.stg_info_opt()
{
return Ok(stg_info.size);
return stg_info.size;
}
if let Some(size) = field_type
@@ -2483,7 +2478,7 @@ pub(super) fn get_field_size(field_type: &PyObject, vm: &VirtualMachine) -> PyRe
(s.len() == 1).then(|| super::get_size(&s))
})
{
return Ok(size);
return size;
}
if let Some(s) = field_type
@@ -2493,10 +2488,10 @@ pub(super) fn get_field_size(field_type: &PyObject, vm: &VirtualMachine) -> PyRe
.and_then(|size| size.try_int(vm).ok())
.and_then(|n| n.as_bigint().to_usize())
{
return Ok(s);
return s;
}
Ok(core::mem::size_of::<usize>())
core::mem::size_of::<usize>()
}
/// Get the alignment of a ctypes field type
+1 -2
View File
@@ -1903,14 +1903,13 @@ impl PyCFuncPtr {
}
#[pygetset(name = "argtypes", setter)]
fn set_argtypes(&self, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
fn set_argtypes(&self, value: PyObjectRef, vm: &VirtualMachine) {
if vm.is_none(&value) {
*self.argtypes.write() = None;
} else {
// Store the argtypes object directly as it is
*self.argtypes.write() = Some(value);
}
Ok(())
}
// errcheck getter/setter
+29 -24
View File
@@ -418,7 +418,12 @@ impl PyCPointer {
&& let Ok(type_str) = type_attr.str(vm)
{
let type_code = type_str.to_string();
return Self::read_value_at_address(addr, element_size, Some(&type_code), vm);
return Ok(Self::read_value_at_address(
addr,
element_size,
Some(&type_code),
vm,
));
}
// Complex type: create instance that references the memory directly (not a copy)
@@ -658,55 +663,55 @@ impl PyCPointer {
size: usize,
type_code: Option<&str>,
vm: &VirtualMachine,
) -> PyResult {
) -> PyObjectRef {
unsafe {
let ptr = addr as *const u8;
match type_code {
// Single-byte types don't need read_unaligned
Some("c") => Ok(vm.ctx.new_bytes(vec![*ptr]).into()),
Some("b") => Ok(vm.ctx.new_int(*ptr as i8 as i32).into()),
Some("B") => Ok(vm.ctx.new_int(*ptr as i32).into()),
Some("c") => vm.ctx.new_bytes(vec![*ptr]).into(),
Some("b") => vm.ctx.new_int(*ptr as i8 as i32).into(),
Some("B") => vm.ctx.new_int(*ptr as i32).into(),
// Multi-byte types need read_unaligned for safety on strict-alignment architectures
Some("h") => Ok(vm
Some("h") => vm
.ctx
.new_int(core::ptr::read_unaligned(ptr as *const i16) as i32)
.into()),
Some("H") => Ok(vm
.into(),
Some("H") => vm
.ctx
.new_int(core::ptr::read_unaligned(ptr as *const u16) as i32)
.into()),
Some("i" | "l") => Ok(vm
.into(),
Some("i" | "l") => vm
.ctx
.new_int(core::ptr::read_unaligned(ptr as *const i32))
.into()),
Some("I" | "L") => Ok(vm
.into(),
Some("I" | "L") => vm
.ctx
.new_int(core::ptr::read_unaligned(ptr as *const u32))
.into()),
Some("q") => Ok(vm
.into(),
Some("q") => vm
.ctx
.new_int(core::ptr::read_unaligned(ptr as *const i64))
.into()),
Some("Q") => Ok(vm
.into(),
Some("Q") => vm
.ctx
.new_int(core::ptr::read_unaligned(ptr as *const u64))
.into()),
Some("f") => Ok(vm
.into(),
Some("f") => vm
.ctx
.new_float(core::ptr::read_unaligned(ptr as *const f32) as f64)
.into()),
Some("d" | "g") => Ok(vm
.into(),
Some("d" | "g") => vm
.ctx
.new_float(core::ptr::read_unaligned(ptr as *const f64))
.into()),
Some("P" | "z" | "Z") => Ok(vm
.into(),
Some("P" | "z" | "Z") => vm
.ctx
.new_int(core::ptr::read_unaligned(ptr as *const usize))
.into()),
.into(),
_ => {
// Default: read as bytes
let bytes = core::slice::from_raw_parts(ptr, size).to_vec();
Ok(vm.ctx.new_bytes(bytes).into())
vm.ctx.new_bytes(bytes).into()
}
}
}
+1 -1
View File
@@ -331,7 +331,7 @@ impl PyCStructType {
}
// Get size and alignment of the field type
let size = super::base::get_field_size(&field_type, vm)?;
let size = super::base::get_field_size(&field_type, vm);
let field_align = super::base::get_field_align(&field_type, vm);
// Calculate effective alignment (PyCField_FromDesc)
+1 -1
View File
@@ -229,7 +229,7 @@ impl PyCUnionType {
super::base::check_other_endian_support(&field_type, vm)?;
}
let size = super::base::get_field_size(&field_type, vm)?;
let size = super::base::get_field_size(&field_type, vm);
let field_align = super::base::get_field_align(&field_type, vm);
// Calculate effective alignment
+3 -4
View File
@@ -177,7 +177,7 @@ mod _functools {
}
#[pymethod]
fn __reduce__(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult {
fn __reduce__(zelf: &Py<Self>, vm: &VirtualMachine) -> PyObjectRef {
let inner = zelf.inner.read();
let partial_type = zelf.class();
@@ -193,14 +193,13 @@ mod _functools {
inner.keywords.clone().into(),
dict_obj,
]);
Ok(vm
.ctx
vm.ctx
.new_tuple(vec![
partial_type.to_owned().into(),
vm.ctx.new_tuple(vec![inner.func.clone()]).into(),
state.into(),
])
.into())
.into()
}
#[pymethod]
+5 -7
View File
@@ -183,8 +183,8 @@ mod _imp {
use version::PYC_MAGIC_NUMBER_TOKEN;
#[pyfunction]
const fn extension_suffixes() -> PyResult<Vec<PyObjectRef>> {
Ok(Vec::new())
const fn extension_suffixes() -> Vec<PyObjectRef> {
Vec::new()
}
#[pyfunction]
@@ -297,14 +297,12 @@ mod _imp {
}
#[pyfunction]
fn _frozen_module_names(vm: &VirtualMachine) -> PyResult<Vec<PyObjectRef>> {
let names = vm
.state
fn _frozen_module_names(vm: &VirtualMachine) -> Vec<PyObjectRef> {
vm.state
.frozen
.keys()
.map(|&name| vm.ctx.new_utf8_str(name).into())
.collect();
Ok(names)
.collect()
}
#[allow(clippy::type_complexity)]
+6 -14
View File
@@ -1591,14 +1591,7 @@ mod _io {
let zelf: PyRef<Self> = zelf.try_into_value(vm)?;
let (raw, BufferSize { buffer_size }): (PyObjectRef, _) =
args.bind(vm).map_err(|e| {
let str_repr = e
.__str__(vm)
.as_ref()
.map_or_else(
|_| "<error getting exception str>".as_ref(),
|s| s.as_wtf8(),
)
.to_owned();
let str_repr = e.__str__(vm).as_wtf8().to_owned();
let msg = format!("{}() {}", Self::CLASS_NAME, str_repr);
vm.new_exception_msg(e.class().to_owned(), msg.into())
})?;
@@ -5310,6 +5303,10 @@ mod _io {
}
}
#[cfg_attr(
not(feature = "host_env"),
expect(clippy::unnecessary_wraps, reason = "Needs to comply with a signature")
)]
pub(crate) fn module_exec(vm: &VirtualMachine, module: &Py<PyModule>) -> PyResult<()> {
// Call auto-generated initialization first
__module_exec(vm, module);
@@ -5953,13 +5950,8 @@ mod fileio {
/// fileio_dealloc_warn in Modules/_io/fileio.c
#[pymethod(name = "_dealloc_warn")]
fn _dealloc_warn_method(
zelf: &Py<Self>,
source: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<()> {
fn _dealloc_warn_method(zelf: &Py<Self>, source: PyObjectRef, vm: &VirtualMachine) {
Self::dealloc_warn(zelf, source, vm);
Ok(())
}
}
+6 -6
View File
@@ -54,13 +54,13 @@ mod _operator {
}
#[pyfunction]
fn is_(a: PyObjectRef, b: PyObjectRef) -> PyResult<bool> {
Ok(a.is(&b))
fn is_(a: PyObjectRef, b: PyObjectRef) -> bool {
a.is(&b)
}
#[pyfunction]
fn is_not(a: PyObjectRef, b: PyObjectRef) -> PyResult<bool> {
Ok(!a.is(&b))
fn is_not(a: PyObjectRef, b: PyObjectRef) -> bool {
!a.is(&b)
}
#[pyfunction]
@@ -363,11 +363,11 @@ mod _operator {
}
#[pymethod]
fn __reduce__(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<(PyTypeRef, PyTupleRef)> {
fn __reduce__(zelf: PyRef<Self>, vm: &VirtualMachine) -> (PyTypeRef, PyTupleRef) {
let attrs = vm
.ctx
.new_tuple(zelf.attrs.iter().map(|v| v.clone().into()).collect());
Ok((zelf.class().to_owned(), attrs))
(zelf.class().to_owned(), attrs)
}
// Go through dotted parts of string and call getattr on whatever is returned.
+1
View File
@@ -703,6 +703,7 @@ pub(crate) mod _signal {
WAKEUP.store(INVALID_WAKEUP, Ordering::Relaxed);
}
#[expect(clippy::unnecessary_wraps, reason = "Needs to comply with a signature")]
pub(crate) fn module_exec(
vm: &VirtualMachine,
module: &Py<crate::builtins::PyModule>,
+11 -17
View File
@@ -172,9 +172,8 @@ mod _symtable {
}
#[pygetset]
fn children(&self, vm: &VirtualMachine) -> PyResult<Vec<PyObjectRef>> {
let children = self
.symtable
fn children(&self, vm: &VirtualMachine) -> Vec<PyObjectRef> {
self.symtable
.sub_tables
.iter()
.flat_map(|t| {
@@ -186,8 +185,7 @@ mod _symtable {
}
})
.map(|t| to_py_symbol_table(t.clone()).into_pyobject(vm))
.collect();
Ok(children)
.collect()
}
#[pygetset]
@@ -196,24 +194,22 @@ mod _symtable {
}
#[pygetset]
fn identifiers(&self, vm: &VirtualMachine) -> PyResult<Vec<PyObjectRef>> {
let symbols = self
.symtable
fn identifiers(&self, vm: &VirtualMachine) -> Vec<PyObjectRef> {
self.symtable
.symbols
.keys()
.map(|s| vm.ctx.new_str(s.as_str()).into())
.collect();
Ok(symbols)
.collect()
}
#[pygetset]
fn symbols(&self, vm: &VirtualMachine) -> PyResult<PyDictRef> {
fn symbols(&self, vm: &VirtualMachine) -> PyDictRef {
let dict = vm.ctx.new_dict();
for (name, symbol) in &self.symtable.symbols {
dict.set_item(name, vm.new_pyobj(symbol.flags.bits()), vm)
.unwrap();
}
Ok(dict)
dict
}
#[pygetset]
@@ -319,13 +315,11 @@ mod _symtable {
}
#[pymethod]
fn get_namespaces(&self, vm: &VirtualMachine) -> PyResult<Vec<PyObjectRef>> {
let namespaces = self
.namespaces
fn get_namespaces(&self, vm: &VirtualMachine) -> Vec<PyObjectRef> {
self.namespaces
.iter()
.map(|table| to_py_symbol_table(table.clone()).into_pyobject(vm))
.collect();
Ok(namespaces)
.collect()
}
#[pymethod]
+2 -4
View File
@@ -140,11 +140,10 @@ pub(crate) mod _thread {
#[cfg(unix)]
#[pymethod]
fn _at_fork_reinit(&self, _vm: &VirtualMachine) -> PyResult<()> {
fn _at_fork_reinit(&self, _vm: &VirtualMachine) {
// Overwrite lock state to unlocked. Do NOT call unlock() here —
// after fork(), unlock_slow() would try to unpark stale waiters.
unsafe { rustpython_common::lock::zero_reinit_after_fork(&self.mu) };
Ok(())
}
#[pymethod]
@@ -235,12 +234,11 @@ pub(crate) mod _thread {
#[cfg(unix)]
#[pymethod]
fn _at_fork_reinit(&self, _vm: &VirtualMachine) -> PyResult<()> {
fn _at_fork_reinit(&self, _vm: &VirtualMachine) {
// Overwrite lock state to unlocked. Do NOT call unlock() here —
// after fork(), unlock_slow() would try to unpark stale waiters.
self.count.store(0, core::sync::atomic::Ordering::Relaxed);
unsafe { rustpython_common::lock::zero_reinit_after_fork(&self.mu) };
Ok(())
}
#[pymethod]
+6 -5
View File
@@ -44,13 +44,13 @@ pub(crate) mod decl {
}
#[pyfunction(name = "override")]
pub(crate) fn r#override(func: PyObjectRef, vm: &VirtualMachine) -> PyResult {
pub(crate) fn r#override(func: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
// Set __override__ attribute to True
// Skip the attribute silently if it is not writable.
// AttributeError happens if the object has __slots__ or a
// read-only property, TypeError if it's a builtin class.
let _ = func.set_attr("__override__", vm.ctx.true_value.clone(), vm);
Ok(func)
func
}
#[pyclass(no_attr, name = "NoDefaultType", module = "typing")]
@@ -302,11 +302,11 @@ pub(crate) mod decl {
}
#[pygetset]
fn evaluate_value(&self, vm: &VirtualMachine) -> PyResult {
fn evaluate_value(&self, vm: &VirtualMachine) -> PyObjectRef {
if self.is_lazy {
return Ok(self.compute_value.clone());
return self.compute_value.clone();
}
Ok(const_evaluator_alloc(self.compute_value.clone(), vm))
const_evaluator_alloc(self.compute_value.clone(), vm)
}
/// Check type_params ordering: non-default params must precede default params.
@@ -492,6 +492,7 @@ pub(crate) mod decl {
Ok(PyTuple::new_ref(new_params, &vm.ctx))
}
#[expect(clippy::unnecessary_wraps, reason = "Needs to comply with a signature")]
pub(crate) fn module_exec(
vm: &VirtualMachine,
module: &Py<crate::builtins::PyModule>,
+2 -2
View File
@@ -928,7 +928,7 @@ mod builtins {
}
#[pyfunction]
fn oct(number: ArgIndex, vm: &VirtualMachine) -> PyResult {
fn oct(number: ArgIndex, vm: &VirtualMachine) -> PyObjectRef {
let number = number.into_int_ref();
let n = number.as_bigint();
let s = if n.is_negative() {
@@ -937,7 +937,7 @@ mod builtins {
format!("0o{n:o}")
};
Ok(vm.ctx.new_str(s).into())
vm.ctx.new_str(s).into()
}
#[pyfunction]
+4 -4
View File
@@ -956,12 +956,12 @@ mod decl {
}
impl PyItertoolsTeeData {
fn new(iterable: PyIter, _vm: &VirtualMachine) -> PyResult<PyRc<Self>> {
Ok(PyRc::new(Self {
fn new(iterable: PyIter, _vm: &VirtualMachine) -> PyRc<Self> {
PyRc::new(Self {
iterable,
values: PyMutex::new(vec![]),
running: AtomicBool::new(false),
}))
})
}
fn get_item(&self, vm: &VirtualMachine, index: usize) -> PyResult<PyIterReturn> {
@@ -1043,7 +1043,7 @@ mod decl {
return vm.call_special_method(&iterator, identifier!(vm, __copy__), ());
}
Ok(Self {
tee_data: PyItertoolsTeeData::new(iterator, vm)?,
tee_data: PyItertoolsTeeData::new(iterator, vm),
index: AtomicCell::new(0),
}
.into_ref_with_type(vm, class.to_owned())?
+3 -3
View File
@@ -127,13 +127,13 @@ pub(crate) mod module {
}
#[pyfunction]
pub(super) fn _supports_virtual_terminal() -> PyResult<bool> {
pub(super) fn _supports_virtual_terminal() -> bool {
let mut mode = 0;
let handle = unsafe { Console::GetStdHandle(Console::STD_ERROR_HANDLE) };
if unsafe { Console::GetConsoleMode(handle, &mut mode) } == 0 {
return Ok(false);
return false;
}
Ok(mode & Console::ENABLE_VIRTUAL_TERMINAL_PROCESSING != 0)
mode & Console::ENABLE_VIRTUAL_TERMINAL_PROCESSING != 0
}
#[derive(FromArgs)]
+26 -21
View File
@@ -637,13 +637,13 @@ pub(super) mod _os {
#[pyclass(flags(DISALLOW_INSTANTIATION), with(Representable))]
impl DirEntry {
#[pygetset]
fn name(&self, vm: &VirtualMachine) -> PyResult {
Ok(self.mode.process_path(&self.file_name, vm))
fn name(&self, vm: &VirtualMachine) -> PyObjectRef {
self.mode.process_path(&self.file_name, vm)
}
#[pygetset]
fn path(&self, vm: &VirtualMachine) -> PyResult {
Ok(self.mode.process_path(&self.pathval, vm))
fn path(&self, vm: &VirtualMachine) -> PyObjectRef {
self.mode.process_path(&self.pathval, vm)
}
/// Build the DirFd to use for stat calls.
@@ -837,30 +837,30 @@ pub(super) mod _os {
#[cfg(unix)]
#[pymethod]
fn inode(&self, _vm: &VirtualMachine) -> PyResult<u64> {
Ok(self.ino.load())
fn inode(&self, _vm: &VirtualMachine) -> u64 {
self.ino.load()
}
#[cfg(not(any(unix, windows)))]
#[pymethod]
fn inode(&self, _vm: &VirtualMachine) -> PyResult<Option<u64>> {
Ok(self.ino.load())
fn inode(&self, _vm: &VirtualMachine) -> Option<u64> {
self.ino.load()
}
#[cfg(not(windows))]
#[pymethod]
const fn is_junction(&self, _vm: &VirtualMachine) -> PyResult<bool> {
Ok(false)
const fn is_junction(&self, _vm: &VirtualMachine) -> bool {
false
}
#[cfg(windows)]
#[pymethod]
fn is_junction(&self, _vm: &VirtualMachine) -> PyResult<bool> {
Ok(junction::exists(self.pathval.clone()).unwrap_or(false))
fn is_junction(&self, _vm: &VirtualMachine) -> bool {
junction::exists(self.pathval.clone()).unwrap_or(false)
}
#[pymethod]
fn __fspath__(&self, vm: &VirtualMachine) -> PyResult {
fn __fspath__(&self, vm: &VirtualMachine) -> PyObjectRef {
self.path(vm)
}
@@ -941,6 +941,7 @@ pub(super) mod _os {
Err(vm.new_type_error("cannot pickle 'ScandirIterator' object"))
}
}
impl Destructor for ScandirIterator {
fn del(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<()> {
// Emit ResourceWarning if the iterator is not yet exhausted/closed
@@ -956,7 +957,9 @@ pub(super) mod _os {
Ok(())
}
}
impl SelfIter for ScandirIterator {}
impl IterNext for ScandirIterator {
fn next(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
let entryref: &mut Option<fs::ReadDir> = &mut zelf.entries.write();
@@ -1904,6 +1907,10 @@ pub(super) mod _os {
#[pyclass(with(PyStructSequence))]
impl PyTimesResult {}
#[allow(
clippy::unnecessary_wraps,
reason = "Can return an error on some platforms"
)]
#[cfg(all(any(unix, windows), not(target_os = "redox")))]
#[pyfunction]
fn times(vm: &VirtualMachine) -> PyResult {
@@ -2107,14 +2114,14 @@ pub(super) mod _os {
}
#[pyfunction]
fn device_encoding(fd: i32, _vm: &VirtualMachine) -> PyResult<Option<String>> {
fn device_encoding(fd: i32, _vm: &VirtualMachine) -> Option<String> {
if !isatty(fd) {
return Ok(None);
return None;
}
cfg_select! {
any(target_os = "android", target_os = "redox") => {
Ok(Some("UTF-8".to_owned()))
Some("UTF-8".to_owned())
}
windows => {
use windows_sys::Win32::System::Console;
@@ -2124,19 +2131,17 @@ pub(super) mod _os {
_ => 0,
};
Ok(Some(format!("cp{cp}")))
Some(format!("cp{cp}"))
}
_ => {
let encoding = unsafe {
Some(unsafe {
let encoding = libc::nl_langinfo(libc::CODESET);
if encoding.is_null() || encoding.read() == b'\0' as libc::c_char {
"UTF-8".to_owned()
} else {
core::ffi::CStr::from_ptr(encoding).to_string_lossy().into_owned()
}
};
Ok(Some(encoding))
})
}
}
}
+2 -2
View File
@@ -98,7 +98,7 @@ mod pwd {
// TODO: maybe merge this functionality into nix?
#[cfg(not(target_os = "android"))]
#[pyfunction]
fn getpwall(vm: &VirtualMachine) -> PyResult<Vec<PyObjectRef>> {
fn getpwall(vm: &VirtualMachine) -> Vec<PyObjectRef> {
// setpwent, getpwent, etc are not thread safe. Could use fgetpwent_r, but this is easier
static GETPWALL: parking_lot::Mutex<()> = parking_lot::Mutex::new(());
let _guard = GETPWALL.lock();
@@ -112,6 +112,6 @@ mod pwd {
}
unsafe { libc::endpwent() };
Ok(list)
list
}
}
+13 -15
View File
@@ -85,16 +85,15 @@ pub mod sys {
#[pyclass]
impl BootstrapStderr {
#[pymethod]
fn write(&self, s: PyStrRef) -> PyResult<usize> {
fn write(&self, s: PyStrRef) -> usize {
let bytes = s.as_bytes();
let _ = std::io::stderr().write_all(bytes);
Ok(bytes.len())
bytes.len()
}
#[pymethod]
fn flush(&self) -> PyResult<()> {
fn flush(&self) {
let _ = std::io::stderr().flush();
Ok(())
}
}
@@ -997,14 +996,14 @@ pub mod sys {
}
#[pyfunction]
fn _getframemodulename(depth: OptionalArg<usize>, vm: &VirtualMachine) -> PyResult {
fn _getframemodulename(depth: OptionalArg<usize>, vm: &VirtualMachine) -> PyObjectRef {
let depth = depth.into_option().unwrap_or(0);
// Get the frame at the specified depth
let func_obj = {
let frames = vm.frames.borrow();
if depth >= frames.len() {
return Ok(vm.ctx.none());
return vm.ctx.none();
}
let idx = frames.len() - depth - 1;
// SAFETY: the FrameRef is alive on the call stack while it's in the Vec
@@ -1014,15 +1013,14 @@ pub mod sys {
// If the frame has a function object, return its __module__ attribute
if let Some(func_obj) = func_obj {
match func_obj.get_attr(identifier!(vm, __module__), vm) {
Ok(module) => Ok(module),
Err(_) => {
func_obj
.get_attr(identifier!(vm, __module__), vm)
.unwrap_or_else(
// CPython clears the error and returns None
Ok(vm.ctx.none())
}
}
|_| vm.ctx.none(),
)
} else {
Ok(vm.ctx.none())
vm.ctx.none()
}
}
@@ -1075,8 +1073,8 @@ pub mod sys {
/// Stub for non-threading builds - returns empty dict
#[cfg(not(feature = "threading"))]
#[pyfunction]
fn _current_frames(vm: &VirtualMachine) -> PyResult<PyDictRef> {
Ok(vm.ctx.new_dict())
fn _current_frames(vm: &VirtualMachine) -> PyDictRef {
vm.ctx.new_dict()
}
#[pyfunction]
+1
View File
@@ -1002,6 +1002,7 @@ pub mod decl {
#[allow(unused_imports)]
use super::platform::*;
#[expect(clippy::unnecessary_wraps, reason = "Needs to comply with a signature")]
pub(crate) fn module_exec(
vm: &VirtualMachine,
module: &Py<crate::builtins::PyModule>,
+36 -26
View File
@@ -173,40 +173,46 @@ pub(crate) mod typevar {
}
#[pygetset]
fn evaluate_bound(&self, vm: &VirtualMachine) -> PyResult {
fn evaluate_bound(&self, vm: &VirtualMachine) -> PyObjectRef {
if !vm.is_none(&self.evaluate_bound) {
return Ok(self.evaluate_bound.clone());
return self.evaluate_bound.clone();
}
let bound = self.bound.lock();
if !vm.is_none(&bound) {
return Ok(const_evaluator_alloc(bound.clone(), vm));
return const_evaluator_alloc(bound.clone(), vm);
}
Ok(vm.ctx.none())
vm.ctx.none()
}
#[pygetset]
fn evaluate_constraints(&self, vm: &VirtualMachine) -> PyResult {
fn evaluate_constraints(&self, vm: &VirtualMachine) -> PyObjectRef {
if !vm.is_none(&self.evaluate_constraints) {
return Ok(self.evaluate_constraints.clone());
return self.evaluate_constraints.clone();
}
let constraints = self.constraints.lock();
if !vm.is_none(&constraints) {
return Ok(const_evaluator_alloc(constraints.clone(), vm));
return const_evaluator_alloc(constraints.clone(), vm);
}
Ok(vm.ctx.none())
vm.ctx.none()
}
#[pygetset]
fn evaluate_default(&self, vm: &VirtualMachine) -> PyResult {
fn evaluate_default(&self, vm: &VirtualMachine) -> PyObjectRef {
let evaluator = self.evaluate_default.lock().clone();
if !vm.is_none(&evaluator) {
return Ok(evaluator);
return evaluator;
}
let default_value = self.default_value.lock().clone();
if !default_value.is(&vm.ctx.typing_no_default) {
return Ok(const_evaluator_alloc(default_value, vm));
return const_evaluator_alloc(default_value, vm);
}
Ok(vm.ctx.none())
vm.ctx.none()
}
#[pymethod]
@@ -480,21 +486,21 @@ pub(crate) mod typevar {
}
#[pygetset]
fn args(zelf: crate::PyRef<Self>, vm: &VirtualMachine) -> PyResult {
fn args(zelf: crate::PyRef<Self>, vm: &VirtualMachine) -> PyObjectRef {
let self_obj: PyObjectRef = zelf.into();
let psa = ParamSpecArgs {
__origin__: self_obj,
};
Ok(psa.into_ref(&vm.ctx).into())
psa.into_ref(&vm.ctx).into()
}
#[pygetset]
fn kwargs(zelf: crate::PyRef<Self>, vm: &VirtualMachine) -> PyResult {
fn kwargs(zelf: crate::PyRef<Self>, vm: &VirtualMachine) -> PyObjectRef {
let self_obj: PyObjectRef = zelf.into();
let psk = ParamSpecKwargs {
__origin__: self_obj,
};
Ok(psk.into_ref(&vm.ctx).into())
psk.into_ref(&vm.ctx).into()
}
#[pygetset]
@@ -539,21 +545,23 @@ pub(crate) mod typevar {
}
#[pygetset]
fn evaluate_default(&self, vm: &VirtualMachine) -> PyResult {
fn evaluate_default(&self, vm: &VirtualMachine) -> PyObjectRef {
let evaluator = self.evaluate_default.lock().clone();
if !vm.is_none(&evaluator) {
return Ok(evaluator);
return evaluator;
}
let default_value = self.default_value.lock().clone();
if !default_value.is(&vm.ctx.typing_no_default) {
return Ok(const_evaluator_alloc(default_value, vm));
return const_evaluator_alloc(default_value, vm);
}
Ok(vm.ctx.none())
vm.ctx.none()
}
#[pymethod]
fn __reduce__(&self) -> PyResult {
Ok(self.name.clone())
fn __reduce__(&self) -> PyObjectRef {
self.name.clone()
}
#[pymethod]
@@ -748,16 +756,18 @@ pub(crate) mod typevar {
}
#[pygetset]
fn evaluate_default(&self, vm: &VirtualMachine) -> PyResult {
fn evaluate_default(&self, vm: &VirtualMachine) -> PyObjectRef {
let evaluator = self.evaluate_default.lock().clone();
if !vm.is_none(&evaluator) {
return Ok(evaluator);
return evaluator;
}
let default_value = self.default_value.lock().clone();
if !default_value.is(&vm.ctx.typing_no_default) {
return Ok(const_evaluator_alloc(default_value, vm));
return const_evaluator_alloc(default_value, vm);
}
Ok(vm.ctx.none())
vm.ctx.none()
}
#[pymethod]
+6 -6
View File
@@ -195,15 +195,15 @@ mod winreg {
}
#[pymethod]
fn Detach(&self) -> PyResult<usize> {
fn Detach(&self) -> usize {
// Atomically swap the handle with null and return the old value
let old_hkey = self.hkey.swap(core::ptr::null_mut());
Ok(old_hkey as usize)
old_hkey as usize
}
#[pymethod]
fn __enter__(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
Ok(zelf)
fn __enter__(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
zelf
}
#[pymethod]
@@ -216,8 +216,8 @@ mod winreg {
}
#[pymethod]
fn __str__(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyRef<PyStr>> {
Ok(vm.ctx.new_str(format!("<PyHkey:{:p}>", zelf.hkey.load())))
fn __str__(zelf: &Py<Self>, vm: &VirtualMachine) -> PyRef<PyStr> {
vm.ctx.new_str(format!("<PyHkey:{:p}>", zelf.hkey.load()))
}
}
+2 -1
View File
@@ -579,7 +579,8 @@ fn bool_wrapper(num: PyNumber<'_>, vm: &VirtualMachine) -> PyResult<bool> {
Ok(crate::builtins::bool_::get_value(&result))
}
// PyObject_SelfIter in CPython
/// PyObject_SelfIter in CPython
#[expect(clippy::unnecessary_wraps, reason = "Needs to comply with a signature")]
const fn self_iter(zelf: PyObjectRef, _vm: &VirtualMachine) -> PyResult {
Ok(zelf)
}
+4 -4
View File
@@ -846,7 +846,7 @@ impl VirtualMachine {
let codec_info = getregentry.call((), self)?;
self.state
.codec_registry
.register_manual("ascii", codec_info.try_into_value(self)?)?;
.register_manual("ascii", codec_info.try_into_value(self)?);
// Register utf-8 encoding (also as "utf8" alias since normalize_encoding_name
// maps "utf-8" → "utf_8" but leaves "utf8" as-is)
@@ -857,10 +857,10 @@ impl VirtualMachine {
let utf8_codec: crate::codecs::PyCodec = codec_info.try_into_value(self)?;
self.state
.codec_registry
.register_manual("utf-8", utf8_codec.clone())?;
.register_manual("utf-8", utf8_codec.clone());
self.state
.codec_registry
.register_manual("utf8", utf8_codec)?;
.register_manual("utf8", utf8_codec);
// Register latin-1 / iso8859-1 aliases needed very early for stdio
// bootstrap (e.g. PYTHONIOENCODING=latin-1).
@@ -873,7 +873,7 @@ impl VirtualMachine {
for name in ["latin-1", "latin_1", "latin1", "iso8859-1", "iso8859_1"] {
self.state
.codec_registry
.register_manual(name, latin1_codec.clone())?;
.register_manual(name, latin1_codec.clone());
}
}
Ok(())
+21 -21
View File
@@ -114,7 +114,7 @@ fn get_warnings_attr(
vm: &VirtualMachine,
attr_name: &'static PyStrInterned,
try_import: bool,
) -> PyResult<Option<PyObjectRef>> {
) -> Option<PyObjectRef> {
let module = if try_import
&& !vm
.state
@@ -123,38 +123,36 @@ fn get_warnings_attr(
{
match vm.import("warnings", 0) {
Ok(module) => module,
Err(_) => return Ok(None),
Err(_) => return None,
}
} else {
match vm.sys_module.get_attr(identifier!(vm, modules), vm) {
Ok(modules) => match modules.get_item(vm.ctx.intern_str("warnings"), vm) {
Ok(module) => module,
Err(_) => return Ok(None),
Err(_) => return None,
},
Err(_) => return Ok(None),
Err(_) => return None,
}
};
match module.get_attr(attr_name, vm) {
Ok(attr) => Ok(Some(attr)),
Err(_) => Ok(None),
}
module.get_attr(attr_name, vm).ok()
}
/// Get the warnings filters list from sys.modules['warnings'].filters,
/// falling back to vm.state.warnings.filters.
fn get_warnings_filters(vm: &VirtualMachine) -> PyResult<PyListRef> {
if let Some(filters_obj) = get_warnings_attr(vm, identifier!(&vm.ctx, filters), false)?
fn get_warnings_filters(vm: &VirtualMachine) -> PyListRef {
if let Some(filters_obj) = get_warnings_attr(vm, identifier!(&vm.ctx, filters), false)
&& let Ok(filters) = filters_obj.try_into_value::<PyListRef>(vm)
{
return Ok(filters);
return filters;
}
Ok(vm.state.warnings.filters.clone())
vm.state.warnings.filters.clone()
}
/// Get the default action from sys.modules['warnings']._defaultaction,
/// falling back to vm.state.warnings.default_action.
fn get_default_action(vm: &VirtualMachine) -> PyResult<PyObjectRef> {
if let Some(action) = get_warnings_attr(vm, identifier!(&vm.ctx, defaultaction), false)? {
if let Some(action) = get_warnings_attr(vm, identifier!(&vm.ctx, defaultaction), false) {
if !action.class().is(vm.ctx.types.str_type) {
return Err(vm.new_type_error(format!(
"_warnings.defaultaction must be a string, not '{}'",
@@ -169,7 +167,7 @@ fn get_default_action(vm: &VirtualMachine) -> PyResult<PyObjectRef> {
/// Get the once registry from sys.modules['warnings']._onceregistry,
/// falling back to vm.state.warnings.once_registry.
fn get_once_registry(vm: &VirtualMachine) -> PyResult<PyObjectRef> {
if let Some(registry) = get_warnings_attr(vm, identifier!(&vm.ctx, onceregistry), false)? {
if let Some(registry) = get_warnings_attr(vm, identifier!(&vm.ctx, onceregistry), false) {
if !registry.class().is(vm.ctx.types.dict_type) {
return Err(vm.new_type_error(format!(
"_warnings.onceregistry must be a dict, not '{}'",
@@ -265,7 +263,7 @@ fn get_filter(
module: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult {
let filters = get_warnings_filters(vm)?;
let filters = get_warnings_filters(vm);
// filters could change while we are iterating over it.
// Re-check list length each iteration (matches C behavior).
@@ -463,15 +461,17 @@ fn call_show_warning(
source: Option<PyObjectRef>,
vm: &VirtualMachine,
) -> PyResult<()> {
let Some(show_fn) =
get_warnings_attr(vm, identifier!(&vm.ctx, _showwarnmsg), source.is_some())?
let Some(show_fn) = get_warnings_attr(vm, identifier!(&vm.ctx, _showwarnmsg), source.is_some())
else {
return show_warning(filename, lineno, text, category, source_line, vm);
show_warning(filename, lineno, text, category, source_line, vm);
return Ok(());
};
if !show_fn.is_callable() {
return Err(vm.new_type_error("warnings._showwarnmsg() must be set to a callable"));
}
let Some(warnmsg_cls) = get_warnings_attr(vm, identifier!(&vm.ctx, WarningMessage), false)?
let Some(warnmsg_cls) = get_warnings_attr(vm, identifier!(&vm.ctx, WarningMessage), false)
else {
return Err(vm.new_runtime_error("unable to get warnings.WarningMessage"));
};
@@ -488,6 +488,7 @@ fn call_show_warning(
],
vm,
)?;
show_fn.call((msg,), vm)?;
Ok(())
}
@@ -499,7 +500,7 @@ fn show_warning(
category: PyTypeRef,
_source_line: Option<PyObjectRef>,
vm: &VirtualMachine,
) -> PyResult<()> {
) {
let stderr = crate::stdlib::sys::PyStderr(vm);
writeln!(
stderr,
@@ -509,7 +510,6 @@ fn show_warning(
category.name(),
text
);
Ok(())
}
/// Check if a frame's filename starts with any of the given prefixes.
+1
View File
@@ -26,6 +26,7 @@ mod _window {
use super::{js_module, wasm_builtins};
use rustpython_vm::{Py, PyPayload, PyResult, VirtualMachine, builtins::PyModule};
#[expect(clippy::unnecessary_wraps, reason = "Needs to comply with a signature")]
pub(crate) fn module_exec(vm: &VirtualMachine, module: &Py<PyModule>) -> PyResult<()> {
__module_exec(vm, module);
extend_module!(vm, module, {