mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Apply clippy suggestions to switch to let chains (#6126)
This commit is contained in:
53 files changed
+637
-666
No files matched your search
+1
-1
@@ -138,7 +138,7 @@ members = [
|
||||
version = "0.4.0"
|
||||
authors = ["RustPython Team"]
|
||||
edition = "2024"
|
||||
rust-version = "1.87.0"
|
||||
rust-version = "1.89.0"
|
||||
repository = "https://github.com/RustPython/RustPython"
|
||||
license = "MIT"
|
||||
|
||||
|
||||
@@ -81,14 +81,13 @@ pub mod windows {
|
||||
.next_back()
|
||||
.and_then(|s| String::from_utf16(s).ok());
|
||||
|
||||
if let Some(file_extension) = file_extension {
|
||||
if file_extension.eq_ignore_ascii_case("exe")
|
||||
if let Some(file_extension) = file_extension
|
||||
&& (file_extension.eq_ignore_ascii_case("exe")
|
||||
|| file_extension.eq_ignore_ascii_case("bat")
|
||||
|| file_extension.eq_ignore_ascii_case("cmd")
|
||||
|| file_extension.eq_ignore_ascii_case("com")
|
||||
{
|
||||
self.st_mode |= 0o111;
|
||||
}
|
||||
|| file_extension.eq_ignore_ascii_case("com"))
|
||||
{
|
||||
self.st_mode |= 0o111;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -942,12 +942,11 @@ impl Compiler {
|
||||
if stack_size > self.symbol_table_stack.len() {
|
||||
// We might be in a situation where symbol table isn't pushed yet
|
||||
// In this case, check the parent symbol table
|
||||
if let Some(parent_table) = self.symbol_table_stack.last() {
|
||||
if let Some(symbol) = parent_table.lookup(¤t_obj_name) {
|
||||
if symbol.scope == SymbolScope::GlobalExplicit {
|
||||
force_global = true;
|
||||
}
|
||||
}
|
||||
if let Some(parent_table) = self.symbol_table_stack.last()
|
||||
&& let Some(symbol) = parent_table.lookup(¤t_obj_name)
|
||||
&& symbol.scope == SymbolScope::GlobalExplicit
|
||||
{
|
||||
force_global = true;
|
||||
}
|
||||
} else if let Some(_current_table) = self.symbol_table_stack.last() {
|
||||
// Mangle the name if necessary (for private names in classes)
|
||||
@@ -956,10 +955,10 @@ impl Compiler {
|
||||
// Look up in parent symbol table to check scope
|
||||
if self.symbol_table_stack.len() >= 2 {
|
||||
let parent_table = &self.symbol_table_stack[self.symbol_table_stack.len() - 2];
|
||||
if let Some(symbol) = parent_table.lookup(&mangled_name) {
|
||||
if symbol.scope == SymbolScope::GlobalExplicit {
|
||||
force_global = true;
|
||||
}
|
||||
if let Some(symbol) = parent_table.lookup(&mangled_name)
|
||||
&& symbol.scope == SymbolScope::GlobalExplicit
|
||||
{
|
||||
force_global = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3528,10 +3527,10 @@ impl Compiler {
|
||||
}
|
||||
|
||||
// Validate rest pattern: '_' cannot be used as a rest target
|
||||
if let Some(rest) = star_target {
|
||||
if rest.as_str() == "_" {
|
||||
return Err(self.error(CodegenErrorType::SyntaxError("invalid syntax".to_string())));
|
||||
}
|
||||
if let Some(rest) = star_target
|
||||
&& rest.as_str() == "_"
|
||||
{
|
||||
return Err(self.error(CodegenErrorType::SyntaxError("invalid syntax".to_string())));
|
||||
}
|
||||
|
||||
// Step 1: Check if subject is a mapping
|
||||
@@ -5377,11 +5376,11 @@ impl Compiler {
|
||||
}
|
||||
|
||||
fn emit_return_value(&mut self) {
|
||||
if let Some(inst) = self.current_block().instructions.last_mut() {
|
||||
if let Instruction::LoadConst { idx } = inst.instr {
|
||||
inst.instr = Instruction::ReturnConst { idx };
|
||||
return;
|
||||
}
|
||||
if let Some(inst) = self.current_block().instructions.last_mut()
|
||||
&& let Instruction::LoadConst { idx } = inst.instr
|
||||
{
|
||||
inst.instr = Instruction::ReturnConst { idx };
|
||||
return;
|
||||
}
|
||||
emit!(self, Instruction::ReturnValue)
|
||||
}
|
||||
|
||||
@@ -240,21 +240,21 @@ fn analyze_symbol_table(symbol_table: &mut SymbolTable) -> SymbolTableResult {
|
||||
*/
|
||||
fn drop_class_free(symbol_table: &mut SymbolTable) {
|
||||
// Check if __class__ is used as a free variable
|
||||
if let Some(class_symbol) = symbol_table.symbols.get("__class__") {
|
||||
if class_symbol.scope == SymbolScope::Free {
|
||||
symbol_table.needs_class_closure = true;
|
||||
// Note: In CPython, the symbol is removed from the free set,
|
||||
// but in RustPython we handle this differently during code generation
|
||||
}
|
||||
if let Some(class_symbol) = symbol_table.symbols.get("__class__")
|
||||
&& class_symbol.scope == SymbolScope::Free
|
||||
{
|
||||
symbol_table.needs_class_closure = true;
|
||||
// Note: In CPython, the symbol is removed from the free set,
|
||||
// but in RustPython we handle this differently during code generation
|
||||
}
|
||||
|
||||
// Check if __classdict__ is used as a free variable
|
||||
if let Some(classdict_symbol) = symbol_table.symbols.get("__classdict__") {
|
||||
if classdict_symbol.scope == SymbolScope::Free {
|
||||
symbol_table.needs_classdict = true;
|
||||
// Note: In CPython, the symbol is removed from the free set,
|
||||
// but in RustPython we handle this differently during code generation
|
||||
}
|
||||
if let Some(classdict_symbol) = symbol_table.symbols.get("__classdict__")
|
||||
&& classdict_symbol.scope == SymbolScope::Free
|
||||
{
|
||||
symbol_table.needs_classdict = true;
|
||||
// Note: In CPython, the symbol is removed from the free set,
|
||||
// but in RustPython we handle this differently during code generation
|
||||
}
|
||||
}
|
||||
|
||||
@@ -733,12 +733,12 @@ impl SymbolTableBuilder {
|
||||
|
||||
fn scan_statement(&mut self, statement: &Stmt) -> SymbolTableResult {
|
||||
use ruff_python_ast::*;
|
||||
if let Stmt::ImportFrom(StmtImportFrom { module, names, .. }) = &statement {
|
||||
if module.as_ref().map(|id| id.as_str()) == Some("__future__") {
|
||||
for feature in names {
|
||||
if &feature.name == "annotations" {
|
||||
self.future_annotations = true;
|
||||
}
|
||||
if let Stmt::ImportFrom(StmtImportFrom { module, names, .. }) = &statement
|
||||
&& module.as_ref().map(|id| id.as_str()) == Some("__future__")
|
||||
{
|
||||
for feature in names {
|
||||
if &feature.name == "annotations" {
|
||||
self.future_annotations = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1032,26 +1032,23 @@ impl SymbolTableBuilder {
|
||||
use ruff_python_ast::*;
|
||||
|
||||
// Check for expressions not allowed in type parameters scope
|
||||
if let Some(table) = self.tables.last() {
|
||||
if table.typ == CompilerScope::TypeParams {
|
||||
if let Some(keyword) = match expression {
|
||||
Expr::Yield(_) | Expr::YieldFrom(_) => Some("yield"),
|
||||
Expr::Await(_) => Some("await"),
|
||||
Expr::Named(_) => Some("named"),
|
||||
_ => None,
|
||||
} {
|
||||
return Err(SymbolTableError {
|
||||
error: format!(
|
||||
"{keyword} expression cannot be used within a type parameter"
|
||||
),
|
||||
location: Some(
|
||||
self.source_file
|
||||
.to_source_code()
|
||||
.source_location(expression.range().start()),
|
||||
),
|
||||
});
|
||||
}
|
||||
if let Some(table) = self.tables.last()
|
||||
&& table.typ == CompilerScope::TypeParams
|
||||
&& let Some(keyword) = match expression {
|
||||
Expr::Yield(_) | Expr::YieldFrom(_) => Some("yield"),
|
||||
Expr::Await(_) => Some("await"),
|
||||
Expr::Named(_) => Some("named"),
|
||||
_ => None,
|
||||
}
|
||||
{
|
||||
return Err(SymbolTableError {
|
||||
error: format!("{keyword} expression cannot be used within a type parameter"),
|
||||
location: Some(
|
||||
self.source_file
|
||||
.to_source_code()
|
||||
.source_location(expression.range().start()),
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
match expression {
|
||||
|
||||
@@ -140,10 +140,10 @@ impl CompilationSource {
|
||||
let mut code_map = HashMap::new();
|
||||
let paths = fs::read_dir(path)
|
||||
.or_else(|e| {
|
||||
if cfg!(windows) {
|
||||
if let Ok(real_path) = fs::read_to_string(path.canonicalize().unwrap()) {
|
||||
return fs::read_dir(real_path.trim());
|
||||
}
|
||||
if cfg!(windows)
|
||||
&& let Ok(real_path) = fs::read_to_string(path.canonicalize().unwrap())
|
||||
{
|
||||
return fs::read_dir(real_path.trim());
|
||||
}
|
||||
Err(e)
|
||||
})
|
||||
@@ -195,14 +195,14 @@ impl CompilationSource {
|
||||
})
|
||||
};
|
||||
let code = compile_path(&path).or_else(|e| {
|
||||
if cfg!(windows) {
|
||||
if let Ok(real_path) = fs::read_to_string(path.canonicalize().unwrap()) {
|
||||
let joined = path.parent().unwrap().join(real_path.trim());
|
||||
if joined.exists() {
|
||||
return compile_path(&joined);
|
||||
} else {
|
||||
return Err(e);
|
||||
}
|
||||
if cfg!(windows)
|
||||
&& let Ok(real_path) = fs::read_to_string(path.canonicalize().unwrap())
|
||||
{
|
||||
let joined = path.parent().unwrap().join(real_path.trim());
|
||||
if joined.exists() {
|
||||
return compile_path(&joined);
|
||||
} else {
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
Err(e)
|
||||
|
||||
@@ -175,10 +175,11 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
|
||||
let target_block = self.get_or_create_block(label);
|
||||
|
||||
// If the current block isn't terminated, jump:
|
||||
if let Some(cur) = self.builder.current_block() {
|
||||
if cur != target_block && self.builder.func.layout.last_inst(cur).is_none() {
|
||||
self.builder.ins().jump(target_block, &[]);
|
||||
}
|
||||
if let Some(cur) = self.builder.current_block()
|
||||
&& cur != target_block
|
||||
&& self.builder.func.layout.last_inst(cur).is_none()
|
||||
{
|
||||
self.builder.ins().jump(target_block, &[]);
|
||||
}
|
||||
// Switch to the target block
|
||||
if self.builder.current_block() != Some(target_block) {
|
||||
@@ -207,10 +208,10 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
|
||||
}
|
||||
|
||||
// After processing, if the current block is unterminated, insert a trap or fallthrough
|
||||
if let Some(cur) = self.builder.current_block() {
|
||||
if self.builder.func.layout.last_inst(cur).is_none() {
|
||||
self.builder.ins().trap(TrapCode::user(0).unwrap());
|
||||
}
|
||||
if let Some(cur) = self.builder.current_block()
|
||||
&& self.builder.func.layout.last_inst(cur).is_none()
|
||||
{
|
||||
self.builder.ins().trap(TrapCode::user(0).unwrap());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
+9
-9
@@ -9,15 +9,15 @@ fn main() {
|
||||
process_python_libs("./Lib/**/*");
|
||||
}
|
||||
|
||||
if cfg!(windows) {
|
||||
if let Ok(real_path) = std::fs::read_to_string("Lib") {
|
||||
let canonicalized_path = std::fs::canonicalize(real_path)
|
||||
.expect("failed to resolve RUSTPYTHONPATH during build time");
|
||||
println!(
|
||||
"cargo:rustc-env=win_lib_path={}",
|
||||
canonicalized_path.to_str().unwrap()
|
||||
);
|
||||
}
|
||||
if cfg!(windows)
|
||||
&& let Ok(real_path) = std::fs::read_to_string("Lib")
|
||||
{
|
||||
let canonicalized_path = std::fs::canonicalize(real_path)
|
||||
.expect("failed to resolve RUSTPYTHONPATH during build time");
|
||||
println!(
|
||||
"cargo:rustc-env=win_lib_path={}",
|
||||
canonicalized_path.to_str().unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-4
@@ -67,10 +67,11 @@ fn shell_exec(
|
||||
{
|
||||
let loc = raw_location.start().to_usize();
|
||||
let mut iter = source.chars();
|
||||
if let Some(quote) = iter.nth(loc) {
|
||||
if iter.next() == Some(quote) && iter.next() == Some(quote) {
|
||||
return ShellExecResult::ContinueLine;
|
||||
}
|
||||
if let Some(quote) = iter.nth(loc)
|
||||
&& iter.next() == Some(quote)
|
||||
&& iter.next() == Some(quote)
|
||||
{
|
||||
return ShellExecResult::ContinueLine;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -378,12 +378,11 @@ mod _contextvars {
|
||||
let ctx = ctxs.last()?;
|
||||
let cached_ptr = zelf.cached.as_ptr();
|
||||
debug_assert!(!cached_ptr.is_null());
|
||||
if let Some(cached) = unsafe { &*cached_ptr } {
|
||||
if zelf.cached_id.load(Ordering::SeqCst) == ctx.get_id()
|
||||
&& cached.idx + 1 == ctxs.len()
|
||||
{
|
||||
return Some(cached.object.clone());
|
||||
}
|
||||
if let Some(cached) = unsafe { &*cached_ptr }
|
||||
&& zelf.cached_id.load(Ordering::SeqCst) == ctx.get_id()
|
||||
&& cached.idx + 1 == ctxs.len()
|
||||
{
|
||||
return Some(cached.object.clone());
|
||||
}
|
||||
let vars = ctx.borrow_vars();
|
||||
let obj = vars.get(zelf)?;
|
||||
|
||||
+10
-10
@@ -518,11 +518,11 @@ mod math {
|
||||
#[pyfunction]
|
||||
fn ceil(x: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
let result_or_err = try_magic_method(identifier!(vm, __ceil__), vm, &x);
|
||||
if result_or_err.is_err() {
|
||||
if let Some(v) = x.try_float_opt(vm) {
|
||||
let v = try_f64_to_bigint(v?.to_f64().ceil(), vm)?;
|
||||
return Ok(vm.ctx.new_int(v).into());
|
||||
}
|
||||
if result_or_err.is_err()
|
||||
&& let Some(v) = x.try_float_opt(vm)
|
||||
{
|
||||
let v = try_f64_to_bigint(v?.to_f64().ceil(), vm)?;
|
||||
return Ok(vm.ctx.new_int(v).into());
|
||||
}
|
||||
result_or_err
|
||||
}
|
||||
@@ -530,11 +530,11 @@ mod math {
|
||||
#[pyfunction]
|
||||
fn floor(x: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
let result_or_err = try_magic_method(identifier!(vm, __floor__), vm, &x);
|
||||
if result_or_err.is_err() {
|
||||
if let Some(v) = x.try_float_opt(vm) {
|
||||
let v = try_f64_to_bigint(v?.to_f64().floor(), vm)?;
|
||||
return Ok(vm.ctx.new_int(v).into());
|
||||
}
|
||||
if result_or_err.is_err()
|
||||
&& let Some(v) = x.try_float_opt(vm)
|
||||
{
|
||||
let v = try_f64_to_bigint(v?.to_f64().floor(), vm)?;
|
||||
return Ok(vm.ctx.new_int(v).into());
|
||||
}
|
||||
result_or_err
|
||||
}
|
||||
|
||||
+13
-14
@@ -86,23 +86,22 @@ mod _scproxy {
|
||||
.and_then(|v| v.downcast::<CFNumber>())
|
||||
.and_then(|v| v.to_i32())
|
||||
.unwrap_or(0);
|
||||
if enabled {
|
||||
if let Some(host) = proxy_dict
|
||||
if enabled
|
||||
&& let Some(host) = proxy_dict
|
||||
.find(host_key)
|
||||
.and_then(|v| v.downcast::<CFString>())
|
||||
{
|
||||
let h = std::borrow::Cow::<str>::from(&host);
|
||||
let v = if let Some(port) = proxy_dict
|
||||
.find(port_key)
|
||||
.and_then(|v| v.downcast::<CFNumber>())
|
||||
.and_then(|v| v.to_i32())
|
||||
{
|
||||
let h = std::borrow::Cow::<str>::from(&host);
|
||||
let v = if let Some(port) = proxy_dict
|
||||
.find(port_key)
|
||||
.and_then(|v| v.downcast::<CFNumber>())
|
||||
.and_then(|v| v.to_i32())
|
||||
{
|
||||
format!("http://{h}:{port}")
|
||||
} else {
|
||||
format!("http://{h}")
|
||||
};
|
||||
result.set_item(proto, vm.new_pyobj(v), vm)?;
|
||||
}
|
||||
format!("http://{h}:{port}")
|
||||
} else {
|
||||
format!("http://{h}")
|
||||
};
|
||||
result.set_item(proto, vm.new_pyobj(v), vm)?;
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
|
||||
@@ -244,10 +244,10 @@ mod decl {
|
||||
Either::A(f) => f,
|
||||
Either::B(i) => i as f64,
|
||||
});
|
||||
if let Some(timeout) = timeout {
|
||||
if timeout < 0.0 {
|
||||
return Err(vm.new_value_error("timeout must be positive"));
|
||||
}
|
||||
if let Some(timeout) = timeout
|
||||
&& timeout < 0.0
|
||||
{
|
||||
return Err(vm.new_value_error("timeout must be positive"));
|
||||
}
|
||||
let deadline = timeout.map(|s| time::time(vm).unwrap() + s);
|
||||
|
||||
|
||||
@@ -2277,15 +2277,16 @@ mod _socket {
|
||||
0,
|
||||
)));
|
||||
}
|
||||
if let c::AF_INET | c::AF_UNSPEC = af {
|
||||
if let Ok(addr) = name.parse::<Ipv4Addr>() {
|
||||
return Ok(SocketAddr::V4(net::SocketAddrV4::new(addr, 0)));
|
||||
}
|
||||
if let c::AF_INET | c::AF_UNSPEC = af
|
||||
&& let Ok(addr) = name.parse::<Ipv4Addr>()
|
||||
{
|
||||
return Ok(SocketAddr::V4(net::SocketAddrV4::new(addr, 0)));
|
||||
}
|
||||
if matches!(af, c::AF_INET | c::AF_UNSPEC) && !name.contains('%') {
|
||||
if let Ok(addr) = name.parse::<Ipv6Addr>() {
|
||||
return Ok(SocketAddr::V6(net::SocketAddrV6::new(addr, 0, 0, 0)));
|
||||
}
|
||||
if matches!(af, c::AF_INET | c::AF_UNSPEC)
|
||||
&& !name.contains('%')
|
||||
&& let Ok(addr) = name.parse::<Ipv6Addr>()
|
||||
{
|
||||
return Ok(SocketAddr::V6(net::SocketAddrV6::new(addr, 0, 0, 0)));
|
||||
}
|
||||
let hints = dns_lookup::AddrInfoHints {
|
||||
address: af,
|
||||
|
||||
@@ -571,10 +571,10 @@ mod _sqlite {
|
||||
|
||||
unsafe extern "C" fn progress_callback(data: *mut c_void) -> c_int {
|
||||
let (callable, vm) = unsafe { (*data.cast::<Self>()).retrieve() };
|
||||
if let Ok(val) = callable.call((), vm) {
|
||||
if let Ok(val) = val.is_true(vm) {
|
||||
return val as c_int;
|
||||
}
|
||||
if let Ok(val) = callable.call((), vm)
|
||||
&& let Ok(val) = val.is_true(vm)
|
||||
{
|
||||
return val as c_int;
|
||||
}
|
||||
-1
|
||||
}
|
||||
@@ -1718,10 +1718,10 @@ mod _sqlite {
|
||||
|
||||
#[pymethod]
|
||||
fn close(&self) {
|
||||
if let Some(inner) = self.inner.lock().take() {
|
||||
if let Some(stmt) = inner.statement {
|
||||
stmt.lock().reset();
|
||||
}
|
||||
if let Some(inner) = self.inner.lock().take()
|
||||
&& let Some(stmt) = inner.statement
|
||||
{
|
||||
stmt.lock().reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -26,16 +26,16 @@ mod syslog {
|
||||
use libc::{LOG_AUTHPRIV, LOG_CRON, LOG_PERROR};
|
||||
|
||||
fn get_argv(vm: &VirtualMachine) -> Option<PyStrRef> {
|
||||
if let Some(argv) = vm.state.settings.argv.first() {
|
||||
if !argv.is_empty() {
|
||||
return Some(
|
||||
PyStr::from(match argv.find('\\') {
|
||||
Some(value) => &argv[value..],
|
||||
None => argv,
|
||||
})
|
||||
.into_ref(&vm.ctx),
|
||||
);
|
||||
}
|
||||
if let Some(argv) = vm.state.settings.argv.first()
|
||||
&& !argv.is_empty()
|
||||
{
|
||||
return Some(
|
||||
PyStr::from(match argv.find('\\') {
|
||||
Some(value) => &argv[value..],
|
||||
None => argv,
|
||||
})
|
||||
.into_ref(&vm.ctx),
|
||||
);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
@@ -121,10 +121,10 @@ mod unicodedata {
|
||||
|
||||
#[pymethod]
|
||||
fn lookup(&self, name: PyStrRef, vm: &VirtualMachine) -> PyResult<String> {
|
||||
if let Some(character) = unicode_names2::character(name.as_str()) {
|
||||
if self.check_age(character.into()) {
|
||||
return Ok(character.to_string());
|
||||
}
|
||||
if let Some(character) = unicode_names2::character(name.as_str())
|
||||
&& self.check_age(character.into())
|
||||
{
|
||||
return Ok(character.to_string());
|
||||
}
|
||||
Err(vm.new_lookup_error(format!("undefined character name '{name}'")))
|
||||
}
|
||||
@@ -138,12 +138,11 @@ mod unicodedata {
|
||||
) -> PyResult {
|
||||
let c = self.extract_char(character, vm)?;
|
||||
|
||||
if let Some(c) = c {
|
||||
if self.check_age(c) {
|
||||
if let Some(name) = c.to_char().and_then(unicode_names2::name) {
|
||||
return Ok(vm.ctx.new_str(name.to_string()).into());
|
||||
}
|
||||
}
|
||||
if let Some(c) = c
|
||||
&& self.check_age(c)
|
||||
&& let Some(name) = c.to_char().and_then(unicode_names2::name)
|
||||
{
|
||||
return Ok(vm.ctx.new_str(name.to_string()).into());
|
||||
}
|
||||
default.ok_or_else(|| vm.new_value_error("no such name"))
|
||||
}
|
||||
|
||||
+10
-10
@@ -193,11 +193,11 @@ mod zlib {
|
||||
fn decompressobj(args: DecompressobjArgs, vm: &VirtualMachine) -> PyResult<PyDecompress> {
|
||||
let mut decompress = InitOptions::new(args.wbits.value, vm)?.decompress();
|
||||
let zdict = args.zdict.into_option();
|
||||
if let Some(dict) = &zdict {
|
||||
if args.wbits.value < 0 {
|
||||
dict.with_ref(|d| decompress.set_dictionary(d))
|
||||
.map_err(|_| new_zlib_error("failed to set dictionary", vm))?;
|
||||
}
|
||||
if let Some(dict) = &zdict
|
||||
&& args.wbits.value < 0
|
||||
{
|
||||
dict.with_ref(|d| decompress.set_dictionary(d))
|
||||
.map_err(|_| new_zlib_error("failed to set dictionary", vm))?;
|
||||
}
|
||||
let inner = PyDecompressInner {
|
||||
decompress: Some(DecompressWithDict { decompress, zdict }),
|
||||
@@ -573,11 +573,11 @@ mod zlib {
|
||||
fn py_new(cls: PyTypeRef, args: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
let mut decompress = InitOptions::new(args.wbits.value, vm)?.decompress();
|
||||
let zdict = args.zdict.into_option();
|
||||
if let Some(dict) = &zdict {
|
||||
if args.wbits.value < 0 {
|
||||
dict.with_ref(|d| decompress.set_dictionary(d))
|
||||
.map_err(|_| new_zlib_error("failed to set dictionary", vm))?;
|
||||
}
|
||||
if let Some(dict) = &zdict
|
||||
&& args.wbits.value < 0
|
||||
{
|
||||
dict.with_ref(|d| decompress.set_dictionary(d))
|
||||
.map_err(|_| new_zlib_error("failed to set dictionary", vm))?;
|
||||
}
|
||||
let inner = DecompressState::new(DecompressWithDict { decompress, zdict }, vm);
|
||||
Self {
|
||||
|
||||
@@ -367,14 +367,12 @@ impl GetDescriptor for PyMemberDescriptor {
|
||||
// return the class's docstring if available
|
||||
// When accessed from class (not instance), check if the class has
|
||||
// an attribute with the same name as this member descriptor
|
||||
if let Some(cls) = cls {
|
||||
if let Ok(cls_type) = cls.downcast::<PyType>() {
|
||||
if let Some(interned) = vm.ctx.interned_str(descr.member.name.as_str()) {
|
||||
if let Some(attr) = cls_type.attributes.read().get(&interned) {
|
||||
return Ok(attr.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(cls) = cls
|
||||
&& let Ok(cls_type) = cls.downcast::<PyType>()
|
||||
&& let Some(interned) = vm.ctx.interned_str(descr.member.name.as_str())
|
||||
&& let Some(attr) = cls_type.attributes.read().get(&interned)
|
||||
{
|
||||
return Ok(attr.clone());
|
||||
}
|
||||
Ok(zelf)
|
||||
}
|
||||
|
||||
@@ -111,10 +111,10 @@ impl PyReverseSequenceIterator {
|
||||
#[pymethod]
|
||||
fn __length_hint__(&self, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
let internal = self.internal.lock();
|
||||
if let IterStatus::Active(obj) = &internal.status {
|
||||
if internal.position <= obj.length(vm)? {
|
||||
return Ok(internal.position + 1);
|
||||
}
|
||||
if let IterStatus::Active(obj) = &internal.status
|
||||
&& internal.position <= obj.length(vm)?
|
||||
{
|
||||
return Ok(internal.position + 1);
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
@@ -280,11 +280,11 @@ impl PyFunction {
|
||||
.take(code.kwonlyarg_count as usize)
|
||||
.filter(|(slot, _)| slot.is_none())
|
||||
{
|
||||
if let Some(defaults) = &get_defaults!().1 {
|
||||
if let Some(default) = defaults.get_item_opt(&**kwarg, vm)? {
|
||||
*slot = Some(default);
|
||||
continue;
|
||||
}
|
||||
if let Some(defaults) = &get_defaults!().1
|
||||
&& let Some(default) = defaults.get_item_opt(&**kwarg, vm)?
|
||||
{
|
||||
*slot = Some(default);
|
||||
continue;
|
||||
}
|
||||
|
||||
// No default value and not specified.
|
||||
|
||||
@@ -269,22 +269,22 @@ pub(crate) fn make_parameters(args: &Py<PyTuple>, vm: &VirtualMachine) -> PyTupl
|
||||
parameters[iparam] = arg.clone();
|
||||
iparam += 1;
|
||||
}
|
||||
} else if let Ok(subparams) = arg.get_attr(identifier!(vm, __parameters__), vm) {
|
||||
if let Ok(sub_params) = subparams.try_to_ref::<PyTuple>(vm) {
|
||||
let len2 = sub_params.len();
|
||||
// Resize if needed
|
||||
if iparam + len2 > parameters.len() {
|
||||
parameters.resize(iparam + len2, vm.ctx.none());
|
||||
}
|
||||
for sub_param in sub_params {
|
||||
// Use tuple_add equivalent logic
|
||||
if tuple_index(¶meters[..iparam], sub_param).is_none() {
|
||||
if iparam >= parameters.len() {
|
||||
parameters.resize(iparam + 1, vm.ctx.none());
|
||||
}
|
||||
parameters[iparam] = sub_param.clone();
|
||||
iparam += 1;
|
||||
} else if let Ok(subparams) = arg.get_attr(identifier!(vm, __parameters__), vm)
|
||||
&& let Ok(sub_params) = subparams.try_to_ref::<PyTuple>(vm)
|
||||
{
|
||||
let len2 = sub_params.len();
|
||||
// Resize if needed
|
||||
if iparam + len2 > parameters.len() {
|
||||
parameters.resize(iparam + len2, vm.ctx.none());
|
||||
}
|
||||
for sub_param in sub_params {
|
||||
// Use tuple_add equivalent logic
|
||||
if tuple_index(¶meters[..iparam], sub_param).is_none() {
|
||||
if iparam >= parameters.len() {
|
||||
parameters.resize(iparam + 1, vm.ctx.none());
|
||||
}
|
||||
parameters[iparam] = sub_param.clone();
|
||||
iparam += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -376,23 +376,22 @@ fn unpack_args(item: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
|
||||
}
|
||||
|
||||
// Try to get __typing_unpacked_tuple_args__
|
||||
if let Ok(sub_args) = item.get_attr(identifier!(vm, __typing_unpacked_tuple_args__), vm) {
|
||||
if !sub_args.is(&vm.ctx.none) {
|
||||
if let Ok(tuple) = sub_args.try_to_ref::<PyTuple>(vm) {
|
||||
// Check for ellipsis at the end
|
||||
let has_ellipsis_at_end = tuple
|
||||
.as_slice()
|
||||
.last()
|
||||
.is_some_and(|item| item.is(&vm.ctx.ellipsis));
|
||||
if let Ok(sub_args) = item.get_attr(identifier!(vm, __typing_unpacked_tuple_args__), vm)
|
||||
&& !sub_args.is(&vm.ctx.none)
|
||||
&& let Ok(tuple) = sub_args.try_to_ref::<PyTuple>(vm)
|
||||
{
|
||||
// Check for ellipsis at the end
|
||||
let has_ellipsis_at_end = tuple
|
||||
.as_slice()
|
||||
.last()
|
||||
.is_some_and(|item| item.is(&vm.ctx.ellipsis));
|
||||
|
||||
if !has_ellipsis_at_end {
|
||||
// Safe to unpack - add all elements's PyList_SetSlice
|
||||
for arg in tuple {
|
||||
new_args.push(arg.clone());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if !has_ellipsis_at_end {
|
||||
// Safe to unpack - add all elements's PyList_SetSlice
|
||||
for arg in tuple {
|
||||
new_args.push(arg.clone());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,17 +420,17 @@ pub fn subs_parameters(
|
||||
|
||||
// Step 2: Call __typing_prepare_subst__ on each parameter
|
||||
for param in parameters.iter() {
|
||||
if let Ok(prepare) = param.get_attr(identifier!(vm, __typing_prepare_subst__), vm) {
|
||||
if !prepare.is(&vm.ctx.none) {
|
||||
// Call prepare(self, item)
|
||||
item = if item.try_to_ref::<PyTuple>(vm).is_ok() {
|
||||
prepare.call((alias.clone(), item.clone()), vm)?
|
||||
} else {
|
||||
// Create a tuple with the single item's "O(O)" format
|
||||
let tuple_args = PyTuple::new_ref(vec![item.clone()], &vm.ctx);
|
||||
prepare.call((alias.clone(), tuple_args.to_pyobject(vm)), vm)?
|
||||
};
|
||||
}
|
||||
if let Ok(prepare) = param.get_attr(identifier!(vm, __typing_prepare_subst__), vm)
|
||||
&& !prepare.is(&vm.ctx.none)
|
||||
{
|
||||
// Call prepare(self, item)
|
||||
item = if item.try_to_ref::<PyTuple>(vm).is_ok() {
|
||||
prepare.call((alias.clone(), item.clone()), vm)?
|
||||
} else {
|
||||
// Create a tuple with the single item's "O(O)" format
|
||||
let tuple_args = PyTuple::new_ref(vec![item.clone()], &vm.ctx);
|
||||
prepare.call((alias.clone(), tuple_args.to_pyobject(vm)), vm)?
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,12 +525,11 @@ impl Callable for PyGenericAlias {
|
||||
type Args = FuncArgs;
|
||||
fn call(zelf: &Py<Self>, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
PyType::call(&zelf.origin, args, vm).map(|obj| {
|
||||
if let Err(exc) = obj.set_attr(identifier!(vm, __orig_class__), zelf.to_owned(), vm) {
|
||||
if !exc.fast_isinstance(vm.ctx.exceptions.attribute_error)
|
||||
&& !exc.fast_isinstance(vm.ctx.exceptions.type_error)
|
||||
{
|
||||
return Err(exc);
|
||||
}
|
||||
if let Err(exc) = obj.set_attr(identifier!(vm, __orig_class__), zelf.to_owned(), vm)
|
||||
&& !exc.fast_isinstance(vm.ctx.exceptions.attribute_error)
|
||||
&& !exc.fast_isinstance(vm.ctx.exceptions.type_error)
|
||||
{
|
||||
return Err(exc);
|
||||
}
|
||||
Ok(obj)
|
||||
})?
|
||||
|
||||
+21
-22
@@ -501,34 +501,33 @@ impl PyInt {
|
||||
let ndigits = ndigits.as_bigint();
|
||||
// round(12345, -2) == 12300
|
||||
// If precision >= 0, then any integer is already rounded correctly
|
||||
if let Some(ndigits) = ndigits.neg().to_u32() {
|
||||
if ndigits > 0 {
|
||||
// Work with positive integers and negate at the end if necessary
|
||||
let sign = if zelf.value.is_negative() {
|
||||
BigInt::from(-1)
|
||||
} else {
|
||||
BigInt::from(1)
|
||||
};
|
||||
let value = zelf.value.abs();
|
||||
if let Some(ndigits) = ndigits.neg().to_u32()
|
||||
&& ndigits > 0
|
||||
{
|
||||
// Work with positive integers and negate at the end if necessary
|
||||
let sign = if zelf.value.is_negative() {
|
||||
BigInt::from(-1)
|
||||
} else {
|
||||
BigInt::from(1)
|
||||
};
|
||||
let value = zelf.value.abs();
|
||||
|
||||
// Divide and multiply by the power of 10 to get the approximate answer
|
||||
let pow10 = BigInt::from(10).pow(ndigits);
|
||||
let quotient = &value / &pow10;
|
||||
let rounded = "ient * &pow10;
|
||||
// Divide and multiply by the power of 10 to get the approximate answer
|
||||
let pow10 = BigInt::from(10).pow(ndigits);
|
||||
let quotient = &value / &pow10;
|
||||
let rounded = "ient * &pow10;
|
||||
|
||||
// Malachite division uses floor rounding, Python uses half-even
|
||||
let remainder = &value - &rounded;
|
||||
let half_pow10 = &pow10 / BigInt::from(2);
|
||||
let correction = if remainder > half_pow10
|
||||
|| (remainder == half_pow10 && quotient.is_odd())
|
||||
{
|
||||
// Malachite division uses floor rounding, Python uses half-even
|
||||
let remainder = &value - &rounded;
|
||||
let half_pow10 = &pow10 / BigInt::from(2);
|
||||
let correction =
|
||||
if remainder > half_pow10 || (remainder == half_pow10 && quotient.is_odd()) {
|
||||
pow10
|
||||
} else {
|
||||
BigInt::from(0)
|
||||
};
|
||||
let rounded = (rounded + correction) * sign;
|
||||
return Ok(vm.ctx.new_int(rounded));
|
||||
}
|
||||
let rounded = (rounded + correction) * sign;
|
||||
return Ok(vm.ctx.new_int(rounded));
|
||||
}
|
||||
}
|
||||
Ok(zelf)
|
||||
|
||||
@@ -151,10 +151,10 @@ impl<T> PositionIterInternal<T> {
|
||||
where
|
||||
F: FnOnce(&T) -> usize,
|
||||
{
|
||||
if let IterStatus::Active(obj) = &self.status {
|
||||
if self.position <= f(obj) {
|
||||
return self.position + 1;
|
||||
}
|
||||
if let IterStatus::Active(obj) = &self.status
|
||||
&& self.position <= f(obj)
|
||||
{
|
||||
return self.position + 1;
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
@@ -62,17 +62,17 @@ impl Constructor for PyMappingProxy {
|
||||
type Args = PyObjectRef;
|
||||
|
||||
fn py_new(cls: PyTypeRef, mapping: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
if let Some(methods) = PyMapping::find_methods(&mapping) {
|
||||
if !mapping.downcastable::<PyList>() && !mapping.downcastable::<PyTuple>() {
|
||||
return Self {
|
||||
mapping: MappingProxyInner::Mapping(ArgMapping::with_methods(
|
||||
mapping,
|
||||
unsafe { methods.borrow_static() },
|
||||
)),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.map(Into::into);
|
||||
if let Some(methods) = PyMapping::find_methods(&mapping)
|
||||
&& !mapping.downcastable::<PyList>()
|
||||
&& !mapping.downcastable::<PyTuple>()
|
||||
{
|
||||
return Self {
|
||||
mapping: MappingProxyInner::Mapping(ArgMapping::with_methods(mapping, unsafe {
|
||||
methods.borrow_static()
|
||||
})),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
.map(Into::into);
|
||||
}
|
||||
Err(vm.new_type_error(format!(
|
||||
"mappingproxy() argument must be a mapping, not {}",
|
||||
|
||||
+12
-12
@@ -330,10 +330,10 @@ impl PyMemoryView {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
if let Some(other) = other.downcast_ref::<Self>() {
|
||||
if other.released.load() {
|
||||
return Ok(false);
|
||||
}
|
||||
if let Some(other) = other.downcast_ref::<Self>()
|
||||
&& other.released.load()
|
||||
{
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let other = match PyBuffer::try_from_borrowed_object(vm, other) {
|
||||
@@ -668,10 +668,10 @@ impl PyMemoryView {
|
||||
if needle.is(&vm.ctx.ellipsis) {
|
||||
return Ok(zelf.into());
|
||||
}
|
||||
if let Some(tuple) = needle.downcast_ref::<PyTuple>() {
|
||||
if tuple.is_empty() {
|
||||
return zelf.unpack_single(0, vm);
|
||||
}
|
||||
if let Some(tuple) = needle.downcast_ref::<PyTuple>()
|
||||
&& tuple.is_empty()
|
||||
{
|
||||
return zelf.unpack_single(0, vm);
|
||||
}
|
||||
return Err(vm.new_type_error("invalid indexing of 0-dim memory"));
|
||||
}
|
||||
@@ -867,10 +867,10 @@ impl Py<PyMemoryView> {
|
||||
// TODO: merge branches when we got conditional if let
|
||||
if needle.is(&vm.ctx.ellipsis) {
|
||||
return self.pack_single(0, value, vm);
|
||||
} else if let Some(tuple) = needle.downcast_ref::<PyTuple>() {
|
||||
if tuple.is_empty() {
|
||||
return self.pack_single(0, value, vm);
|
||||
}
|
||||
} else if let Some(tuple) = needle.downcast_ref::<PyTuple>()
|
||||
&& tuple.is_empty()
|
||||
{
|
||||
return self.pack_single(0, value, vm);
|
||||
}
|
||||
return Err(vm.new_type_error("invalid indexing of 0-dim memory"));
|
||||
}
|
||||
|
||||
+28
-31
@@ -53,14 +53,12 @@ impl Constructor for PyBaseObject {
|
||||
let tp_init = cls.get_attr(identifier!(vm, __init__));
|
||||
let object_init = vm.ctx.types.object_type.get_attr(identifier!(vm, __init__));
|
||||
|
||||
if let (Some(tp_init), Some(object_init)) = (tp_init, object_init) {
|
||||
if tp_init.is(&object_init) {
|
||||
// Both __new__ and __init__ are object's versions,
|
||||
// so the type accepts no arguments
|
||||
return Err(
|
||||
vm.new_type_error(format!("{}() takes no arguments", cls.name()))
|
||||
);
|
||||
}
|
||||
if let (Some(tp_init), Some(object_init)) = (tp_init, object_init)
|
||||
&& tp_init.is(&object_init)
|
||||
{
|
||||
// Both __new__ and __init__ are object's versions,
|
||||
// so the type accepts no arguments
|
||||
return Err(vm.new_type_error(format!("{}() takes no arguments", cls.name())));
|
||||
}
|
||||
// If tp_init != object_init, then the type has custom __init__
|
||||
// which might accept arguments, so we allow it
|
||||
@@ -75,32 +73,31 @@ impl Constructor for PyBaseObject {
|
||||
};
|
||||
|
||||
// Ensure that all abstract methods are implemented before instantiating instance.
|
||||
if let Some(abs_methods) = cls.get_attr(identifier!(vm, __abstractmethods__)) {
|
||||
if let Some(unimplemented_abstract_method_count) = abs_methods.length_opt(vm) {
|
||||
let methods: Vec<PyStrRef> = abs_methods.try_to_value(vm)?;
|
||||
let methods: String =
|
||||
Itertools::intersperse(methods.iter().map(|name| name.as_str()), "', '")
|
||||
.collect();
|
||||
if let Some(abs_methods) = cls.get_attr(identifier!(vm, __abstractmethods__))
|
||||
&& let Some(unimplemented_abstract_method_count) = abs_methods.length_opt(vm)
|
||||
{
|
||||
let methods: Vec<PyStrRef> = abs_methods.try_to_value(vm)?;
|
||||
let methods: String =
|
||||
Itertools::intersperse(methods.iter().map(|name| name.as_str()), "', '").collect();
|
||||
|
||||
let unimplemented_abstract_method_count = unimplemented_abstract_method_count?;
|
||||
let name = cls.name().to_string();
|
||||
let unimplemented_abstract_method_count = unimplemented_abstract_method_count?;
|
||||
let name = cls.name().to_string();
|
||||
|
||||
match unimplemented_abstract_method_count {
|
||||
0 => {}
|
||||
1 => {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"class {name} without an implementation for abstract method '{methods}'"
|
||||
)));
|
||||
}
|
||||
2.. => {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"class {name} without an implementation for abstract methods '{methods}'"
|
||||
)));
|
||||
}
|
||||
// TODO: remove `allow` when redox build doesn't complain about it
|
||||
#[allow(unreachable_patterns)]
|
||||
_ => unreachable!(),
|
||||
match unimplemented_abstract_method_count {
|
||||
0 => {}
|
||||
1 => {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"class {name} without an implementation for abstract method '{methods}'"
|
||||
)));
|
||||
}
|
||||
2.. => {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"class {name} without an implementation for abstract methods '{methods}'"
|
||||
)));
|
||||
}
|
||||
// TODO: remove `allow` when redox build doesn't complain about it
|
||||
#[allow(unreachable_patterns)]
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+16
-16
@@ -74,10 +74,10 @@ impl PyProperty {
|
||||
}
|
||||
|
||||
// Otherwise try to get __name__ from getter
|
||||
if let Some(getter) = self.getter.read().as_ref() {
|
||||
if let Ok(name) = getter.get_attr("__name__", vm) {
|
||||
return Some(name);
|
||||
}
|
||||
if let Some(getter) = self.getter.read().as_ref()
|
||||
&& let Ok(name) = getter.get_attr("__name__", vm)
|
||||
{
|
||||
return Some(name);
|
||||
}
|
||||
|
||||
None
|
||||
@@ -249,24 +249,24 @@ impl PyProperty {
|
||||
};
|
||||
|
||||
// Check getter
|
||||
if let Some(getter) = self.getter.read().as_ref() {
|
||||
if is_abstract(getter)? {
|
||||
return Ok(vm.ctx.new_bool(true).into());
|
||||
}
|
||||
if let Some(getter) = self.getter.read().as_ref()
|
||||
&& is_abstract(getter)?
|
||||
{
|
||||
return Ok(vm.ctx.new_bool(true).into());
|
||||
}
|
||||
|
||||
// Check setter
|
||||
if let Some(setter) = self.setter.read().as_ref() {
|
||||
if is_abstract(setter)? {
|
||||
return Ok(vm.ctx.new_bool(true).into());
|
||||
}
|
||||
if let Some(setter) = self.setter.read().as_ref()
|
||||
&& is_abstract(setter)?
|
||||
{
|
||||
return Ok(vm.ctx.new_bool(true).into());
|
||||
}
|
||||
|
||||
// Check deleter
|
||||
if let Some(deleter) = self.deleter.read().as_ref() {
|
||||
if is_abstract(deleter)? {
|
||||
return Ok(vm.ctx.new_bool(true).into());
|
||||
}
|
||||
if let Some(deleter) = self.deleter.read().as_ref()
|
||||
&& is_abstract(deleter)?
|
||||
{
|
||||
return Ok(vm.ctx.new_bool(true).into());
|
||||
}
|
||||
|
||||
Ok(vm.ctx.new_bool(false).into())
|
||||
|
||||
@@ -324,12 +324,12 @@ impl IterNext for PyStrIterator {
|
||||
internal.1 = offset + ch.len_wtf8();
|
||||
return Ok(PyIterReturn::Return(ch.to_pyobject(vm)));
|
||||
}
|
||||
} else if let Some(value) = value.get(internal.1..) {
|
||||
if let Some(ch) = value.code_points().next() {
|
||||
internal.0.position += 1;
|
||||
internal.1 += ch.len_wtf8();
|
||||
return Ok(PyIterReturn::Return(ch.to_pyobject(vm)));
|
||||
}
|
||||
} else if let Some(value) = value.get(internal.1..)
|
||||
&& let Some(ch) = value.code_points().next()
|
||||
{
|
||||
internal.0.position += 1;
|
||||
internal.1 += ch.len_wtf8();
|
||||
return Ok(PyIterReturn::Return(ch.to_pyobject(vm)));
|
||||
}
|
||||
internal.0.status = Exhausted;
|
||||
}
|
||||
|
||||
@@ -239,19 +239,20 @@ impl Representable for PySuper {
|
||||
}
|
||||
|
||||
fn super_check(ty: PyTypeRef, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyTypeRef> {
|
||||
if let Ok(cls) = obj.clone().downcast::<PyType>() {
|
||||
if cls.fast_issubclass(&ty) {
|
||||
return Ok(cls);
|
||||
}
|
||||
if let Ok(cls) = obj.clone().downcast::<PyType>()
|
||||
&& cls.fast_issubclass(&ty)
|
||||
{
|
||||
return Ok(cls);
|
||||
}
|
||||
if obj.fast_isinstance(&ty) {
|
||||
return Ok(obj.class().to_owned());
|
||||
}
|
||||
let class_attr = obj.get_attr("__class__", vm)?;
|
||||
if let Ok(cls) = class_attr.downcast::<PyType>() {
|
||||
if !cls.is(&ty) && cls.fast_issubclass(&ty) {
|
||||
return Ok(cls);
|
||||
}
|
||||
if let Ok(cls) = class_attr.downcast::<PyType>()
|
||||
&& !cls.is(&ty)
|
||||
&& cls.fast_issubclass(&ty)
|
||||
{
|
||||
return Ok(cls);
|
||||
}
|
||||
Err(vm.new_type_error("super(type, obj): obj must be an instance or subtype of type"))
|
||||
}
|
||||
|
||||
+39
-40
@@ -273,25 +273,24 @@ impl PyType {
|
||||
|
||||
// First check in our own attributes
|
||||
let abc_tpflags_name = ctx.intern_str("__abc_tpflags__");
|
||||
if let Some(abc_tpflags_obj) = attrs.get(abc_tpflags_name) {
|
||||
if let Some(int_obj) = abc_tpflags_obj.downcast_ref::<crate::builtins::int::PyInt>() {
|
||||
let flags_val = int_obj.as_bigint().to_i64().unwrap_or(0);
|
||||
let abc_flags = PyTypeFlags::from_bits_truncate(flags_val as u64);
|
||||
slots.flags |= abc_flags & COLLECTION_FLAGS;
|
||||
return;
|
||||
}
|
||||
if let Some(abc_tpflags_obj) = attrs.get(abc_tpflags_name)
|
||||
&& let Some(int_obj) = abc_tpflags_obj.downcast_ref::<crate::builtins::int::PyInt>()
|
||||
{
|
||||
let flags_val = int_obj.as_bigint().to_i64().unwrap_or(0);
|
||||
let abc_flags = PyTypeFlags::from_bits_truncate(flags_val as u64);
|
||||
slots.flags |= abc_flags & COLLECTION_FLAGS;
|
||||
return;
|
||||
}
|
||||
|
||||
// Then check in base classes
|
||||
for base in bases {
|
||||
if let Some(abc_tpflags_obj) = base.find_name_in_mro(abc_tpflags_name) {
|
||||
if let Some(int_obj) = abc_tpflags_obj.downcast_ref::<crate::builtins::int::PyInt>()
|
||||
{
|
||||
let flags_val = int_obj.as_bigint().to_i64().unwrap_or(0);
|
||||
let abc_flags = PyTypeFlags::from_bits_truncate(flags_val as u64);
|
||||
slots.flags |= abc_flags & COLLECTION_FLAGS;
|
||||
return;
|
||||
}
|
||||
if let Some(abc_tpflags_obj) = base.find_name_in_mro(abc_tpflags_name)
|
||||
&& let Some(int_obj) = abc_tpflags_obj.downcast_ref::<crate::builtins::int::PyInt>()
|
||||
{
|
||||
let flags_val = int_obj.as_bigint().to_i64().unwrap_or(0);
|
||||
let abc_flags = PyTypeFlags::from_bits_truncate(flags_val as u64);
|
||||
slots.flags |= abc_flags & COLLECTION_FLAGS;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -322,13 +321,13 @@ impl PyType {
|
||||
slots.basicsize = base.slots.basicsize;
|
||||
}
|
||||
|
||||
if let Some(qualname) = attrs.get(identifier!(ctx, __qualname__)) {
|
||||
if !qualname.fast_isinstance(ctx.types.str_type) {
|
||||
return Err(format!(
|
||||
"type __qualname__ must be a str, not {}",
|
||||
qualname.class().name()
|
||||
));
|
||||
}
|
||||
if let Some(qualname) = attrs.get(identifier!(ctx, __qualname__))
|
||||
&& !qualname.fast_isinstance(ctx.types.str_type)
|
||||
{
|
||||
return Err(format!(
|
||||
"type __qualname__ must be a str, not {}",
|
||||
qualname.class().name()
|
||||
));
|
||||
}
|
||||
|
||||
let new_type = PyRef::new_ref(
|
||||
@@ -945,10 +944,10 @@ impl PyType {
|
||||
fn __type_params__(&self, vm: &VirtualMachine) -> PyTupleRef {
|
||||
let attrs = self.attributes.read();
|
||||
let key = identifier!(vm, __type_params__);
|
||||
if let Some(params) = attrs.get(&key) {
|
||||
if let Ok(tuple) = params.clone().downcast::<PyTuple>() {
|
||||
return tuple;
|
||||
}
|
||||
if let Some(params) = attrs.get(&key)
|
||||
&& let Ok(tuple) = params.clone().downcast::<PyTuple>()
|
||||
{
|
||||
return tuple;
|
||||
}
|
||||
// Return empty tuple if not found or not a tuple
|
||||
vm.ctx.empty_tuple.clone()
|
||||
@@ -1064,16 +1063,16 @@ impl Constructor for PyType {
|
||||
});
|
||||
let mut attributes = dict.to_attributes(vm);
|
||||
|
||||
if let Some(f) = attributes.get_mut(identifier!(vm, __init_subclass__)) {
|
||||
if f.class().is(vm.ctx.types.function_type) {
|
||||
*f = PyClassMethod::from(f.clone()).into_pyobject(vm);
|
||||
}
|
||||
if let Some(f) = attributes.get_mut(identifier!(vm, __init_subclass__))
|
||||
&& f.class().is(vm.ctx.types.function_type)
|
||||
{
|
||||
*f = PyClassMethod::from(f.clone()).into_pyobject(vm);
|
||||
}
|
||||
|
||||
if let Some(f) = attributes.get_mut(identifier!(vm, __class_getitem__)) {
|
||||
if f.class().is(vm.ctx.types.function_type) {
|
||||
*f = PyClassMethod::from(f.clone()).into_pyobject(vm);
|
||||
}
|
||||
if let Some(f) = attributes.get_mut(identifier!(vm, __class_getitem__))
|
||||
&& f.class().is(vm.ctx.types.function_type)
|
||||
{
|
||||
*f = PyClassMethod::from(f.clone()).into_pyobject(vm);
|
||||
}
|
||||
|
||||
if let Some(current_frame) = vm.current_frame() {
|
||||
@@ -1370,12 +1369,12 @@ impl Py<PyType> {
|
||||
fn __doc__(&self, vm: &VirtualMachine) -> PyResult {
|
||||
// Similar to CPython's type_get_doc
|
||||
// For non-heap types (static types), check if there's an internal doc
|
||||
if !self.slots.flags.has_feature(PyTypeFlags::HEAPTYPE) {
|
||||
if let Some(internal_doc) = self.slots.doc {
|
||||
// Process internal doc, removing signature if present
|
||||
let doc_str = get_doc_from_internal_doc(&self.name(), internal_doc);
|
||||
return Ok(vm.ctx.new_str(doc_str).into());
|
||||
}
|
||||
if !self.slots.flags.has_feature(PyTypeFlags::HEAPTYPE)
|
||||
&& let Some(internal_doc) = self.slots.doc
|
||||
{
|
||||
// Process internal doc, removing signature if present
|
||||
let doc_str = get_doc_from_internal_doc(&self.name(), internal_doc);
|
||||
return Ok(vm.ctx.new_str(doc_str).into());
|
||||
}
|
||||
|
||||
// Check if there's a __doc__ in the type's dict
|
||||
|
||||
+4
-4
@@ -8,10 +8,10 @@ pub fn bytes_from_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult<Vec<u8
|
||||
return Ok(elements);
|
||||
}
|
||||
|
||||
if !obj.fast_isinstance(vm.ctx.types.str_type) {
|
||||
if let Ok(elements) = vm.map_iterable_object(obj, |x| value_from_object(vm, &x)) {
|
||||
return elements;
|
||||
}
|
||||
if !obj.fast_isinstance(vm.ctx.types.str_type)
|
||||
&& let Ok(elements) = vm.map_iterable_object(obj, |x| value_from_object(vm, &x))
|
||||
{
|
||||
return elements;
|
||||
}
|
||||
|
||||
Err(vm.new_type_error("can assign only bytes, buffers, or iterables of ints in range(0, 256)"))
|
||||
|
||||
+4
-4
@@ -195,10 +195,10 @@ fn spec_format_string(
|
||||
.ok_or_else(|| vm.new_overflow_error("%c arg not in range(0x110000)"))?;
|
||||
return Ok(spec.format_char(ch));
|
||||
}
|
||||
if let Some(s) = obj.downcast_ref::<PyStr>() {
|
||||
if let Ok(ch) = s.as_wtf8().code_points().exactly_one() {
|
||||
return Ok(spec.format_char(ch));
|
||||
}
|
||||
if let Some(s) = obj.downcast_ref::<PyStr>()
|
||||
&& let Ok(ch) = s.as_wtf8().code_points().exactly_one()
|
||||
{
|
||||
return Ok(spec.format_char(ch));
|
||||
}
|
||||
Err(vm.new_type_error("%c requires int or char"))
|
||||
}
|
||||
|
||||
+22
-23
@@ -1535,10 +1535,10 @@ pub(super) mod types {
|
||||
if !vm.is_none(&filename) {
|
||||
let mut args_reduced: Vec<PyObjectRef> = vec![errno, msg, filename];
|
||||
|
||||
if let Ok(filename2) = obj.get_attr("filename2", vm) {
|
||||
if !vm.is_none(&filename2) {
|
||||
args_reduced.push(filename2);
|
||||
}
|
||||
if let Ok(filename2) = obj.get_attr("filename2", vm)
|
||||
&& !vm.is_none(&filename2)
|
||||
{
|
||||
args_reduced.push(filename2);
|
||||
}
|
||||
result.push(args_reduced.into_pytuple(vm).into());
|
||||
} else {
|
||||
@@ -1658,28 +1658,27 @@ pub(super) mod types {
|
||||
|
||||
zelf.set_attr("print_file_and_line", vm.ctx.none(), vm)?;
|
||||
|
||||
if len == 2 {
|
||||
if let Ok(location_tuple) = new_args.args[1]
|
||||
if len == 2
|
||||
&& let Ok(location_tuple) = new_args.args[1]
|
||||
.clone()
|
||||
.downcast::<crate::builtins::PyTuple>()
|
||||
{
|
||||
let location_tup_len = location_tuple.len();
|
||||
for (i, &attr) in [
|
||||
"filename",
|
||||
"lineno",
|
||||
"offset",
|
||||
"text",
|
||||
"end_lineno",
|
||||
"end_offset",
|
||||
]
|
||||
.iter()
|
||||
.enumerate()
|
||||
{
|
||||
let location_tup_len = location_tuple.len();
|
||||
for (i, &attr) in [
|
||||
"filename",
|
||||
"lineno",
|
||||
"offset",
|
||||
"text",
|
||||
"end_lineno",
|
||||
"end_offset",
|
||||
]
|
||||
.iter()
|
||||
.enumerate()
|
||||
{
|
||||
if location_tup_len > i {
|
||||
zelf.set_attr(attr, location_tuple[i].to_owned(), vm)?;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if location_tup_len > i {
|
||||
zelf.set_attr(attr, location_tuple[i].to_owned(), vm)?;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,12 +192,10 @@ impl WeakRefList {
|
||||
}))
|
||||
});
|
||||
let mut inner = unsafe { inner_ptr.as_ref().lock() };
|
||||
if is_generic {
|
||||
if let Some(generic_weakref) = inner.generic_weakref {
|
||||
let generic_weakref = unsafe { generic_weakref.as_ref() };
|
||||
if generic_weakref.0.ref_count.get() != 0 {
|
||||
return generic_weakref.to_owned();
|
||||
}
|
||||
if is_generic && let Some(generic_weakref) = inner.generic_weakref {
|
||||
let generic_weakref = unsafe { generic_weakref.as_ref() };
|
||||
if generic_weakref.0.ref_count.get() != 0 {
|
||||
return generic_weakref.to_owned();
|
||||
}
|
||||
}
|
||||
let obj = PyWeak {
|
||||
|
||||
@@ -78,13 +78,13 @@ impl AsRef<PyObject> for PyMapping<'_> {
|
||||
|
||||
impl<'a> PyMapping<'a> {
|
||||
pub fn try_protocol(obj: &'a PyObject, vm: &VirtualMachine) -> PyResult<Self> {
|
||||
if let Some(methods) = Self::find_methods(obj) {
|
||||
if methods.as_ref().check() {
|
||||
return Ok(Self {
|
||||
obj,
|
||||
methods: unsafe { methods.borrow_static() },
|
||||
});
|
||||
}
|
||||
if let Some(methods) = Self::find_methods(obj)
|
||||
&& methods.as_ref().check()
|
||||
{
|
||||
return Ok(Self {
|
||||
obj,
|
||||
methods: unsafe { methods.borrow_static() },
|
||||
});
|
||||
}
|
||||
|
||||
Err(vm.new_type_error(format!("{} is not a mapping object", obj.class())))
|
||||
|
||||
@@ -220,14 +220,13 @@ impl PyObject {
|
||||
Some(descr) => {
|
||||
let descr_cls = descr.class();
|
||||
let descr_get = descr_cls.mro_find_map(|cls| cls.slots.descr_get.load());
|
||||
if let Some(descr_get) = descr_get {
|
||||
if descr_cls
|
||||
if let Some(descr_get) = descr_get
|
||||
&& descr_cls
|
||||
.mro_find_map(|cls| cls.slots.descr_set.load())
|
||||
.is_some()
|
||||
{
|
||||
let cls = obj_cls.to_owned().into();
|
||||
return descr_get(descr, Some(self.to_owned()), Some(cls), vm).map(Some);
|
||||
}
|
||||
{
|
||||
let cls = obj_cls.to_owned().into();
|
||||
return descr_get(descr, Some(self.to_owned()), Some(cls), vm).map(Some);
|
||||
}
|
||||
Some((descr, descr_get))
|
||||
}
|
||||
@@ -556,12 +555,10 @@ impl PyObject {
|
||||
// Check __class__ attribute, only masking AttributeError
|
||||
if let Some(i_cls) =
|
||||
vm.get_attribute_opt(self.to_owned(), identifier!(vm, __class__))?
|
||||
&& let Ok(i_cls_type) = PyTypeRef::try_from_object(vm, i_cls)
|
||||
&& !i_cls_type.is(self.class())
|
||||
{
|
||||
if let Ok(i_cls_type) = PyTypeRef::try_from_object(vm, i_cls) {
|
||||
if !i_cls_type.is(self.class()) {
|
||||
retval = i_cls_type.is_subtype(cls);
|
||||
}
|
||||
}
|
||||
retval = i_cls_type.is_subtype(cls);
|
||||
}
|
||||
}
|
||||
Ok(retval)
|
||||
|
||||
+4
-4
@@ -95,10 +95,10 @@ mod rustyline_readline {
|
||||
}
|
||||
|
||||
pub fn save_history(&mut self, path: &Path) -> OtherResult<()> {
|
||||
if !path.exists() {
|
||||
if let Some(parent) = path.parent() {
|
||||
std::fs::create_dir_all(parent)?;
|
||||
}
|
||||
if !path.exists()
|
||||
&& let Some(parent) = path.parent()
|
||||
{
|
||||
std::fs::create_dir_all(parent)?;
|
||||
}
|
||||
self.repl.save_history(path)?;
|
||||
Ok(())
|
||||
|
||||
+5
-6
@@ -35,12 +35,11 @@ fn trigger_signals(vm: &VirtualMachine) -> PyResult<()> {
|
||||
let signal_handlers = vm.signal_handlers.as_ref().unwrap().borrow();
|
||||
for (signum, trigger) in TRIGGERS.iter().enumerate().skip(1) {
|
||||
let triggered = trigger.swap(false, Ordering::Relaxed);
|
||||
if triggered {
|
||||
if let Some(handler) = &signal_handlers[signum] {
|
||||
if let Some(callable) = handler.to_callable() {
|
||||
callable.invoke((signum, vm.ctx.none()), vm)?;
|
||||
}
|
||||
}
|
||||
if triggered
|
||||
&& let Some(handler) = &signal_handlers[signum]
|
||||
&& let Some(callable) = handler.to_callable()
|
||||
{
|
||||
callable.invoke((signum, vm.ctx.none()), vm)?;
|
||||
}
|
||||
}
|
||||
if let Some(signal_rx) = &vm.signal_rx {
|
||||
|
||||
@@ -33,14 +33,14 @@ pub(crate) mod _ast {
|
||||
zelf.set_attr(name, arg, vm)?;
|
||||
}
|
||||
for (key, value) in args.kwargs {
|
||||
if let Some(pos) = fields.iter().position(|f| f.as_str() == key) {
|
||||
if pos < n_args {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"{} got multiple values for argument '{}'",
|
||||
zelf.class().name(),
|
||||
key
|
||||
)));
|
||||
}
|
||||
if let Some(pos) = fields.iter().position(|f| f.as_str() == key)
|
||||
&& pos < n_args
|
||||
{
|
||||
return Err(vm.new_type_error(format!(
|
||||
"{} got multiple values for argument '{}'",
|
||||
zelf.class().name(),
|
||||
key
|
||||
)));
|
||||
}
|
||||
zelf.set_attr(vm.ctx.intern_str(key), value, vm)?;
|
||||
}
|
||||
|
||||
+11
-17
@@ -969,17 +969,13 @@ mod builtins {
|
||||
if let Ok(type_params) = function
|
||||
.as_object()
|
||||
.get_attr(identifier!(vm, __type_params__), vm)
|
||||
&& let Some(type_params_tuple) = type_params.downcast_ref::<PyTuple>()
|
||||
&& !type_params_tuple.is_empty()
|
||||
{
|
||||
if let Some(type_params_tuple) = type_params.downcast_ref::<PyTuple>() {
|
||||
if !type_params_tuple.is_empty() {
|
||||
// Set .type_params in namespace so the compiler-generated code can use it
|
||||
namespace.as_object().set_item(
|
||||
vm.ctx.intern_str(".type_params"),
|
||||
type_params,
|
||||
vm,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
// Set .type_params in namespace so the compiler-generated code can use it
|
||||
namespace
|
||||
.as_object()
|
||||
.set_item(vm.ctx.intern_str(".type_params"), type_params, vm)?;
|
||||
}
|
||||
|
||||
let classcell = function.invoke_with_locals(().into(), Some(namespace.clone()), vm)?;
|
||||
@@ -1006,14 +1002,12 @@ mod builtins {
|
||||
if let Ok(type_params) = function
|
||||
.as_object()
|
||||
.get_attr(identifier!(vm, __type_params__), vm)
|
||||
&& let Some(type_params_tuple) = type_params.downcast_ref::<PyTuple>()
|
||||
&& !type_params_tuple.is_empty()
|
||||
{
|
||||
if let Some(type_params_tuple) = type_params.downcast_ref::<PyTuple>() {
|
||||
if !type_params_tuple.is_empty() {
|
||||
class.set_attr(identifier!(vm, __type_params__), type_params.clone(), vm)?;
|
||||
// Also set __parameters__ for compatibility with typing module
|
||||
class.set_attr(identifier!(vm, __parameters__), type_params, vm)?;
|
||||
}
|
||||
}
|
||||
class.set_attr(identifier!(vm, __type_params__), type_params.clone(), vm)?;
|
||||
// Also set __parameters__ for compatibility with typing module
|
||||
class.set_attr(identifier!(vm, __parameters__), type_params, vm)?;
|
||||
}
|
||||
|
||||
if let Some(ref classcell) = classcell {
|
||||
|
||||
+3
-5
@@ -3394,11 +3394,9 @@ mod _io {
|
||||
output.to_mut().insert(0, '\r'.into());
|
||||
self.pendingcr = false;
|
||||
}
|
||||
if !final_ {
|
||||
if let Some(s) = output.strip_suffix("\r".as_ref()) {
|
||||
output = Cow::Owned(s.to_owned());
|
||||
self.pendingcr = true;
|
||||
}
|
||||
if !final_ && let Some(s) = output.strip_suffix("\r".as_ref()) {
|
||||
output = Cow::Owned(s.to_owned());
|
||||
self.pendingcr = true;
|
||||
}
|
||||
|
||||
if output.is_empty() {
|
||||
|
||||
@@ -976,10 +976,10 @@ mod decl {
|
||||
zelf.cur.fetch_add(1);
|
||||
}
|
||||
|
||||
if let Some(stop) = zelf.stop {
|
||||
if zelf.cur.load() >= stop {
|
||||
return Ok(PyIterReturn::StopIteration(None));
|
||||
}
|
||||
if let Some(stop) = zelf.stop
|
||||
&& zelf.cur.load() >= stop
|
||||
{
|
||||
return Ok(PyIterReturn::StopIteration(None));
|
||||
}
|
||||
|
||||
let obj = raise_if_stop!(zelf.iterable.next(vm)?);
|
||||
|
||||
+12
-12
@@ -363,20 +363,20 @@ pub(crate) mod module {
|
||||
return Ok((total, free));
|
||||
}
|
||||
let err = io::Error::last_os_error();
|
||||
if err.raw_os_error() == Some(Foundation::ERROR_DIRECTORY as i32) {
|
||||
if let Some(parent) = path.as_ref().parent() {
|
||||
let parent = widestring::WideCString::from_os_str(parent).unwrap();
|
||||
if err.raw_os_error() == Some(Foundation::ERROR_DIRECTORY as i32)
|
||||
&& let Some(parent) = path.as_ref().parent()
|
||||
{
|
||||
let parent = widestring::WideCString::from_os_str(parent).unwrap();
|
||||
|
||||
let ret = unsafe {
|
||||
GetDiskFreeSpaceExW(parent.as_ptr(), &mut _free_to_me, &mut total, &mut free)
|
||||
};
|
||||
let ret = unsafe {
|
||||
GetDiskFreeSpaceExW(parent.as_ptr(), &mut _free_to_me, &mut total, &mut free)
|
||||
};
|
||||
|
||||
return if ret == 0 {
|
||||
Err(errno_err(vm))
|
||||
} else {
|
||||
Ok((total, free))
|
||||
};
|
||||
}
|
||||
return if ret == 0 {
|
||||
Err(errno_err(vm))
|
||||
} else {
|
||||
Ok((total, free))
|
||||
};
|
||||
}
|
||||
Err(err.to_pyexception(vm))
|
||||
}
|
||||
|
||||
+34
-34
@@ -183,16 +183,16 @@ mod sys {
|
||||
let ctx = &vm.ctx;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
if let Some(exec_path) = env::args_os().next() {
|
||||
if let Ok(path) = which::which(exec_path) {
|
||||
return ctx
|
||||
.new_str(
|
||||
path.into_os_string()
|
||||
.into_string()
|
||||
.unwrap_or_else(|p| p.to_string_lossy().into_owned()),
|
||||
)
|
||||
.into();
|
||||
}
|
||||
if let Some(exec_path) = env::args_os().next()
|
||||
&& let Ok(path) = which::which(exec_path)
|
||||
{
|
||||
return ctx
|
||||
.new_str(
|
||||
path.into_os_string()
|
||||
.into_string()
|
||||
.unwrap_or_else(|p| p.to_string_lossy().into_owned()),
|
||||
)
|
||||
.into();
|
||||
}
|
||||
}
|
||||
if let Some(exec_path) = env::args().next() {
|
||||
@@ -203,16 +203,16 @@ mod sys {
|
||||
if path.is_absolute() {
|
||||
return ctx.new_str(exec_path).into();
|
||||
}
|
||||
if let Ok(dir) = env::current_dir() {
|
||||
if let Ok(dir) = dir.into_os_string().into_string() {
|
||||
return ctx
|
||||
.new_str(format!(
|
||||
"{}/{}",
|
||||
dir,
|
||||
exec_path.strip_prefix("./").unwrap_or(&exec_path)
|
||||
))
|
||||
.into();
|
||||
}
|
||||
if let Ok(dir) = env::current_dir()
|
||||
&& let Ok(dir) = dir.into_os_string().into_string()
|
||||
{
|
||||
return ctx
|
||||
.new_str(format!(
|
||||
"{}/{}",
|
||||
dir,
|
||||
exec_path.strip_prefix("./").unwrap_or(&exec_path)
|
||||
))
|
||||
.into();
|
||||
}
|
||||
}
|
||||
ctx.none()
|
||||
@@ -868,22 +868,22 @@ mod sys {
|
||||
|
||||
#[pyfunction]
|
||||
fn set_asyncgen_hooks(args: SetAsyncgenHooksArgs, vm: &VirtualMachine) -> PyResult<()> {
|
||||
if let Some(Some(finalizer)) = args.finalizer.as_option() {
|
||||
if !finalizer.is_callable() {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"callable finalizer expected, got {:.50}",
|
||||
finalizer.class().name()
|
||||
)));
|
||||
}
|
||||
if let Some(Some(finalizer)) = args.finalizer.as_option()
|
||||
&& !finalizer.is_callable()
|
||||
{
|
||||
return Err(vm.new_type_error(format!(
|
||||
"callable finalizer expected, got {:.50}",
|
||||
finalizer.class().name()
|
||||
)));
|
||||
}
|
||||
|
||||
if let Some(Some(firstiter)) = args.firstiter.as_option() {
|
||||
if !firstiter.is_callable() {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"callable firstiter expected, got {:.50}",
|
||||
firstiter.class().name()
|
||||
)));
|
||||
}
|
||||
if let Some(Some(firstiter)) = args.firstiter.as_option()
|
||||
&& !firstiter.is_callable()
|
||||
{
|
||||
return Err(vm.new_type_error(format!(
|
||||
"callable firstiter expected, got {:.50}",
|
||||
firstiter.class().name()
|
||||
)));
|
||||
}
|
||||
|
||||
if let Some(finalizer) = args.finalizer.into_option() {
|
||||
|
||||
@@ -91,12 +91,11 @@ mod decl {
|
||||
#[pyfunction]
|
||||
fn sleep(seconds: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let dur = seconds.try_into_value::<Duration>(vm).map_err(|e| {
|
||||
if e.class().is(vm.ctx.exceptions.value_error) {
|
||||
if let Some(s) = e.args().first().and_then(|arg| arg.str(vm).ok()) {
|
||||
if s.as_str() == "negative duration" {
|
||||
return vm.new_value_error("sleep length must be non-negative");
|
||||
}
|
||||
}
|
||||
if e.class().is(vm.ctx.exceptions.value_error)
|
||||
&& let Some(s) = e.args().first().and_then(|arg| arg.str(vm).ok())
|
||||
&& s.as_str() == "negative duration"
|
||||
{
|
||||
return vm.new_value_error("sleep length must be non-negative");
|
||||
}
|
||||
e
|
||||
})?;
|
||||
|
||||
@@ -9,10 +9,10 @@ pub fn warn(
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
// TODO: use rust warnings module
|
||||
if let Ok(module) = vm.import("warnings", 0) {
|
||||
if let Ok(func) = module.get_attr("warn", vm) {
|
||||
let _ = func.call((message, category.to_owned(), stack_level), vm);
|
||||
}
|
||||
if let Ok(module) = vm.import("warnings", 0)
|
||||
&& let Ok(func) = module.get_attr("warn", vm)
|
||||
{
|
||||
let _ = func.call((message, category.to_owned(), stack_level), vm);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
+10
-10
@@ -387,22 +387,22 @@ impl Context {
|
||||
|
||||
#[inline]
|
||||
pub fn new_int<T: Into<BigInt> + ToPrimitive>(&self, i: T) -> PyIntRef {
|
||||
if let Some(i) = i.to_i32() {
|
||||
if Self::INT_CACHE_POOL_RANGE.contains(&i) {
|
||||
let inner_idx = (i - Self::INT_CACHE_POOL_MIN) as usize;
|
||||
return self.int_cache_pool[inner_idx].clone();
|
||||
}
|
||||
if let Some(i) = i.to_i32()
|
||||
&& Self::INT_CACHE_POOL_RANGE.contains(&i)
|
||||
{
|
||||
let inner_idx = (i - Self::INT_CACHE_POOL_MIN) as usize;
|
||||
return self.int_cache_pool[inner_idx].clone();
|
||||
}
|
||||
PyInt::from(i).into_ref(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_bigint(&self, i: &BigInt) -> PyIntRef {
|
||||
if let Some(i) = i.to_i32() {
|
||||
if Self::INT_CACHE_POOL_RANGE.contains(&i) {
|
||||
let inner_idx = (i - Self::INT_CACHE_POOL_MIN) as usize;
|
||||
return self.int_cache_pool[inner_idx].clone();
|
||||
}
|
||||
if let Some(i) = i.to_i32()
|
||||
&& Self::INT_CACHE_POOL_RANGE.contains(&i)
|
||||
{
|
||||
let inner_idx = (i - Self::INT_CACHE_POOL_MIN) as usize;
|
||||
return self.int_cache_pool[inner_idx].clone();
|
||||
}
|
||||
PyInt::from(i.clone()).into_ref(self)
|
||||
}
|
||||
|
||||
+9
-10
@@ -42,14 +42,13 @@ impl PyMethod {
|
||||
None
|
||||
} else {
|
||||
let descr_get = descr_cls.mro_find_map(|cls| cls.slots.descr_get.load());
|
||||
if let Some(descr_get) = descr_get {
|
||||
if descr_cls
|
||||
if let Some(descr_get) = descr_get
|
||||
&& descr_cls
|
||||
.mro_find_map(|cls| cls.slots.descr_set.load())
|
||||
.is_some()
|
||||
{
|
||||
let cls = cls.to_owned().into();
|
||||
return descr_get(descr, Some(obj), Some(cls), vm).map(Self::Attribute);
|
||||
}
|
||||
{
|
||||
let cls = cls.to_owned().into();
|
||||
return descr_get(descr, Some(obj), Some(cls), vm).map(Self::Attribute);
|
||||
}
|
||||
descr_get
|
||||
};
|
||||
@@ -58,10 +57,10 @@ impl PyMethod {
|
||||
None => None,
|
||||
};
|
||||
|
||||
if let Some(dict) = obj.dict() {
|
||||
if let Some(attr) = dict.get_item_opt(name, vm)? {
|
||||
return Ok(Self::Attribute(attr));
|
||||
}
|
||||
if let Some(dict) = obj.dict()
|
||||
&& let Some(attr) = dict.get_item_opt(name, vm)?
|
||||
{
|
||||
return Ok(Self::Attribute(attr));
|
||||
}
|
||||
|
||||
if let Some((attr, descr_get)) = cls_attr {
|
||||
|
||||
+22
-21
@@ -363,13 +363,14 @@ impl VirtualMachine {
|
||||
let res = essential_init();
|
||||
let importlib = self.expect_pyresult(res, "essential initialization failed");
|
||||
|
||||
if self.state.settings.allow_external_library && cfg!(feature = "rustpython-compiler") {
|
||||
if let Err(e) = import::init_importlib_package(self, importlib) {
|
||||
eprintln!(
|
||||
"importlib initialization failed. This is critical for many complicated packages."
|
||||
);
|
||||
self.print_exception(e);
|
||||
}
|
||||
if self.state.settings.allow_external_library
|
||||
&& cfg!(feature = "rustpython-compiler")
|
||||
&& let Err(e) = import::init_importlib_package(self, importlib)
|
||||
{
|
||||
eprintln!(
|
||||
"importlib initialization failed. This is critical for many complicated packages."
|
||||
);
|
||||
self.print_exception(e);
|
||||
}
|
||||
|
||||
let expect_stdlib =
|
||||
@@ -714,10 +715,10 @@ impl VirtualMachine {
|
||||
};
|
||||
// TODO: fix extend to do this check (?), see test_extend in Lib/test/list_tests.py,
|
||||
// https://github.com/python/cpython/blob/v3.9.0/Objects/listobject.c#L922-L928
|
||||
if let Some(cap) = cap {
|
||||
if cap >= isize::MAX as usize {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
if let Some(cap) = cap
|
||||
&& cap >= isize::MAX as usize
|
||||
{
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
|
||||
let mut results = PyIterIter::new(self, iter.as_ref(), cap)
|
||||
@@ -829,18 +830,18 @@ impl VirtualMachine {
|
||||
}
|
||||
|
||||
pub(crate) fn contextualize_exception(&self, exception: &PyBaseExceptionRef) {
|
||||
if let Some(context_exc) = self.topmost_exception() {
|
||||
if !context_exc.is(exception) {
|
||||
let mut o = context_exc.clone();
|
||||
while let Some(context) = o.__context__() {
|
||||
if context.is(exception) {
|
||||
o.set___context__(None);
|
||||
break;
|
||||
}
|
||||
o = context;
|
||||
if let Some(context_exc) = self.topmost_exception()
|
||||
&& !context_exc.is(exception)
|
||||
{
|
||||
let mut o = context_exc.clone();
|
||||
while let Some(context) = o.__context__() {
|
||||
if context.is(exception) {
|
||||
o.set___context__(None);
|
||||
break;
|
||||
}
|
||||
exception.set___context__(Some(context_exc))
|
||||
o = context;
|
||||
}
|
||||
exception.set___context__(Some(context_exc))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-4
@@ -347,10 +347,11 @@ impl VirtualMachine {
|
||||
if let Some(source) = source {
|
||||
let loc = raw_location.start().to_usize();
|
||||
let mut iter = source.chars();
|
||||
if let Some(quote) = iter.nth(loc) {
|
||||
if iter.next() == Some(quote) && iter.next() == Some(quote) {
|
||||
is_incomplete = true;
|
||||
}
|
||||
if let Some(quote) = iter.nth(loc)
|
||||
&& iter.next() == Some(quote)
|
||||
&& iter.next() == Some(quote)
|
||||
{
|
||||
is_incomplete = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+21
-22
@@ -171,14 +171,14 @@ impl VirtualMachine {
|
||||
}
|
||||
|
||||
if let Some(slot_a) = slot_a {
|
||||
if let Some(slot_bb) = slot_b {
|
||||
if class_b.fast_issubclass(class_a) {
|
||||
let ret = slot_bb(a, b, self)?;
|
||||
if !ret.is(&self.ctx.not_implemented) {
|
||||
return Ok(ret);
|
||||
}
|
||||
slot_b = None;
|
||||
if let Some(slot_bb) = slot_b
|
||||
&& class_b.fast_issubclass(class_a)
|
||||
{
|
||||
let ret = slot_bb(a, b, self)?;
|
||||
if !ret.is(&self.ctx.not_implemented) {
|
||||
return Ok(ret);
|
||||
}
|
||||
slot_b = None;
|
||||
}
|
||||
let ret = slot_a(a, b, self)?;
|
||||
if !ret.is(&self.ctx.not_implemented) {
|
||||
@@ -277,14 +277,14 @@ impl VirtualMachine {
|
||||
}
|
||||
|
||||
if let Some(slot_a) = slot_a {
|
||||
if let Some(slot_bb) = slot_b {
|
||||
if class_b.fast_issubclass(class_a) {
|
||||
let ret = slot_bb(a, b, c, self)?;
|
||||
if !ret.is(&self.ctx.not_implemented) {
|
||||
return Ok(ret);
|
||||
}
|
||||
slot_b = None;
|
||||
if let Some(slot_bb) = slot_b
|
||||
&& class_b.fast_issubclass(class_a)
|
||||
{
|
||||
let ret = slot_bb(a, b, c, self)?;
|
||||
if !ret.is(&self.ctx.not_implemented) {
|
||||
return Ok(ret);
|
||||
}
|
||||
slot_b = None;
|
||||
}
|
||||
let ret = slot_a(a, b, c, self)?;
|
||||
if !ret.is(&self.ctx.not_implemented) {
|
||||
@@ -299,14 +299,13 @@ impl VirtualMachine {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(slot_c) = class_c.slots.as_number.left_ternary_op(op_slot) {
|
||||
if slot_a.is_some_and(|slot_a| !std::ptr::fn_addr_eq(slot_a, slot_c))
|
||||
&& slot_b.is_some_and(|slot_b| !std::ptr::fn_addr_eq(slot_b, slot_c))
|
||||
{
|
||||
let ret = slot_c(a, b, c, self)?;
|
||||
if !ret.is(&self.ctx.not_implemented) {
|
||||
return Ok(ret);
|
||||
}
|
||||
if let Some(slot_c) = class_c.slots.as_number.left_ternary_op(op_slot)
|
||||
&& slot_a.is_some_and(|slot_a| !std::ptr::fn_addr_eq(slot_a, slot_c))
|
||||
&& slot_b.is_some_and(|slot_b| !std::ptr::fn_addr_eq(slot_b, slot_c))
|
||||
{
|
||||
let ret = slot_c(a, b, c, self)?;
|
||||
if !ret.is(&self.ctx.not_implemented) {
|
||||
return Ok(ret);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -110,16 +110,16 @@ fn win32_xstat_impl(path: &OsStr, traverse: bool) -> std::io::Result<StatStruct>
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
if let Some(errno) = e.raw_os_error() {
|
||||
if matches!(
|
||||
if let Some(errno) = e.raw_os_error()
|
||||
&& matches!(
|
||||
errno as u32,
|
||||
Foundation::ERROR_FILE_NOT_FOUND
|
||||
| Foundation::ERROR_PATH_NOT_FOUND
|
||||
| Foundation::ERROR_NOT_READY
|
||||
| Foundation::ERROR_BAD_NET_NAME
|
||||
) {
|
||||
return Err(e);
|
||||
}
|
||||
)
|
||||
{
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+50
-50
@@ -80,63 +80,63 @@ pub fn js_err_to_py_err(vm: &VirtualMachine, js_err: &JsValue) -> PyBaseExceptio
|
||||
}
|
||||
|
||||
pub fn py_to_js(vm: &VirtualMachine, py_obj: PyObjectRef) -> JsValue {
|
||||
if let Some(ref wasm_id) = vm.wasm_id {
|
||||
if py_obj.fast_isinstance(vm.ctx.types.function_type) {
|
||||
let wasm_vm = WASMVirtualMachine {
|
||||
id: wasm_id.clone(),
|
||||
};
|
||||
let weak_py_obj = wasm_vm.push_held_rc(py_obj).unwrap().unwrap();
|
||||
if let Some(ref wasm_id) = vm.wasm_id
|
||||
&& py_obj.fast_isinstance(vm.ctx.types.function_type)
|
||||
{
|
||||
let wasm_vm = WASMVirtualMachine {
|
||||
id: wasm_id.clone(),
|
||||
};
|
||||
let weak_py_obj = wasm_vm.push_held_rc(py_obj).unwrap().unwrap();
|
||||
|
||||
let closure = move |args: Option<Box<[JsValue]>>,
|
||||
kwargs: Option<Object>|
|
||||
-> Result<JsValue, JsValue> {
|
||||
let py_obj = match wasm_vm.assert_valid() {
|
||||
Ok(_) => weak_py_obj
|
||||
.upgrade()
|
||||
.expect("weak_py_obj to be valid if VM is valid"),
|
||||
Err(err) => {
|
||||
return Err(err);
|
||||
}
|
||||
let closure = move |args: Option<Box<[JsValue]>>,
|
||||
kwargs: Option<Object>|
|
||||
-> Result<JsValue, JsValue> {
|
||||
let py_obj = match wasm_vm.assert_valid() {
|
||||
Ok(_) => weak_py_obj
|
||||
.upgrade()
|
||||
.expect("weak_py_obj to be valid if VM is valid"),
|
||||
Err(err) => {
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
stored_vm_from_wasm(&wasm_vm).interp.enter(move |vm| {
|
||||
let args = match args {
|
||||
Some(args) => Vec::from(args)
|
||||
.into_iter()
|
||||
.map(|arg| js_to_py(vm, arg))
|
||||
.collect::<Vec<_>>(),
|
||||
None => Vec::new(),
|
||||
};
|
||||
stored_vm_from_wasm(&wasm_vm).interp.enter(move |vm| {
|
||||
let args = match args {
|
||||
Some(args) => Vec::from(args)
|
||||
.into_iter()
|
||||
.map(|arg| js_to_py(vm, arg))
|
||||
.collect::<Vec<_>>(),
|
||||
None => Vec::new(),
|
||||
};
|
||||
let mut py_func_args = FuncArgs::from(args);
|
||||
if let Some(ref kwargs) = kwargs {
|
||||
for pair in object_entries(kwargs) {
|
||||
let (key, val) = pair?;
|
||||
py_func_args
|
||||
.kwargs
|
||||
.insert(js_sys::JsString::from(key).into(), js_to_py(vm, val));
|
||||
}
|
||||
let mut py_func_args = FuncArgs::from(args);
|
||||
if let Some(ref kwargs) = kwargs {
|
||||
for pair in object_entries(kwargs) {
|
||||
let (key, val) = pair?;
|
||||
py_func_args
|
||||
.kwargs
|
||||
.insert(js_sys::JsString::from(key).into(), js_to_py(vm, val));
|
||||
}
|
||||
let result = py_obj.call(py_func_args, vm);
|
||||
pyresult_to_js_result(vm, result)
|
||||
})
|
||||
};
|
||||
let closure = Closure::wrap(Box::new(closure)
|
||||
as Box<
|
||||
dyn FnMut(Option<Box<[JsValue]>>, Option<Object>) -> Result<JsValue, JsValue>,
|
||||
>);
|
||||
let func = closure.as_ref().clone();
|
||||
}
|
||||
let result = py_obj.call(py_func_args, vm);
|
||||
pyresult_to_js_result(vm, result)
|
||||
})
|
||||
};
|
||||
let closure = Closure::wrap(Box::new(closure)
|
||||
as Box<
|
||||
dyn FnMut(Option<Box<[JsValue]>>, Option<Object>) -> Result<JsValue, JsValue>,
|
||||
>);
|
||||
let func = closure.as_ref().clone();
|
||||
|
||||
// stores pretty much nothing, it's fine to leak this because if it gets dropped
|
||||
// the error message is worse
|
||||
closure.forget();
|
||||
// stores pretty much nothing, it's fine to leak this because if it gets dropped
|
||||
// the error message is worse
|
||||
closure.forget();
|
||||
|
||||
return func;
|
||||
}
|
||||
return func;
|
||||
}
|
||||
// the browser module might not be injected
|
||||
if vm.try_class("_js", "Promise").is_ok() {
|
||||
if let Some(py_prom) = py_obj.downcast_ref::<js_module::PyPromise>() {
|
||||
return py_prom.as_js(vm).into();
|
||||
}
|
||||
if vm.try_class("_js", "Promise").is_ok()
|
||||
&& let Some(py_prom) = py_obj.downcast_ref::<js_module::PyPromise>()
|
||||
{
|
||||
return py_prom.as_js(vm).into();
|
||||
}
|
||||
|
||||
if let Ok(bytes) = ArgBytesLike::try_from_borrowed_object(vm, &py_obj) {
|
||||
|
||||
Reference in new issue
Block a user