Clean up PyDict

This commit is contained in:
Jeong Yunwon
2022-04-27 02:02:31 +09:00
parent fdc95e3098
commit 955c3fdfbe

View File

@@ -62,15 +62,7 @@ impl PyDict {
pub fn new_ref(ctx: &Context) -> PyRef<Self> {
PyRef::new_ref(Self::default(), ctx.types.dict_type.clone(), None)
}
}
// Python dict methods:
#[allow(clippy::len_without_is_empty)]
#[pyimpl(
with(Initializer, AsMapping, Hashable, Comparable, Iterable, AsSequence),
flags(BASETYPE)
)]
impl PyDict {
/// escape hatch to access the underlying data structure directly. prefer adding a method on
/// PyDict instead of using this
pub(crate) fn _as_dict_inner(&self) -> &DictContentType {
@@ -81,13 +73,6 @@ impl PyDict {
Self { entries }
}
#[pyslot]
fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
PyDict::default()
.into_ref_with_type(vm, cls)
.map(Into::into)
}
// Used in update and ior.
fn merge_object(
dict: &DictContentType,
@@ -141,36 +126,6 @@ impl PyDict {
Ok(())
}
#[pyclassmethod]
fn fromkeys(
class: PyTypeRef,
iterable: ArgIterable,
value: OptionalArg<PyObjectRef>,
vm: &VirtualMachine,
) -> PyResult {
let value = value.unwrap_or_none(vm);
let d = PyType::call(&class, ().into(), vm)?;
match d.downcast_exact::<PyDict>(vm) {
Ok(pydict) => {
for key in iterable.iter(vm)? {
pydict.setitem(key?, value.clone(), vm)?;
}
Ok(pydict.to_pyobject(vm))
}
Err(pyobj) => {
for key in iterable.iter(vm)? {
pyobj.set_item(key?, value.clone(), vm)?;
}
Ok(pyobj)
}
}
}
#[pymethod(magic)]
fn bool(&self) -> bool {
!self.entries.is_empty()
}
fn inner_cmp(
zelf: &Py<Self>,
other: &Py<PyDict>,
@@ -208,13 +163,122 @@ impl PyDict {
Ok(Implemented(true))
}
pub fn is_empty(&self) -> bool {
self.entries.len() == 0
}
/// Set item variant which can be called with multiple
/// key types, such as str to name a notable one.
pub(crate) fn inner_setitem<K: DictKey + ToPyObject>(
&self,
key: K,
value: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<()> {
self.entries.insert(vm, key, value)
}
pub(crate) fn inner_delitem<K: DictKey + ToPyObject>(
&self,
key: K,
vm: &VirtualMachine,
) -> PyResult<()> {
self.entries.delete(vm, key)
}
pub fn get_or_insert(
&self,
vm: &VirtualMachine,
key: PyObjectRef,
default: impl FnOnce() -> PyObjectRef,
) -> PyResult {
self.entries.setdefault(vm, key, default)
}
pub fn from_attributes(attrs: PyAttributes, vm: &VirtualMachine) -> PyResult<Self> {
let dict = DictContentType::default();
for (key, value) in attrs {
dict.insert(vm, vm.new_pyobj(key), value)?;
}
Ok(PyDict { entries: dict })
}
pub fn contains_key<K: ToPyObject>(&self, key: K, vm: &VirtualMachine) -> bool {
let key = key.to_pyobject(vm);
self.entries.contains(vm, &key).unwrap()
}
pub fn size(&self) -> dictdatatype::DictSize {
self.entries.size()
}
pub(crate) const MAPPING_METHODS: PyMappingMethods = PyMappingMethods {
length: Some(|mapping, _vm| Ok(Self::mapping_downcast(mapping).len())),
subscript: Some(|mapping, needle, vm| {
Self::mapping_downcast(mapping).inner_getitem(needle, vm)
}),
ass_subscript: Some(|mapping, needle, value, vm| {
let zelf = Self::mapping_downcast(mapping);
if let Some(value) = value {
zelf.inner_setitem(needle, value, vm)
} else {
zelf.inner_delitem(needle, vm)
}
}),
};
}
// Python dict methods:
#[allow(clippy::len_without_is_empty)]
#[pyimpl(
with(
Constructor,
Initializer,
AsMapping,
Hashable,
Comparable,
Iterable,
AsSequence
),
flags(BASETYPE)
)]
impl PyDict {
#[pyclassmethod]
fn fromkeys(
class: PyTypeRef,
iterable: ArgIterable,
value: OptionalArg<PyObjectRef>,
vm: &VirtualMachine,
) -> PyResult {
let value = value.unwrap_or_none(vm);
let d = PyType::call(&class, ().into(), vm)?;
match d.downcast_exact::<PyDict>(vm) {
Ok(pydict) => {
for key in iterable.iter(vm)? {
pydict.setitem(key?, value.clone(), vm)?;
}
Ok(pydict.to_pyobject(vm))
}
Err(pyobj) => {
for key in iterable.iter(vm)? {
pyobj.set_item(key?, value.clone(), vm)?;
}
Ok(pyobj)
}
}
}
#[pymethod(magic)]
fn bool(&self) -> bool {
!self.entries.is_empty()
}
#[pymethod(magic)]
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.len() == 0
}
#[pymethod(magic)]
fn sizeof(&self) -> usize {
@@ -273,25 +337,6 @@ impl PyDict {
self.inner_setitem(key, value, vm)
}
/// Set item variant which can be called with multiple
/// key types, such as str to name a notable one.
pub(crate) fn inner_setitem<K: DictKey + ToPyObject>(
&self,
key: K,
value: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<()> {
self.entries.insert(vm, key, value)
}
pub(crate) fn inner_delitem<K: DictKey + ToPyObject>(
&self,
key: K,
vm: &VirtualMachine,
) -> PyResult<()> {
self.entries.delete(vm, key)
}
#[pymethod(magic)]
#[cfg_attr(feature = "flame-it", flame("PyDictRef"))]
fn getitem(zelf: PyRef<Self>, key: PyObjectRef, vm: &VirtualMachine) -> PyResult {
@@ -322,15 +367,6 @@ impl PyDict {
.setdefault(vm, key, || default.unwrap_or_none(vm))
}
pub fn get_or_insert(
&self,
vm: &VirtualMachine,
key: PyObjectRef,
default: impl FnOnce() -> PyObjectRef,
) -> PyResult {
self.entries.setdefault(vm, key, default)
}
#[pymethod]
pub fn copy(&self) -> PyDict {
PyDict {
@@ -407,25 +443,6 @@ impl PyDict {
Ok((key, value))
}
pub fn from_attributes(attrs: PyAttributes, vm: &VirtualMachine) -> PyResult<Self> {
let dict = DictContentType::default();
for (key, value) in attrs {
dict.insert(vm, vm.new_pyobj(key), value)?;
}
Ok(PyDict { entries: dict })
}
pub fn contains_key<K: ToPyObject>(&self, key: K, vm: &VirtualMachine) -> bool {
let key = key.to_pyobject(vm);
self.entries.contains(vm, &key).unwrap()
}
pub fn size(&self) -> dictdatatype::DictSize {
self.entries.size()
}
#[pymethod(magic)]
fn reversed(zelf: PyRef<Self>) -> PyDictReverseKeyIterator {
PyDictReverseKeyIterator::new(zelf)
@@ -437,21 +454,14 @@ impl PyDict {
}
}
impl PyDict {
pub(crate) const MAPPING_METHODS: PyMappingMethods = PyMappingMethods {
length: Some(|mapping, _vm| Ok(Self::mapping_downcast(mapping).len())),
subscript: Some(|mapping, needle, vm| {
Self::mapping_downcast(mapping).inner_getitem(needle, vm)
}),
ass_subscript: Some(|mapping, needle, value, vm| {
let zelf = Self::mapping_downcast(mapping);
if let Some(value) = value {
zelf.inner_setitem(needle, value, vm)
} else {
zelf.inner_delitem(needle, vm)
}
}),
};
impl Constructor for PyDict {
type Args = FuncArgs;
fn py_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
PyDict::default()
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
impl Initializer for PyDict {