setattro uses Py<PyStr>

This commit is contained in:
Jeong YunWon
2023-03-19 09:16:56 +09:00
parent ab1de2942c
commit dfb37d9a44
17 changed files with 87 additions and 72 deletions

View File

@@ -1650,8 +1650,6 @@ class GeneralModuleTests(unittest.TestCase):
f = None
support.gc_collect()
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_name_closed_socketio(self):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
fp = sock.makefile("rb")

View File

@@ -458,6 +458,7 @@ impl ModuleItem for ClassItem {
let set_attr = match py_names.len() {
0 => quote! {
let _ = new_class; // suppress warning
let _ = vm.ctx.intern_str(#class_name);
},
1 => {
let py_name = &py_names[0];

View File

@@ -766,7 +766,7 @@ mod _sqlite {
pub(super) fn setup_module(module: &PyObject, vm: &VirtualMachine) {
for (name, code) in ERROR_CODES {
let name = vm.ctx.new_str(*name);
let name = vm.ctx.intern_str(*name);
let code = vm.new_pyobj(*code);
module.set_attr(name, code, vm).unwrap();
}

View File

@@ -1,4 +1,3 @@
use super::pystr::IntoPyStrRef;
use super::{PyDictRef, PyStr, PyStrRef, PyType, PyTypeRef};
use crate::{
builtins::{pystr::AsPyStr, PyStrInterned},
@@ -84,9 +83,9 @@ impl Py<PyModule> {
self.getattr_inner(attr_name.as_pystr(&vm.ctx), vm)
}
pub fn set_attr(
pub fn set_attr<'a>(
&self,
attr_name: impl IntoPyStrRef,
attr_name: impl AsPyStr<'a>,
attr_value: impl Into<PyObjectRef>,
vm: &VirtualMachine,
) -> PyResult<()> {

View File

@@ -53,7 +53,8 @@ impl Initializer for PyNamespace {
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)?;
let name = vm.ctx.new_str(name);
zelf.as_object().set_attr(&name, value, vm)?;
}
Ok(())
}

View File

@@ -161,19 +161,19 @@ impl PyBaseObject {
value: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<()> {
obj.generic_setattr(name, PySetterValue::Assign(value), vm)
obj.generic_setattr(&name, PySetterValue::Assign(value), vm)
}
/// Implement delattr(self, name).
#[pymethod]
fn __delattr__(obj: PyObjectRef, name: PyStrRef, vm: &VirtualMachine) -> PyResult<()> {
obj.generic_setattr(name, PySetterValue::Delete, vm)
obj.generic_setattr(&name, PySetterValue::Delete, vm)
}
#[pyslot]
fn slot_setattro(
obj: &PyObject,
attr_name: PyStrRef,
attr_name: &Py<PyStr>,
value: PySetterValue,
vm: &VirtualMachine,
) -> PyResult<()> {

View File

@@ -374,23 +374,30 @@ impl PyType {
call_slot_new(zelf, subtype, args, vm)
}
pub fn slot_name(&self) -> BorrowedValue<str> {
fn name_inner<'a, R: 'a>(
&'a self,
static_f: impl FnOnce(&'static str) -> R,
heap_f: impl FnOnce(&'a HeapTypeExt) -> R,
) -> R {
if !self.slots.flags.has_feature(PyTypeFlags::HEAPTYPE) {
return self.slots.name.load().into();
static_f(self.slots.name.load())
} else {
heap_f(self.heaptype_ext.as_ref().unwrap())
}
let name_lock = self.heaptype_ext.as_ref().unwrap().name.read();
PyRwLockReadGuard::map(name_lock, |_| self.slots.name.load()).into()
}
pub fn slot_name(&self) -> BorrowedValue<str> {
self.name_inner(
|name| name.into(),
|ext| PyRwLockReadGuard::map(ext.name.read(), |name| name.as_str()).into(),
)
}
pub fn name(&self) -> BorrowedValue<str> {
if !self.slots.flags.has_feature(PyTypeFlags::HEAPTYPE) {
return self.slots.name.load().into();
}
let name_lock = self.heaptype_ext.as_ref().unwrap().name.read();
PyRwLockReadGuard::map(name_lock, |name| {
name.as_str() // = self.slots.name.load().rsplit_once('.').unwrap().1
})
.into()
self.name_inner(
|name| name.rsplit_once('.').map_or(name, |(_, name)| name).into(),
|ext| PyRwLockReadGuard::map(ext.name.read(), |name| name.as_str()).into(),
)
}
}
@@ -438,19 +445,20 @@ impl PyType {
#[pygetset]
pub fn __name__(&self, vm: &VirtualMachine) -> PyStrRef {
if !self.slots.flags.has_feature(PyTypeFlags::HEAPTYPE) {
vm.ctx
.interned_str(self.slots.name.load())
.unwrap_or_else(|| {
panic!(
"static type name must be already interned but {} is not",
self.slots.name.load()
)
})
.to_owned()
} else {
self.heaptype_ext.as_ref().unwrap().name.read().clone()
}
self.name_inner(
|name| {
vm.ctx
.interned_str(name.rsplit_once('.').map_or(name, |(_, name)| name))
.unwrap_or_else(|| {
panic!(
"static type name must be already interned but {} is not",
self.slots.name.load()
)
})
.to_owned()
},
|ext| ext.name.read().clone(),
)
}
#[pygetset(magic)]
@@ -1037,7 +1045,7 @@ impl GetAttr for PyType {
impl SetAttr for PyType {
fn setattro(
zelf: &Py<Self>,
attr_name: PyStrRef,
attr_name: &Py<PyStr>,
value: PySetterValue,
vm: &VirtualMachine,
) -> PyResult<()> {

View File

@@ -141,7 +141,7 @@ impl GetAttr for PyWeakProxy {
impl SetAttr for PyWeakProxy {
fn setattro(
zelf: &Py<Self>,
attr_name: PyStrRef,
attr_name: &Py<PyStr>,
value: PySetterValue,
vm: &VirtualMachine,
) -> PyResult<()> {

View File

@@ -3,8 +3,8 @@
use crate::{
builtins::{
pystr::{AsPyStr, IntoPyStrRef},
PyBytes, PyDict, PyDictRef, PyGenericAlias, PyInt, PyStr, PyStrRef, PyTupleRef, PyTypeRef,
pystr::AsPyStr, PyBytes, PyDict, PyDictRef, PyGenericAlias, PyInt, PyStr, PyStrRef,
PyTupleRef, PyTypeRef,
},
bytesinner::ByteInnerNewOptions,
common::{hash::PyHash, str::to_ascii},
@@ -102,7 +102,7 @@ impl PyObject {
pub fn call_set_attr(
&self,
vm: &VirtualMachine,
attr_name: PyStrRef,
attr_name: &Py<PyStr>,
attr_value: PySetterValue,
) -> PyResult<()> {
let setattro = {
@@ -126,13 +126,13 @@ impl PyObject {
setattro(self, attr_name, attr_value, vm)
}
pub fn set_attr(
pub fn set_attr<'a>(
&self,
attr_name: impl IntoPyStrRef,
attr_name: impl AsPyStr<'a>,
attr_value: impl Into<PyObjectRef>,
vm: &VirtualMachine,
) -> PyResult<()> {
let attr_name = attr_name.into_pystr_ref(vm);
let attr_name = attr_name.as_pystr(&vm.ctx);
self.call_set_attr(vm, attr_name, PySetterValue::Assign(attr_value.into()))
}
@@ -140,14 +140,14 @@ impl PyObject {
#[cfg_attr(feature = "flame-it", flame)]
pub fn generic_setattr(
&self,
attr_name: PyStrRef, // TODO: Py<PyStr>
attr_name: &Py<PyStr>,
value: PySetterValue,
vm: &VirtualMachine,
) -> PyResult<()> {
vm_trace!("object.__setattr__({:?}, {}, {:?})", self, attr_name, value);
if let Some(attr) = vm
.ctx
.interned_str(&*attr_name)
.interned_str(attr_name)
.and_then(|attr_name| self.get_class_attr(attr_name))
{
let descr_set = attr.class().mro_find_map(|cls| cls.slots.descr_set.load());
@@ -158,9 +158,9 @@ impl PyObject {
if let Some(dict) = self.dict() {
if let PySetterValue::Assign(value) = value {
dict.set_item(&*attr_name, value, vm)?;
dict.set_item(attr_name, value, vm)?;
} else {
dict.del_item(&*attr_name, vm).map_err(|e| {
dict.del_item(attr_name, vm).map_err(|e| {
if e.fast_isinstance(vm.ctx.exceptions.key_error) {
vm.new_attribute_error(format!(
"'{}' object has no attribute '{}'",
@@ -243,8 +243,8 @@ impl PyObject {
}
}
pub fn del_attr(&self, attr_name: impl IntoPyStrRef, vm: &VirtualMachine) -> PyResult<()> {
let attr_name = attr_name.into_pystr_ref(vm);
pub fn del_attr<'a>(&self, attr_name: impl AsPyStr<'a>, vm: &VirtualMachine) -> PyResult<()> {
let attr_name = attr_name.as_pystr(&vm.ctx);
self.call_set_attr(vm, attr_name, PySetterValue::Delete)
}

View File

@@ -50,7 +50,7 @@ mod _ast {
)));
}
for (name, arg) in fields.iter().zip(args.args) {
zelf.set_attr(name.clone(), arg, vm)?;
zelf.set_attr(name, arg, vm)?;
}
for (key, value) in args.kwargs {
if let Some(pos) = fields.iter().position(|f| f.as_str() == key) {
@@ -62,7 +62,7 @@ mod _ast {
)));
}
}
zelf.set_attr(key, value, vm)?;
zelf.set_attr(vm.ctx.intern_str(key), value, vm)?;
}
Ok(())
}

View File

@@ -187,7 +187,7 @@ mod builtins {
#[pyfunction]
fn delattr(obj: PyObjectRef, attr: PyStrRef, vm: &VirtualMachine) -> PyResult<()> {
obj.del_attr(attr, vm)
obj.del_attr(&attr, vm)
}
#[pyfunction]
@@ -744,7 +744,7 @@ mod builtins {
value: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<()> {
obj.set_attr(attr, value, vm)?;
obj.set_attr(&attr, value, vm)?;
Ok(())
}

View File

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

View File

@@ -5,7 +5,7 @@ pub(crate) use _thread::{make_module, RawRMutex};
#[pymodule]
pub(crate) mod _thread {
use crate::{
builtins::{PyDictRef, PyStr, PyStrRef, PyTupleRef, PyTypeRef},
builtins::{PyDictRef, PyStr, PyTupleRef, PyTypeRef},
convert::ToPyException,
function::{ArgCallable, Either, FuncArgs, KwArgs, OptionalArg, PySetterValue},
types::{Constructor, GetAttr, SetAttr},
@@ -381,7 +381,7 @@ pub(crate) mod _thread {
impl SetAttr for Local {
fn setattro(
zelf: &Py<Self>,
attr: PyStrRef,
attr: &Py<PyStr>,
value: PySetterValue,
vm: &VirtualMachine,
) -> PyResult<()> {
@@ -393,9 +393,9 @@ pub(crate) mod _thread {
} else {
let dict = zelf.ldict(vm);
if let PySetterValue::Assign(value) = value {
dict.set_item(&*attr, value, vm)?;
dict.set_item(attr, value, vm)?;
} else {
dict.del_item(&*attr, vm)?;
dict.del_item(attr, vm)?;
}
Ok(())
}

View File

@@ -283,7 +283,7 @@ pub(crate) type HashFunc = fn(&PyObject, &VirtualMachine) -> PyResult<PyHash>;
pub(crate) type StringifyFunc = fn(&PyObject, &VirtualMachine) -> PyResult<PyStrRef>;
pub(crate) type GetattroFunc = fn(&PyObject, &Py<PyStr>, &VirtualMachine) -> PyResult;
pub(crate) type SetattroFunc =
fn(&PyObject, PyStrRef, PySetterValue, &VirtualMachine) -> PyResult<()>;
fn(&PyObject, &Py<PyStr>, PySetterValue, &VirtualMachine) -> PyResult<()>;
pub(crate) type AsBufferFunc = fn(&PyObject, &VirtualMachine) -> PyResult<PyBuffer>;
pub(crate) type RichCompareFunc = fn(
&PyObject,
@@ -418,11 +418,12 @@ fn getattro_wrapper(zelf: &PyObject, name: &Py<PyStr>, vm: &VirtualMachine) -> P
fn setattro_wrapper(
zelf: &PyObject,
name: PyStrRef,
name: &Py<PyStr>,
value: PySetterValue,
vm: &VirtualMachine,
) -> PyResult<()> {
let zelf = zelf.to_owned();
let name = name.to_owned();
match value {
PySetterValue::Assign(value) => {
vm.call_special_method(zelf, identifier!(vm, __setattr__), (name, value))?;
@@ -1241,7 +1242,7 @@ pub trait SetAttr: PyPayload {
#[inline]
fn slot_setattro(
obj: &PyObject,
name: PyStrRef,
name: &Py<PyStr>,
value: PySetterValue,
vm: &VirtualMachine,
) -> PyResult<()> {
@@ -1253,7 +1254,7 @@ pub trait SetAttr: PyPayload {
fn setattro(
zelf: &Py<Self>,
name: PyStrRef,
name: &Py<PyStr>,
value: PySetterValue,
vm: &VirtualMachine,
) -> PyResult<()>;
@@ -1266,13 +1267,13 @@ pub trait SetAttr: PyPayload {
value: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<()> {
Self::setattro(&zelf, name, PySetterValue::Assign(value), vm)
Self::setattro(&zelf, &name, PySetterValue::Assign(value), vm)
}
#[inline]
#[pymethod(magic)]
fn delattr(zelf: PyRef<Self>, name: PyStrRef, vm: &VirtualMachine) -> PyResult<()> {
Self::setattro(&zelf, name, PySetterValue::Delete, vm)
Self::setattro(&zelf, &name, PySetterValue::Delete, vm)
}
}

View File

@@ -389,8 +389,12 @@ impl Context {
pystr::PyStr::new_ref(s, self)
}
pub fn interned_or_new_str(&self, s: &str) -> PyRef<PyStr> {
match self.interned_str(s) {
pub fn interned_or_new_str<S, M>(&self, s: S) -> PyRef<PyStr>
where
S: Into<PyStr> + AsRef<M>,
M: MaybeInternedString,
{
match self.interned_str(s.as_ref()) {
Some(s) => s.to_owned(),
None => self.new_str(s),
}

View File

@@ -17,7 +17,7 @@ mod vm_ops;
use crate::{
builtins::{
code::PyCode,
pystr::{AsPyStr, IntoPyStrRef},
pystr::AsPyStr,
tuple::{PyTuple, PyTupleTyped},
PyBaseExceptionRef, PyDictRef, PyInt, PyList, PyModule, PyStr, PyStrInterned, PyStrRef,
PyTypeRef,
@@ -270,8 +270,9 @@ impl VirtualMachine {
Default::default(),
self,
)?;
let dunder_name = self.ctx.intern_str(format!("__{name}__"));
self.sys_module.set_attr(
format!("__{name}__"), // e.g. __stdin__
dunder_name, // e.g. __stdin__
stdio.clone(),
self,
)?;
@@ -795,12 +796,12 @@ impl VirtualMachine {
pub fn __module_set_attr(
&self,
module: &PyObject,
attr_name: impl IntoPyStrRef,
attr_name: &str,
attr_value: impl Into<PyObjectRef>,
) -> PyResult<()> {
let val = attr_value.into();
module.generic_setattr(
attr_name.into_pystr_ref(self),
self.ctx.intern_str(attr_name),
PySetterValue::Assign(val),
self,
)

View File

@@ -314,7 +314,7 @@ impl WASMVirtualMachine {
let (key, value) = entry?;
let key = Object::from(key).to_string();
extend_module!(vm, py_module, {
&vm.ctx.new_str(String::from(key)) => convert::js_to_py(vm, value),
&String::from(key) => convert::js_to_py(vm, value),
});
}