Merge pull request #2035 from youknowone/dictkey

Refactor DictKey
This commit is contained in:
Jeong YunWon
2020-08-04 02:45:05 +09:00
committed by GitHub
18 changed files with 126 additions and 137 deletions

View File

@@ -68,7 +68,7 @@ pub fn hash_float(value: f64) -> PyHash {
x as PyHash * value.signum() as PyHash
}
pub fn hash_value<T: Hash>(data: &T) -> PyHash {
pub fn hash_value<T: Hash + ?Sized>(data: &T) -> PyHash {
let mut hasher = DefaultHasher::new();
data.hash(&mut hasher);
hasher.finish() as PyHash

View File

@@ -40,7 +40,7 @@ macro_rules! add_python_function {
// inserts the first function found in the module into the provided scope.
$scope.globals.set_item(
&def.obj_name,
def.obj_name.as_str(),
$vm.context().new_pyfunction(
vm::obj::objcode::PyCode::new(*def.clone()).into_ref(&$vm),
$scope.clone(),

View File

@@ -883,9 +883,9 @@ impl PyBytesInner {
return self
.elements
.iter()
.cloned()
.copied()
.filter(|x| *x != b'\t')
.collect::<Vec<u8>>();
.collect();
}
for i in &self.elements {

View File

@@ -130,18 +130,16 @@ impl<T: Clone> Dict<T> {
}
/// Store a key
pub fn insert<K: DictKey + IntoPyObject + Copy>(
&self,
vm: &VirtualMachine,
key: K,
value: T,
) -> PyResult<()> {
pub fn insert<K>(&self, vm: &VirtualMachine, key: K, value: T) -> PyResult<()>
where
K: DictKey,
{
// This does not need to be accurate so we can take the lock mutiple times.
if self.borrow_value().indices.len() > 2 * self.borrow_value().size {
self.resize();
}
loop {
match self.lookup(vm, key)? {
match self.lookup(vm, &key)? {
LookupResult::Existing(index) => {
let mut inner = self.borrow_value_mut();
// Update existing key
@@ -166,7 +164,7 @@ impl<T: Clone> Dict<T> {
}
}
pub fn contains<K: DictKey + Copy>(&self, vm: &VirtualMachine, key: K) -> PyResult<bool> {
pub fn contains<K: DictKey>(&self, vm: &VirtualMachine, key: &K) -> PyResult<bool> {
if let LookupResult::Existing(_) = self.lookup(vm, key)? {
Ok(true)
} else {
@@ -176,7 +174,7 @@ impl<T: Clone> Dict<T> {
/// Retrieve a key
#[cfg_attr(feature = "flame-it", flame("Dict"))]
pub fn get<K: DictKey + Copy>(&self, vm: &VirtualMachine, key: K) -> PyResult<Option<T>> {
pub fn get<K: DictKey>(&self, vm: &VirtualMachine, key: &K) -> PyResult<Option<T>> {
loop {
if let LookupResult::Existing(index) = self.lookup(vm, key)? {
if let Some(entry) = &self.borrow_value().entries[index] {
@@ -304,7 +302,7 @@ impl<T: Clone> Dict<T> {
/// Lookup the index for the given key.
#[cfg_attr(feature = "flame-it", flame("Dict"))]
fn lookup<K: DictKey + Copy>(&self, vm: &VirtualMachine, key: K) -> PyResult<LookupResult> {
fn lookup<K: DictKey>(&self, vm: &VirtualMachine, key: &K) -> PyResult<LookupResult> {
let hash_value = key.do_hash(vm)?;
let perturb = hash_value;
let mut hash_index: HashIndex = hash_value;
@@ -359,7 +357,7 @@ impl<T: Clone> Dict<T> {
}
/// Retrieve and delete a key
pub fn pop<K: DictKey + Copy>(&self, vm: &VirtualMachine, key: K) -> PyResult<Option<T>> {
pub fn pop<K: DictKey>(&self, vm: &VirtualMachine, key: &K) -> PyResult<Option<T>> {
loop {
if let LookupResult::Existing(index) = self.lookup(vm, key)? {
let mut inner = self.borrow_value_mut();
@@ -413,41 +411,41 @@ enum LookupResult {
/// the dictionary. Typical usecases are:
/// - PyObjectRef -> arbitrary python type used as key
/// - str -> string reference used as key, this is often used internally
pub trait DictKey {
fn do_hash(self, vm: &VirtualMachine) -> PyResult<HashValue>;
fn do_is(self, other: &PyObjectRef) -> bool;
fn do_eq(self, vm: &VirtualMachine, other_key: &PyObjectRef) -> PyResult<bool>;
pub trait DictKey: IntoPyObject {
fn do_hash(&self, vm: &VirtualMachine) -> PyResult<HashValue>;
fn do_is(&self, other: &PyObjectRef) -> bool;
fn do_eq(&self, vm: &VirtualMachine, other_key: &PyObjectRef) -> PyResult<bool>;
}
/// Implement trait for PyObjectRef such that we can use python objects
/// to index dictionaries.
impl DictKey for &PyObjectRef {
fn do_hash(self, vm: &VirtualMachine) -> PyResult<HashValue> {
impl DictKey for PyObjectRef {
fn do_hash(&self, vm: &VirtualMachine) -> PyResult<HashValue> {
let raw_hash = vm._hash(self)?;
let mut hasher = DefaultHasher::new();
raw_hash.hash(&mut hasher);
Ok(hasher.finish() as HashValue)
}
fn do_is(self, other: &PyObjectRef) -> bool {
fn do_is(&self, other: &PyObjectRef) -> bool {
self.is(other)
}
fn do_eq(self, vm: &VirtualMachine, other_key: &PyObjectRef) -> PyResult<bool> {
fn do_eq(&self, vm: &VirtualMachine, other_key: &PyObjectRef) -> PyResult<bool> {
vm.identical_or_equal(self, other_key)
}
}
impl DictKey for &PyStringRef {
fn do_hash(self, _vm: &VirtualMachine) -> PyResult<HashValue> {
impl DictKey for PyStringRef {
fn do_hash(&self, _vm: &VirtualMachine) -> PyResult<HashValue> {
Ok(self.hash())
}
fn do_is(self, other: &PyObjectRef) -> bool {
fn do_is(&self, other: &PyObjectRef) -> bool {
self.is(other)
}
fn do_eq(self, vm: &VirtualMachine, other_key: &PyObjectRef) -> PyResult<bool> {
fn do_eq(&self, vm: &VirtualMachine, other_key: &PyObjectRef) -> PyResult<bool> {
if self.is(other_key) {
Ok(true)
} else if let Some(py_str_value) = other_key.payload::<PyString>() {
@@ -458,49 +456,37 @@ impl DictKey for &PyStringRef {
}
}
// AsRef<str> fit this case but not possible in rust 1.46
/// Implement trait for the str type, so that we can use strings
/// to index dictionaries.
impl DictKey for &str {
fn do_hash(self, _vm: &VirtualMachine) -> PyResult<HashValue> {
fn do_hash(&self, _vm: &VirtualMachine) -> PyResult<HashValue> {
// follow a similar route as the hashing of PyStringRef
let raw_hash = hash::hash_value(&self.to_owned()).to_bigint().unwrap();
let raw_hash = hash::hash_value(*self).to_bigint().unwrap();
let raw_hash = hash::hash_bigint(&raw_hash);
let mut hasher = DefaultHasher::new();
raw_hash.hash(&mut hasher);
Ok(hasher.finish() as HashValue)
}
fn do_is(self, _other: &PyObjectRef) -> bool {
fn do_is(&self, _other: &PyObjectRef) -> bool {
// No matter who the other pyobject is, we are never the same thing, since
// we are a str, not a pyobject.
false
}
fn do_eq(self, vm: &VirtualMachine, other_key: &PyObjectRef) -> PyResult<bool> {
fn do_eq(&self, vm: &VirtualMachine, other_key: &PyObjectRef) -> PyResult<bool> {
if let Some(py_str_value) = other_key.payload::<PyString>() {
Ok(py_str_value.as_str() == self)
Ok(py_str_value.as_str() == *self)
} else {
// Fall back to PyString implementation.
let s = vm.new_str(self.to_owned());
let s = vm.ctx.new_str(*self);
s.do_eq(vm, other_key)
}
}
}
impl DictKey for &String {
fn do_hash(self, vm: &VirtualMachine) -> PyResult<HashValue> {
self.as_str().do_hash(vm)
}
fn do_is(self, other: &PyObjectRef) -> bool {
self.as_str().do_is(other)
}
fn do_eq(self, vm: &VirtualMachine, other_key: &PyObjectRef) -> PyResult<bool> {
self.as_str().do_eq(vm, other_key)
}
}
#[cfg(test)]
mod tests {
use super::{Dict, DictKey, VirtualMachine};
@@ -513,27 +499,27 @@ mod tests {
let key1 = vm.new_bool(true);
let value1 = vm.new_str("abc".to_owned());
dict.insert(&vm, &key1, value1.clone()).unwrap();
dict.insert(&vm, key1.clone(), value1.clone()).unwrap();
assert_eq!(1, dict.len());
let key2 = vm.new_str("x".to_owned());
let value2 = vm.new_str("def".to_owned());
dict.insert(&vm, &key2, value2.clone()).unwrap();
dict.insert(&vm, key2.clone(), value2.clone()).unwrap();
assert_eq!(2, dict.len());
dict.insert(&vm, &key1, value2.clone()).unwrap();
dict.insert(&vm, key1.clone(), value2.clone()).unwrap();
assert_eq!(2, dict.len());
dict.delete(&vm, &key1).unwrap();
assert_eq!(1, dict.len());
dict.insert(&vm, &key1, value2.clone()).unwrap();
dict.insert(&vm, key1.clone(), value2.clone()).unwrap();
assert_eq!(2, dict.len());
assert_eq!(true, dict.contains(&vm, &key1).unwrap());
assert_eq!(true, dict.contains(&vm, "x").unwrap());
assert_eq!(true, dict.contains(&vm, &"x").unwrap());
let val = dict.get(&vm, "x").unwrap().unwrap();
let val = dict.get(&vm, &"x").unwrap().unwrap();
vm.bool_eq(val, value2)
.expect("retrieved value must be equal to inserted value.");
}

View File

@@ -956,7 +956,7 @@ impl ExecutingFrame<'_> {
let idx = self.pop_value();
let obj = self.pop_value();
let value = self.pop_value();
obj.set_item(&idx, value, vm)?;
obj.set_item(idx, value, vm)?;
Ok(None)
}
@@ -996,12 +996,12 @@ impl ExecutingFrame<'_> {
return Err(vm.new_type_error(msg));
}
}
map_obj.set_item(&key, value, vm).unwrap();
map_obj.set_item(key, value, vm).unwrap();
}
}
} else {
for (key, value) in self.pop_multiple(2 * size).into_iter().tuples() {
map_obj.set_item(&key, value, vm).unwrap();
map_obj.set_item(key, value, vm).unwrap();
}
}

View File

@@ -70,13 +70,13 @@ impl PyDictRef {
let dicted: Result<PyDictRef, _> = dict_obj.clone().downcast();
if let Ok(dict_obj) = dicted {
for (key, value) in dict_obj {
dict.insert(vm, &key, value)?;
dict.insert(vm, key, value)?;
}
} else if let Some(keys) = vm.get_method(dict_obj.clone(), "keys") {
let keys = objiter::get_iter(vm, &vm.invoke(&keys?, vec![])?)?;
while let Some(key) = objiter::get_next_object(vm, &keys)? {
let val = dict_obj.get_item(&key, vm)?;
dict.insert(vm, &key, val)?;
dict.insert(vm, key, val)?;
}
} else {
let iter = objiter::get_iter(vm, &dict_obj)?;
@@ -94,13 +94,13 @@ impl PyDictRef {
if objiter::get_next_object(vm, &elem_iter)?.is_some() {
return Err(err(vm));
}
dict.insert(vm, &key, value)?;
dict.insert(vm, key, value)?;
}
}
}
for (key, value) in kwargs.into_iter() {
dict.insert(vm, &vm.new_str(key), value)?;
dict.insert(vm, vm.new_str(key), value)?;
}
Ok(())
}
@@ -111,7 +111,7 @@ impl PyDictRef {
vm: &VirtualMachine,
) -> PyResult<()> {
for (key, value) in dict_other {
dict.insert(vm, &key, value)?;
dict.insert(vm, key, value)?;
}
Ok(())
}
@@ -127,7 +127,7 @@ impl PyDictRef {
let value = value.unwrap_or_else(|| vm.ctx.none());
for elem in iterable.iter(vm)? {
let elem = elem?;
dict.insert(vm, &elem, value.clone())?;
dict.insert(vm, elem, value.clone())?;
}
PyDict { entries: dict }.into_ref_with_type(vm, class)
}
@@ -246,12 +246,12 @@ impl PyDictRef {
#[pymethod(magic)]
fn setitem(self, key: PyObjectRef, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
self.inner_setitem_fast(&key, value, vm)
self.inner_setitem_fast(key, value, vm)
}
/// Set item variant which can be called with multiple
/// key types, such as str to name a notable one.
fn inner_setitem_fast<K: DictKey + IntoPyObject + Copy>(
fn inner_setitem_fast<K: DictKey>(
&self,
key: K,
value: PyObjectRef,
@@ -263,20 +263,20 @@ impl PyDictRef {
#[pymethod(magic)]
#[cfg_attr(feature = "flame-it", flame("PyDictRef"))]
fn getitem(self, key: PyObjectRef, vm: &VirtualMachine) -> PyResult {
if let Some(value) = self.inner_getitem_option(&key, vm)? {
if let Some(value) = self.inner_getitem_option(key.clone(), vm)? {
Ok(value)
} else {
Err(vm.new_key_error(key.clone()))
Err(vm.new_key_error(key))
}
}
/// Return an optional inner item, or an error (can be key error as well)
fn inner_getitem_option<K: DictKey + IntoPyObject + Copy>(
fn inner_getitem_option<K: DictKey>(
&self,
key: K,
vm: &VirtualMachine,
) -> PyResult<Option<PyObjectRef>> {
if let Some(value) = self.entries.get(vm, key)? {
if let Some(value) = self.entries.get(vm, &key)? {
return Ok(Some(value));
}
@@ -312,7 +312,7 @@ impl PyDictRef {
Some(value) => Ok(value),
None => {
let set_value = default.unwrap_or_else(|| vm.ctx.none());
self.entries.insert(vm, &key, set_value.clone())?;
self.entries.insert(vm, key, set_value.clone())?;
Ok(set_value)
}
}
@@ -378,7 +378,7 @@ impl PyDictRef {
Some(value) => Ok(value),
None => match default {
OptionalArg::Present(default) => Ok(default),
OptionalArg::Missing => Err(vm.new_key_error(key.clone())),
OptionalArg::Missing => Err(vm.new_key_error(key)),
},
}
}
@@ -407,7 +407,7 @@ impl PyDictRef {
let dict = DictContentType::default();
for (key, value) in attrs {
dict.insert(vm, &vm.ctx.new_str(key), value)?;
dict.insert(vm, vm.ctx.new_str(key), value)?;
}
Ok(PyDict { entries: dict }.into_ref(vm))
@@ -432,7 +432,7 @@ impl PyDictRef {
/// python value, or None.
/// Note that we can pass any type which implements the DictKey
/// trait. Notable examples are String and PyObjectRef.
pub fn get_item_option<T: IntoPyObject + DictKey + Copy>(
pub fn get_item_option<T: IntoPyObject + DictKey>(
&self,
key: T,
vm: &VirtualMachine,
@@ -471,17 +471,15 @@ impl PyDictRef {
}
}
impl ItemProtocol for PyDictRef {
fn get_item<T: IntoPyObject + DictKey + Copy>(&self, key: T, vm: &VirtualMachine) -> PyResult {
impl<T> ItemProtocol<T> for PyDictRef
where
T: DictKey,
{
fn get_item(&self, key: T, vm: &VirtualMachine) -> PyResult {
self.as_object().get_item(key, vm)
}
fn set_item<T: IntoPyObject + DictKey + Copy>(
&self,
key: T,
value: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult {
fn set_item(&self, key: T, value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
if self.lease_class().is(&vm.ctx.dict_type()) {
self.inner_setitem_fast(key, value, vm)
.map(|_| vm.ctx.none())
@@ -491,7 +489,7 @@ impl ItemProtocol for PyDictRef {
}
}
fn del_item<T: IntoPyObject + DictKey + Copy>(&self, key: T, vm: &VirtualMachine) -> PyResult {
fn del_item(&self, key: T, vm: &VirtualMachine) -> PyResult {
self.as_object().del_item(key, vm)
}
}

View File

@@ -91,7 +91,7 @@ impl PyFunction {
for i in 0..n {
let arg_name = &code_object.arg_names[i];
let arg = &func_args.args[i];
locals.set_item(arg_name, arg.clone(), vm)?;
locals.set_item(arg_name.as_str(), arg.clone(), vm)?;
}
// Pack other positional arguments in to *args:
@@ -103,7 +103,7 @@ impl PyFunction {
}
let vararg_value = vm.ctx.new_tuple(last_args);
locals.set_item(vararg_name, vararg_value, vm)?;
locals.set_item(vararg_name.as_str(), vararg_value, vm)?;
} else {
// Check the number of positional arguments
if nargs > nexpected_args {
@@ -121,7 +121,7 @@ impl PyFunction {
{
let d = vm.ctx.new_dict();
if let Some(ref kwargs_name) = code_object.varkeywords_name {
locals.set_item(kwargs_name, d.as_object().clone(), vm)?;
locals.set_item(kwargs_name.as_str(), d.as_object().clone(), vm)?;
}
Some(d)
} else {
@@ -143,9 +143,9 @@ impl PyFunction {
);
}
locals.set_item(&name, value, vm)?;
locals.set_item(name.as_str(), value, vm)?;
} else if let Some(d) = &kwargs {
d.set_item(&name, value, vm)?;
d.set_item(name.as_str(), value, vm)?;
} else {
return Err(
vm.new_type_error(format!("Got an unexpected keyword argument '{}'", name))
@@ -189,7 +189,7 @@ impl PyFunction {
for (default_index, i) in (required_args..nexpected_args).enumerate() {
let arg_name = &code_object.arg_names[i];
if !locals.contains_key(arg_name, vm) {
locals.set_item(arg_name, defaults[default_index].clone(), vm)?;
locals.set_item(arg_name.as_str(), defaults[default_index].clone(), vm)?;
}
}
}
@@ -199,8 +199,10 @@ impl PyFunction {
for arg_name in &code_object.kwonlyarg_names {
if !locals.contains_key(arg_name, vm) {
if let Some(kw_only_defaults) = &self.kw_only_defaults {
if let Some(default) = kw_only_defaults.get_item_option(arg_name, vm)? {
locals.set_item(arg_name, default, vm)?;
if let Some(default) =
kw_only_defaults.get_item_option(arg_name.as_str(), vm)?
{
locals.set_item(arg_name.as_str(), default, vm)?;
continue;
}
}

View File

@@ -73,7 +73,7 @@ impl PySetInner {
fn new(iterable: PyIterable, vm: &VirtualMachine) -> PyResult<PySetInner> {
let set = PySetInner::default();
for item in iterable.iter(vm)? {
set.add(&item?, vm)?;
set.add(item?, vm)?;
}
Ok(set)
}
@@ -177,7 +177,7 @@ impl PySetInner {
fn union(&self, other: PyIterable, vm: &VirtualMachine) -> PyResult<PySetInner> {
let set = self.clone();
for item in other.iter(vm)? {
set.add(&item?, vm)?;
set.add(item?, vm)?;
}
Ok(set)
@@ -188,7 +188,7 @@ impl PySetInner {
for item in other.iter(vm)? {
let obj = item?;
if self.contains(&obj, vm)? {
set.add(&obj, vm)?;
set.add(obj, vm)?;
}
}
Ok(set)
@@ -256,16 +256,16 @@ impl PySetInner {
Ok(format!("{{{}}}", str_parts.join(", ")))
}
fn add(&self, item: &PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
fn add(&self, item: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
self.content.insert(vm, item, ())
}
fn remove(&self, item: &PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
self.content.delete(vm, item)
fn remove(&self, item: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
self.content.delete(vm, &item)
}
fn discard(&self, item: &PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
self.content.delete_if_exists(vm, item)
self.content.delete_if_exists(vm, &item)
}
fn clear(&self) {
@@ -284,7 +284,7 @@ impl PySetInner {
fn update(&self, others: Args<PyIterable>, vm: &VirtualMachine) -> PyResult<()> {
for iterable in others {
for item in iterable.iter(vm)? {
self.add(&item?, vm)?;
self.add(item?, vm)?;
}
}
Ok(())
@@ -297,7 +297,7 @@ impl PySetInner {
for item in iterable.iter(vm)? {
let obj = item?;
if temp_inner.contains(&obj, vm)? {
self.add(&obj, vm)?;
self.add(obj, vm)?;
}
}
temp_inner = self.copy()
@@ -518,13 +518,13 @@ impl PySet {
#[pymethod]
pub fn add(&self, item: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
self.inner.add(&item, vm)?;
self.inner.add(item, vm)?;
Ok(())
}
#[pymethod]
fn remove(&self, item: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
self.inner.remove(&item, vm)
self.inner.remove(item, vm)
}
#[pymethod]
@@ -620,7 +620,7 @@ impl PyFrozenSet {
) -> PyResult<Self> {
let inner = PySetInner::default();
for elem in it {
inner.add(&elem, vm)?;
inner.add(elem, vm)?;
}
Ok(Self { inner })
}

View File

@@ -993,11 +993,11 @@ impl PyString {
Ok(from_str) => {
if to_str.len() == from_str.len() {
for (c1, c2) in from_str.value.chars().zip(to_str.value.chars()) {
new_dict.set_item(&vm.new_int(c1 as u32), vm.new_int(c2 as u32), vm)?;
new_dict.set_item(vm.new_int(c1 as u32), vm.new_int(c2 as u32), vm)?;
}
if let OptionalArg::Present(none_str) = none_str {
for c in none_str.value.chars() {
new_dict.set_item(&vm.new_int(c as u32), vm.get_none(), vm)?;
new_dict.set_item(vm.new_int(c as u32), vm.get_none(), vm)?;
}
}
new_dict.into_pyobject(vm)
@@ -1019,14 +1019,14 @@ impl PyString {
for (key, val) in dict {
if let Some(num) = key.payload::<PyInt>() {
new_dict.set_item(
&num.as_bigint().to_i32().into_pyobject(vm)?,
num.as_bigint().to_i32().into_pyobject(vm)?,
val,
vm,
)?;
} else if let Some(string) = key.payload::<PyString>() {
if string.len() == 1 {
let num_value = string.value.chars().next().unwrap() as u32;
new_dict.set_item(&num_value.into_pyobject(vm)?, val, vm)?;
new_dict.set_item(num_value.into_pyobject(vm)?, val, vm)?;
} else {
return Err(vm.new_value_error(
"string keys in translate table must be of length 1".to_owned(),

View File

@@ -114,7 +114,11 @@ impl PySuper {
} else {
let frame = vm.current_frame().expect("no current frame for super()");
if let Some(first_arg) = frame.code.arg_names.get(0) {
match frame.scope.get_locals().get_item_option(first_arg, vm)? {
match frame
.scope
.get_locals()
.get_item_option(first_arg.as_str(), vm)?
{
Some(obj) => obj,
_ => {
return Err(vm.new_type_error(format!(

View File

@@ -209,7 +209,7 @@ impl<'de> Visitor<'de> for PyObjectDeserializer<'de> {
// Although JSON keys must be strings, implementation accepts any keys
// and can be reused by other deserializers without such limit
while let Some((key_obj, value)) = access.next_entry_seed(self.clone(), self.clone())? {
dict.set_item(&key_obj, value, self.vm).unwrap();
dict.set_item(key_obj, value, self.vm).unwrap();
}
Ok(dict.into_object())
}

View File

@@ -10,7 +10,6 @@ use num_complex::Complex64;
use num_traits::{One, ToPrimitive, Zero};
use crate::bytecode;
use crate::dictdatatype::DictKey;
use crate::exceptions::{self, PyBaseExceptionRef};
use crate::function::{IntoPyNativeFunc, PyFuncArgs};
use crate::obj::objbuiltinfunc::{PyBuiltinFunction, PyBuiltinMethod};
@@ -952,32 +951,28 @@ impl<T: TypeProtocol> TypeProtocol for &'_ T {
/// The python item protocol. Mostly applies to dictionaries.
/// Allows getting, setting and deletion of keys-value pairs.
pub trait ItemProtocol {
fn get_item<T: IntoPyObject + DictKey + Copy>(&self, key: T, vm: &VirtualMachine) -> PyResult;
fn set_item<T: IntoPyObject + DictKey + Copy>(
&self,
key: T,
value: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult;
fn del_item<T: IntoPyObject + DictKey + Copy>(&self, key: T, vm: &VirtualMachine) -> PyResult;
pub trait ItemProtocol<T>
where
T: IntoPyObject + ?Sized,
{
fn get_item(&self, key: T, vm: &VirtualMachine) -> PyResult;
fn set_item(&self, key: T, value: PyObjectRef, vm: &VirtualMachine) -> PyResult;
fn del_item(&self, key: T, vm: &VirtualMachine) -> PyResult;
}
impl ItemProtocol for PyObjectRef {
fn get_item<T: IntoPyObject>(&self, key: T, vm: &VirtualMachine) -> PyResult {
impl<T> ItemProtocol<T> for PyObjectRef
where
T: IntoPyObject,
{
fn get_item(&self, key: T, vm: &VirtualMachine) -> PyResult {
vm.call_method(self, "__getitem__", key.into_pyobject(vm)?)
}
fn set_item<T: IntoPyObject>(
&self,
key: T,
value: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult {
fn set_item(&self, key: T, value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
vm.call_method(self, "__setitem__", vec![key.into_pyobject(vm)?, value])
}
fn del_item<T: IntoPyObject>(&self, key: T, vm: &VirtualMachine) -> PyResult {
fn del_item(&self, key: T, vm: &VirtualMachine) -> PyResult {
vm.call_method(self, "__delitem__", key.into_pyobject(vm)?)
}
}

View File

@@ -33,7 +33,7 @@ fn dis_compiler_flag_names(vm: &VirtualMachine) -> PyObjectRef {
let dict = vm.ctx.new_dict();
for (name, flag) in CodeFlags::NAME_MAPPING {
dict.set_item(
&vm.ctx.new_int(flag.bits()),
vm.ctx.new_int(flag.bits()),
vm.ctx.new_str((*name).to_owned()),
vm,
)

View File

@@ -9,7 +9,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
for (name, code) in ERROR_CODES {
let name = vm.new_str((*name).to_owned());
let code = vm.ctx.new_int(*code);
errorcode.set_item(&code, name.clone(), vm).unwrap();
errorcode.set_item(code.clone(), name.clone(), vm).unwrap();
vm.set_attr(&module, name, code).unwrap();
}
module

View File

@@ -1131,7 +1131,7 @@ mod posix {
for (key, value) in env::vars_os() {
environ
.set_item(
&vm.ctx.new_bytes(key.into_vec()),
vm.ctx.new_bytes(key.into_vec()),
vm.ctx.new_bytes(value.into_vec()),
vm,
)
@@ -2254,7 +2254,7 @@ mod nt {
for (key, value) in env::vars() {
environ
.set_item(&vm.new_str(key), vm.new_str(value), vm)
.set_item(vm.new_str(key), vm.new_str(value), vm)
.unwrap();
}
environ

View File

@@ -330,7 +330,7 @@ impl PyLocal {
zelf.as_object()
)))
} else {
zelf.ldict(vm).set_item(attr.as_object(), value, vm)?;
zelf.ldict(vm).set_item(attr.into_object(), value, vm)?;
Ok(())
}
}
@@ -343,7 +343,7 @@ impl PyLocal {
zelf.as_object()
)))
} else {
zelf.ldict(vm).del_item(attr.as_object(), vm)?;
zelf.ldict(vm).del_item(attr.into_object(), vm)?;
Ok(())
}
}

View File

@@ -213,8 +213,12 @@ pub fn js_to_py(vm: &VirtualMachine, js_val: JsValue) -> PyObjectRef {
for pair in object_entries(&Object::from(js_val)) {
let (key, val) = pair.expect("iteration over object to not fail");
let py_val = js_to_py(vm, val);
dict.set_item(&String::from(js_sys::JsString::from(key)), py_val, vm)
.unwrap();
dict.set_item(
String::from(js_sys::JsString::from(key)).as_str(),
py_val,
vm,
)
.unwrap();
}
dict.into_object()
}

View File

@@ -267,7 +267,7 @@ impl WASMVirtualMachine {
let (key, value) = entry?;
let key: String = Object::from(key).to_string().into();
attrs
.set_item(&key, convert::js_to_py(vm, value), vm)
.set_item(key.as_str(), convert::js_to_py(vm, value), vm)
.to_js(vm)?;
}
}
@@ -280,7 +280,7 @@ impl WASMVirtualMachine {
let sys_modules = vm
.get_attribute(vm.sys_module.clone(), "modules")
.to_js(vm)?;
sys_modules.set_item(&name, module, vm).to_js(vm)?;
sys_modules.set_item(name, module, vm).to_js(vm)?;
Ok(())
})?
@@ -301,7 +301,7 @@ impl WASMVirtualMachine {
let sys_modules = vm
.get_attribute(vm.sys_module.clone(), "modules")
.to_js(vm)?;
sys_modules.set_item(&name, py_module, vm).to_js(vm)?;
sys_modules.set_item(name, py_module, vm).to_js(vm)?;
Ok(())
})?