forked from RustPython/RustPython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnamespace.rs
More file actions
102 lines (91 loc) · 2.98 KB
/
namespace.rs
File metadata and controls
102 lines (91 loc) · 2.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use super::{PyType, PyTypeRef};
use crate::{
builtins::PyDict,
class::PyClassImpl,
function::{FuncArgs, PyComparisonValue},
recursion::ReprGuard,
types::{Comparable, Constructor, Initializer, PyComparisonOp},
AsObject, Context, Py, PyObject, PyPayload, PyRef, PyResult, VirtualMachine,
};
/// A simple attribute-based namespace.
///
/// SimpleNamespace(**kwargs)
#[pyclass(module = false, name = "SimpleNamespace")]
#[derive(Debug)]
pub struct PyNamespace {}
impl PyPayload for PyNamespace {
fn class(vm: &VirtualMachine) -> &'static Py<PyType> {
vm.ctx.types.namespace_type
}
}
impl Constructor for PyNamespace {
type Args = FuncArgs;
fn py_new(cls: PyTypeRef, _args: Self::Args, vm: &VirtualMachine) -> PyResult {
PyNamespace {}.into_ref_with_type(vm, cls).map(Into::into)
}
}
impl PyNamespace {
pub fn new_ref(ctx: &Context) -> PyRef<Self> {
PyRef::new_ref(
Self {},
ctx.types.namespace_type.to_owned(),
Some(ctx.new_dict()),
)
}
}
#[pyclass(flags(BASETYPE, HAS_DICT), with(Constructor, Initializer, Comparable))]
impl PyNamespace {
#[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 dict = zelf.as_object().dict().unwrap();
let mut parts = Vec::with_capacity(dict.len());
for (key, value) in dict {
let k = &key.repr(vm)?;
let key_str = k.as_str();
let value_repr = value.repr(vm)?;
parts.push(format!("{}={}", &key_str[1..key_str.len() - 1], value_repr));
}
format!("{}({})", name, parts.join(", "))
} else {
format!("{name}(...)")
};
Ok(repr)
}
}
impl Initializer for PyNamespace {
type Args = FuncArgs;
fn init(zelf: PyRef<Self>, args: Self::Args, 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(())
}
}
impl Comparable for PyNamespace {
fn cmp(
zelf: &crate::Py<Self>,
other: &PyObject,
op: PyComparisonOp,
vm: &VirtualMachine,
) -> PyResult<PyComparisonValue> {
let other = class_or_notimplemented!(Self, other);
let (d1, d2) = (
zelf.as_object().dict().unwrap(),
other.as_object().dict().unwrap(),
);
PyDict::cmp(&d1, d2.as_object(), op, vm)
}
}
pub fn init(context: &Context) {
PyNamespace::extend_class(context, context.types.namespace_type);
}