diff --git a/Lib/atexit.py b/Lib/atexit.py new file mode 100644 index 000000000..c990e82ba --- /dev/null +++ b/Lib/atexit.py @@ -0,0 +1,9 @@ +# Dummy implementation of atexit + + +def register(func, *args, **kwargs): + return func + + +def unregister(func): + pass diff --git a/vm/src/macros.rs b/vm/src/macros.rs index 39150b307..7dca09f4d 100644 --- a/vm/src/macros.rs +++ b/vm/src/macros.rs @@ -116,22 +116,22 @@ macro_rules! no_kwargs { #[macro_export] macro_rules! py_module { - ( $vm:expr, $module_name:expr, { $($name:expr => $value:expr),* $(,)* }) => {{ + ( $vm:expr, $module_name:expr, { $($name:expr => $value:expr),* $(,)? }) => {{ let module = $vm.new_module($module_name, $vm.ctx.new_dict()); - $( - $vm.set_attr(&module, $name, $value).unwrap(); - )* + $crate::extend_module!($vm, module, { $($name => $value),* }); module }}; } #[macro_export] macro_rules! extend_module { - ( $vm:expr, $module:expr, { $($name:expr => $value:expr),* $(,)* }) => { + ( $vm:expr, $module:expr, { $($name:expr => $value:expr),* $(,)? }) => {{ + #[allow(unused_variables)] + let module: &$crate::pyobject::PyObjectRef = &$module; $( - $vm.set_attr(&$module, $name, $value).unwrap(); + $vm.__module_set_attr(&module, $name, $value).unwrap(); )* - } + }}; } #[macro_export] diff --git a/vm/src/obj/objfunction.rs b/vm/src/obj/objfunction.rs index 5742a9553..e780fc316 100644 --- a/vm/src/obj/objfunction.rs +++ b/vm/src/obj/objfunction.rs @@ -64,11 +64,24 @@ pub struct PyMethod { // TODO: these shouldn't be public pub object: PyObjectRef, pub function: PyObjectRef, + pub actually_bind: bool, } impl PyMethod { pub fn new(object: PyObjectRef, function: PyObjectRef) -> Self { - PyMethod { object, function } + PyMethod { + object, + function, + actually_bind: true, + } + } + + pub fn new_nobind(object: PyObjectRef, function: PyObjectRef) -> Self { + PyMethod { + object, + function, + actually_bind: false, + } } fn getattribute(&self, name: PyStringRef, vm: &VirtualMachine) -> PyResult { diff --git a/vm/src/vm.rs b/vm/src/vm.rs index f9cac2244..85f50e820 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -580,9 +580,15 @@ impl VirtualMachine { } else if let Some(PyMethod { ref function, ref object, + actually_bind, }) = func_ref.payload() { - self.invoke(&function, args.insert(object.clone())) + let args = if *actually_bind { + args.insert(object.clone()) + } else { + args + }; + self.invoke(&function, args) } else if let Some(PyBuiltinFunction { ref value }) = func_ref.payload() { value(self, args) } else if self.is_callable(&func_ref) { @@ -1303,6 +1309,28 @@ impl VirtualMachine { }; Ok(value) } + + #[doc(hidden)] + pub fn __module_set_attr( + &self, + module: &PyObjectRef, + attr_name: impl TryIntoRef, + attr_value: impl Into, + ) -> PyResult<()> { + let val = attr_value.into(); + let val = if val + .class() + .is(&self.ctx.types.builtin_function_or_method_type) + { + PyMethod::new_nobind(module.clone(), val) + .into_ref(self) + .into_object() + } else { + val + }; + self.set_attr(module, attr_name, val)?; + Ok(()) + } } impl Default for VirtualMachine {