Merge pull request #3334 from DimitrisJim/namespace_fixes

Namespace fixes
This commit is contained in:
Jeong YunWon
2021-10-21 01:35:04 +09:00
committed by GitHub
2 changed files with 66 additions and 18 deletions

View File

@@ -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()
@@ -1295,8 +1293,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()
@@ -1335,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()

View File

@@ -1,8 +1,11 @@
use super::PyTypeRef;
use crate::{
function::{IntoPyObject, KwArgs},
types::Constructor,
PyClassImpl, PyContext, PyRef, PyResult, PyValue, VirtualMachine,
builtins::PyDict,
function::FuncArgs,
types::{Comparable, Constructor, PyComparisonOp},
vm::ReprGuard,
IdProtocol, PyClassImpl, PyComparisonValue, PyContext, PyObjectRef, PyRef, PyResult, PyValue,
TypeProtocol, VirtualMachine,
};
/// A simple attribute-based namespace.
@@ -19,14 +22,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)
}
}
@@ -36,8 +35,63 @@ impl PyNamespace {
}
}
#[pyimpl(flags(BASETYPE, HAS_DICT), with(Constructor))]
impl PyNamespace {}
#[pyimpl(flags(BASETYPE, HAS_DICT), with(Constructor, Comparable))]
impl PyNamespace {
#[pymethod(magic)]
fn init(zelf: PyRef<Self>, 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(())
}
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<String> {
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 {
fn cmp(
zelf: &PyRef<Self>,
other: &PyObjectRef,
op: PyComparisonOp,
vm: &VirtualMachine,
) -> PyResult<PyComparisonValue> {
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);