diff --git a/src/main.rs b/src/main.rs index 1b92a5ee46..1ff1b7ef42 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,14 +10,8 @@ extern crate rustyline; use clap::{App, Arg}; use rustpython_parser::error::ParseError; use rustpython_vm::{ - compile, - error::CompileError, - frame::Scope, - import, - obj::objstr, - print_exception, - pyobject::{AttributeProtocol, PyResult}, - util, VirtualMachine, + compile, error::CompileError, frame::Scope, import, obj::objstr, print_exception, + pyobject::PyResult, util, VirtualMachine, }; use rustyline::{error::ReadlineError, Editor}; use std::path::{Path, PathBuf}; @@ -176,8 +170,8 @@ fn run_shell(vm: &mut VirtualMachine) -> PyResult { println!("No previous history."); } - let ps1 = &objstr::get_value(&vm.sys_module.get_attr("ps1").unwrap()); - let ps2 = &objstr::get_value(&vm.sys_module.get_attr("ps2").unwrap()); + let ps1 = &objstr::get_value(&vm.get_attribute(vm.sys_module.clone(), "ps1").unwrap()); + let ps2 = &objstr::get_value(&vm.get_attribute(vm.sys_module.clone(), "ps2").unwrap()); let mut prompt = ps1; loop { diff --git a/vm/src/frame.rs b/vm/src/frame.rs index 1588699456..576d988fb5 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -21,8 +21,8 @@ use crate::obj::objslice::PySlice; use crate::obj::objstr; use crate::obj::objtype; use crate::pyobject::{ - AttributeProtocol, DictProtocol, IdProtocol, PyContext, PyObjectRef, PyResult, PyValue, - TryFromObject, TypeProtocol, + DictProtocol, IdProtocol, PyContext, PyObjectRef, PyResult, PyValue, TryFromObject, + TypeProtocol, }; use crate::vm::VirtualMachine; @@ -810,13 +810,10 @@ impl Frame { // If we're importing a symbol, look it up and use it, otherwise construct a module and return // that let obj = match symbol { - Some(symbol) => module.get_attr(symbol).map_or_else( - || { - let import_error = vm.context().exceptions.import_error.clone(); - Err(vm.new_exception(import_error, format!("cannot import name '{}'", symbol))) - }, - Ok, - ), + Some(symbol) => vm.get_attribute(module, symbol.as_str()).map_err(|_| { + let import_error = vm.context().exceptions.import_error.clone(); + vm.new_exception(import_error, format!("cannot import name '{}'", symbol)) + }), None => Ok(module), }; diff --git a/vm/src/import.rs b/vm/src/import.rs index a36168c287..0b27eb72c9 100644 --- a/vm/src/import.rs +++ b/vm/src/import.rs @@ -8,7 +8,7 @@ use std::path::PathBuf; use crate::compile; use crate::frame::Scope; use crate::obj::{objsequence, objstr}; -use crate::pyobject::{AttributeProtocol, DictProtocol, PyResult}; +use crate::pyobject::{DictProtocol, PyResult}; use crate::util; use crate::vm::VirtualMachine; @@ -54,7 +54,7 @@ pub fn import_module( module_name: &str, ) -> PyResult { // First, see if we already loaded the module: - let sys_modules = vm.sys_module.get_attr("modules").unwrap(); + let sys_modules = vm.get_attribute(vm.sys_module.clone(), "modules")?; if let Some(module) = sys_modules.get_item(module_name) { return Ok(module); } @@ -63,8 +63,12 @@ pub fn import_module( Ok(module) } -fn find_source(vm: &VirtualMachine, current_path: PathBuf, name: &str) -> Result { - let sys_path = vm.sys_module.get_attr("path").unwrap(); +fn find_source( + vm: &mut VirtualMachine, + current_path: PathBuf, + name: &str, +) -> Result { + let sys_path = vm.get_attribute(vm.sys_module.clone(), "path").unwrap(); let mut paths: Vec = objsequence::get_elements(&sys_path) .iter() .map(|item| PathBuf::from(objstr::get_value(item))) diff --git a/vm/src/obj/objclassmethod.rs b/vm/src/obj/objclassmethod.rs index c2322b1836..8a1baad31c 100644 --- a/vm/src/obj/objclassmethod.rs +++ b/vm/src/obj/objclassmethod.rs @@ -1,43 +1,42 @@ -use crate::function::PyFuncArgs; -use crate::pyobject::{AttributeProtocol, PyContext, PyResult, TypeProtocol}; +use super::objtype::PyClassRef; +use crate::pyobject::{PyContext, PyObjectRef, PyRef, PyResult, PyValue}; use crate::vm::VirtualMachine; -pub fn init(context: &PyContext) { - let classmethod_type = &context.classmethod_type; - extend_class!(context, classmethod_type, { - "__get__" => context.new_rustfunc(classmethod_get), - "__new__" => context.new_rustfunc(classmethod_new) - }); +#[derive(Clone, Debug)] +pub struct PyClassMethod { + pub callable: PyObjectRef, } +pub type PyClassMethodRef = PyRef; -fn classmethod_get(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - trace!("classmethod.__get__ {:?}", args.args); - arg_check!( - vm, - args, - required = [ - (cls, Some(vm.ctx.classmethod_type())), - (_inst, None), - (owner, None) - ] - ); - match cls.get_attr("function") { - Some(function) => { - let py_obj = owner.clone(); - let py_method = vm.ctx.new_bound_method(function, py_obj); - Ok(py_method) - } - None => Err(vm.new_attribute_error( - "Attribute Error: classmethod must have 'function' attribute".to_string(), - )), +impl PyValue for PyClassMethod { + fn class(vm: &mut VirtualMachine) -> PyObjectRef { + vm.ctx.classmethod_type() } } -fn classmethod_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - trace!("classmethod.__new__ {:?}", args.args); - arg_check!(vm, args, required = [(cls, None), (callable, None)]); +impl PyClassMethodRef { + fn new( + cls: PyClassRef, + callable: PyObjectRef, + vm: &mut VirtualMachine, + ) -> PyResult { + PyClassMethod { + callable: callable.clone(), + } + .into_ref_with_type(vm, cls) + } + + fn get(self, _inst: PyObjectRef, owner: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + Ok(vm + .ctx + .new_bound_method(self.callable.clone(), owner.clone())) + } +} - let py_obj = vm.ctx.new_instance(cls.clone(), None); - vm.ctx.set_attr(&py_obj, "function", callable.clone()); - Ok(py_obj) +pub fn init(context: &PyContext) { + let classmethod_type = &context.classmethod_type; + extend_class!(context, classmethod_type, { + "__get__" => context.new_rustfunc(PyClassMethodRef::get), + "__new__" => context.new_rustfunc(PyClassMethodRef::new) + }); } diff --git a/vm/src/obj/objstaticmethod.rs b/vm/src/obj/objstaticmethod.rs index 9d1a96ed2a..78307bcc3e 100644 --- a/vm/src/obj/objstaticmethod.rs +++ b/vm/src/obj/objstaticmethod.rs @@ -1,40 +1,40 @@ -use crate::function::PyFuncArgs; -use crate::pyobject::{AttributeProtocol, PyContext, PyResult, TypeProtocol}; +use super::objtype::PyClassRef; +use crate::pyobject::{PyContext, PyObjectRef, PyRef, PyResult, PyValue}; use crate::vm::VirtualMachine; -pub fn init(context: &PyContext) { - let staticmethod_type = &context.staticmethod_type; - extend_class!(context, staticmethod_type, { - "__get__" => context.new_rustfunc(staticmethod_get), - "__new__" => context.new_rustfunc(staticmethod_new), - }); +#[derive(Clone, Debug)] +pub struct PyStaticMethod { + pub callable: PyObjectRef, } +pub type PyStaticMethodRef = PyRef; -// `staticmethod` methods. -fn staticmethod_get(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - trace!("staticmethod.__get__ {:?}", args.args); - arg_check!( - vm, - args, - required = [ - (cls, Some(vm.ctx.staticmethod_type())), - (_inst, None), - (_owner, None) - ] - ); - match cls.get_attr("function") { - Some(function) => Ok(function), - None => Err(vm.new_attribute_error( - "Attribute Error: staticmethod must have 'function' attribute".to_string(), - )), +impl PyValue for PyStaticMethod { + fn class(vm: &mut VirtualMachine) -> PyObjectRef { + vm.ctx.staticmethod_type() } } -fn staticmethod_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - trace!("staticmethod.__new__ {:?}", args.args); - arg_check!(vm, args, required = [(cls, None), (callable, None)]); +impl PyStaticMethodRef { + fn new( + cls: PyClassRef, + callable: PyObjectRef, + vm: &mut VirtualMachine, + ) -> PyResult { + PyStaticMethod { + callable: callable.clone(), + } + .into_ref_with_type(vm, cls) + } + + fn get(self, _inst: PyObjectRef, _owner: PyObjectRef, _vm: &mut VirtualMachine) -> PyResult { + Ok(self.callable.clone()) + } +} - let py_obj = vm.ctx.new_instance(cls.clone(), None); - vm.ctx.set_attr(&py_obj, "function", callable.clone()); - Ok(py_obj) +pub fn init(context: &PyContext) { + let staticmethod_type = &context.staticmethod_type; + extend_class!(context, staticmethod_type, { + "__get__" => context.new_rustfunc(PyStaticMethodRef::get), + "__new__" => context.new_rustfunc(PyStaticMethodRef::new), + }); } diff --git a/vm/src/stdlib/io.rs b/vm/src/stdlib/io.rs index aba31198aa..5ba8197fbf 100644 --- a/vm/src/stdlib/io.rs +++ b/vm/src/stdlib/io.rs @@ -20,8 +20,7 @@ use crate::obj::objbytes; use crate::obj::objint; use crate::obj::objstr; use crate::pyobject::{ - AttributeProtocol, BufferProtocol, PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue, - TypeProtocol, + BufferProtocol, PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -165,7 +164,7 @@ fn file_io_init(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { fn file_io_read(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(file_io, None)]); - let py_name = file_io.get_attr("name").unwrap(); + let py_name = vm.get_attribute(file_io.clone(), "name")?; let f = match File::open(objstr::get_value(&py_name)) { Ok(v) => Ok(v), Err(_) => Err(vm.new_type_error("Error opening file".to_string())), @@ -200,7 +199,7 @@ fn file_io_readinto(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let py_length = vm.call_method(obj, "__len__", PyFuncArgs::default())?; let length = objint::get_value(&py_length).to_u64().unwrap(); - let file_no = file_io.get_attr("fileno").unwrap(); + let file_no = vm.get_attribute(file_io.clone(), "fileno")?; let raw_fd = objint::get_value(&file_no).to_i64().unwrap(); //extract unix file descriptor. @@ -230,7 +229,7 @@ fn file_io_write(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { required = [(file_io, None), (obj, Some(vm.ctx.bytes_type()))] ); - let file_no = file_io.get_attr("fileno").unwrap(); + let file_no = vm.get_attribute(file_io.clone(), "fileno")?; let raw_fd = objint::get_value(&file_no).to_i64().unwrap(); //unsafe block - creates file handle from the UNIX file descriptor diff --git a/vm/src/stdlib/re.rs b/vm/src/stdlib/re.rs index eda5be75f1..8fc7e359ed 100644 --- a/vm/src/stdlib/re.rs +++ b/vm/src/stdlib/re.rs @@ -12,14 +12,12 @@ use regex::{Match, Regex}; use crate::function::PyFuncArgs; use crate::import; use crate::obj::objstr; -use crate::pyobject::{ - AttributeProtocol, PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, -}; +use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol}; use crate::vm::VirtualMachine; impl PyValue for Regex { fn class(vm: &mut VirtualMachine) -> PyObjectRef { - vm.import("re").unwrap().get_attr("Pattern").unwrap() + vm.class("re", "Pattern") } } diff --git a/vm/src/sysmodule.rs b/vm/src/sysmodule.rs index e2713d7834..6bfa14eb3e 100644 --- a/vm/src/sysmodule.rs +++ b/vm/src/sysmodule.rs @@ -57,7 +57,7 @@ fn sys_getsizeof(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { Ok(vm.ctx.new_int(size)) } -pub fn make_module(ctx: &PyContext) -> PyObjectRef { +pub fn make_module(ctx: &PyContext, builtins: PyObjectRef) -> PyObjectRef { let path_list = match env::var_os("PYTHONPATH") { Some(paths) => env::split_paths(&paths) .map(|path| { @@ -156,6 +156,7 @@ settrace() -- set the global debug tracing function }); modules.set_item(&ctx, sys_name, sys_mod.clone()); + modules.set_item(&ctx, "builtins", builtins); ctx.set_attr(&sys_mod, "modules", modules); sys_mod diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 7f9b474d0a..594b596381 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -57,11 +57,7 @@ impl VirtualMachine { // Hard-core modules: let builtins = builtins::make_module(&ctx); - let sysmod = sysmodule::make_module(&ctx); - - // Add builtins as builtins module: - let modules = sysmod.get_attr("modules").unwrap(); - modules.set_item(&ctx, "builtins", builtins.clone()); + let sysmod = sysmodule::make_module(&ctx, builtins.clone()); let stdlib_inits = stdlib::get_module_inits(); VirtualMachine { @@ -105,10 +101,11 @@ impl VirtualMachine { } pub fn class(&mut self, module: &str, class: &str) -> PyObjectRef { - self.import(module) - .unwrap_or_else(|_| panic!("unable to import {}", module)) - .get_attr(class) - .unwrap_or_else(|| panic!("module {} has no class {}", module, class)) + let module = self + .import(module) + .unwrap_or_else(|_| panic!("unable to import {}", module)); + self.get_attribute(module.clone(), class) + .unwrap_or_else(|_| panic!("module {} has no class {}", module, class)) } /// Create a new python string object. pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy