From dd482371e76ca7e4be54ee6c21959d2cd384f241 Mon Sep 17 00:00:00 2001 From: jfh Date: Mon, 18 Oct 2021 10:52:16 +0300 Subject: [PATCH 1/3] Move initialization to __init__. --- vm/src/builtins/namespace.rs | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/vm/src/builtins/namespace.rs b/vm/src/builtins/namespace.rs index 36edb1ef6c..d8c4cc3579 100644 --- a/vm/src/builtins/namespace.rs +++ b/vm/src/builtins/namespace.rs @@ -1,8 +1,7 @@ use super::PyTypeRef; use crate::{ - function::{IntoPyObject, KwArgs}, - types::Constructor, - PyClassImpl, PyContext, PyRef, PyResult, PyValue, VirtualMachine, + function::FuncArgs, types::Constructor, PyClassImpl, PyContext, PyRef, PyResult, PyValue, + VirtualMachine, }; /// A simple attribute-based namespace. @@ -19,14 +18,10 @@ impl PyValue for PyNamespace { } impl Constructor for PyNamespace { - type Args = KwArgs; + type Args = FuncArgs; - fn py_new(cls: PyTypeRef, kwargs: Self::Args, vm: &VirtualMachine) -> PyResult { - let zelf = PyNamespace.into_ref_with_type(vm, cls)?; - for (name, value) in kwargs.into_iter() { - zelf.as_object().set_attr(name, value, vm)?; - } - Ok(zelf.into_pyobject(vm)) + fn py_new(cls: PyTypeRef, _args: Self::Args, vm: &VirtualMachine) -> PyResult { + PyNamespace {}.into_pyresult_with_type(vm, cls) } } @@ -37,7 +32,18 @@ impl PyNamespace { } #[pyimpl(flags(BASETYPE, HAS_DICT), with(Constructor))] -impl PyNamespace {} +impl PyNamespace { + #[pymethod(magic)] + fn init(zelf: PyRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> { + if !args.args.is_empty() { + return Err(vm.new_type_error("no positional arguments expected".to_owned())); + } + for (name, value) in args.kwargs.into_iter() { + zelf.as_object().set_attr(name, value, vm)?; + } + Ok(()) + } +} pub fn init(context: &PyContext) { PyNamespace::extend_class(context, &context.types.namespace_type); From 809171dcf8e490e0694f7e4961073c83aed9e9bf Mon Sep 17 00:00:00 2001 From: jfh Date: Mon, 18 Oct 2021 12:28:14 +0300 Subject: [PATCH 2/3] Make namespaces comparable. --- Lib/test/test_types.py | 2 -- vm/src/builtins/namespace.rs | 22 ++++++++++++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index be218da341..009ebcbb2d 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1295,8 +1295,6 @@ class SimpleNamespaceTests(unittest.TestCase): self.assertEqual(repr(ns1), "{name}(x=1, y=2, w=3)".format(name=name)) self.assertEqual(repr(ns2), "{name}(x='spam', _y=5)".format(name=name)) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_equal(self): ns1 = types.SimpleNamespace(x=1) ns2 = types.SimpleNamespace() diff --git a/vm/src/builtins/namespace.rs b/vm/src/builtins/namespace.rs index d8c4cc3579..e448d0ebfb 100644 --- a/vm/src/builtins/namespace.rs +++ b/vm/src/builtins/namespace.rs @@ -1,6 +1,9 @@ use super::PyTypeRef; use crate::{ - function::FuncArgs, types::Constructor, PyClassImpl, PyContext, PyRef, PyResult, PyValue, + builtins::PyDict, + function::FuncArgs, + types::{Comparable, Constructor, PyComparisonOp}, + PyClassImpl, PyComparisonValue, PyContext, PyObjectRef, PyRef, PyResult, PyValue, VirtualMachine, }; @@ -31,7 +34,7 @@ impl PyNamespace { } } -#[pyimpl(flags(BASETYPE, HAS_DICT), with(Constructor))] +#[pyimpl(flags(BASETYPE, HAS_DICT), with(Constructor, Comparable))] impl PyNamespace { #[pymethod(magic)] fn init(zelf: PyRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> { @@ -45,6 +48,21 @@ impl PyNamespace { } } +impl Comparable for PyNamespace { + fn cmp( + zelf: &PyRef, + other: &PyObjectRef, + op: PyComparisonOp, + vm: &VirtualMachine, + ) -> PyResult { + let other = class_or_notimplemented!(Self, other); + match (zelf.as_object().dict(), other.as_object().dict()) { + (Some(d1), Some(d2)) => PyDict::cmp(&d1, d2.as_object(), op, vm), + _ => Ok(PyComparisonValue::NotImplemented), + } + } +} + pub fn init(context: &PyContext) { PyNamespace::extend_class(context, &context.types.namespace_type); } From c6a8511425c2069a7f9fc4679647db514284cfda Mon Sep 17 00:00:00 2001 From: jfh Date: Mon, 18 Oct 2021 13:15:22 +0300 Subject: [PATCH 3/3] Add repr for namespaces. --- Lib/test/test_types.py | 4 ---- vm/src/builtins/namespace.rs | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 009ebcbb2d..cc2aff0f57 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1283,8 +1283,6 @@ class SimpleNamespaceTests(unittest.TestCase): del ns1.spam self.assertEqual(vars(ns1), {}) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_repr(self): ns1 = types.SimpleNamespace(x=1, y=2, w=3) ns2 = types.SimpleNamespace() @@ -1333,8 +1331,6 @@ class SimpleNamespaceTests(unittest.TestCase): self.assertEqual(ns3.spam, ns2) self.assertEqual(ns2.spam.spam, ns2) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_recursive_repr(self): ns1 = types.SimpleNamespace(c='cookie') ns2 = types.SimpleNamespace() diff --git a/vm/src/builtins/namespace.rs b/vm/src/builtins/namespace.rs index e448d0ebfb..910bc354fd 100644 --- a/vm/src/builtins/namespace.rs +++ b/vm/src/builtins/namespace.rs @@ -3,8 +3,9 @@ use crate::{ builtins::PyDict, function::FuncArgs, types::{Comparable, Constructor, PyComparisonOp}, - PyClassImpl, PyComparisonValue, PyContext, PyObjectRef, PyRef, PyResult, PyValue, - VirtualMachine, + vm::ReprGuard, + IdProtocol, PyClassImpl, PyComparisonValue, PyContext, PyObjectRef, PyRef, PyResult, PyValue, + TypeProtocol, VirtualMachine, }; /// A simple attribute-based namespace. @@ -46,6 +47,35 @@ impl PyNamespace { } Ok(()) } + + #[pymethod(magic)] + fn repr(zelf: PyRef, vm: &VirtualMachine) -> PyResult { + let o = zelf.as_object(); + let name = if o.class().is(&vm.ctx.types.namespace_type) { + "namespace".to_owned() + } else { + o.class().slot_name() + }; + + let repr = if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) { + let parts = if let Some(dict) = zelf.as_object().dict() { + let mut parts = Vec::with_capacity(dict.len()); + for (key, value) in dict { + let k = vm.to_repr(&key)?; + let key_str = k.as_str(); + let value_repr = vm.to_repr(&value)?; + parts.push(format!("{}={}", &key_str[1..key_str.len() - 1], value_repr)); + } + parts + } else { + vec![] + }; + format!("{}({})", name, parts.join(", ")) + } else { + format!("{}(...)", name) + }; + Ok(repr) + } } impl Comparable for PyNamespace {