forked from Rust-related/RustPython
Merge pull request #4721 from youknowone/opt-getattr
type.__name__ & getattr optimization
This commit is contained in:
2
Lib/test/test_socket.py
vendored
2
Lib/test/test_socket.py
vendored
@@ -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")
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -78,7 +78,8 @@ impl<'vm> ShellHelper<'vm> {
|
||||
let mut current = self.globals.get_item_opt(first.as_str(), self.vm).ok()??;
|
||||
|
||||
for attr in parents {
|
||||
current = current.get_attr(attr.as_str(), self.vm).ok()?;
|
||||
let attr = self.vm.ctx.new_str(attr.as_str());
|
||||
current = current.get_attr(&attr, self.vm).ok()?;
|
||||
}
|
||||
|
||||
let current_iter = str_iter_method(current, identifier!(self.vm, __dir__)).ok()?;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ mod _ssl {
|
||||
/// SSL/TLS connection terminated abruptly.
|
||||
#[pyattr(name = "SSLEOFError", once)]
|
||||
fn ssl_eof_error(vm: &VirtualMachine) -> PyTypeRef {
|
||||
PyType::new_simple_ref("ssl.SSLEOFError", &ssl_error(vm), &vm.ctx).unwrap()
|
||||
PyType::new_simple_heap("ssl.SSLEOFError", &ssl_error(vm), &vm.ctx).unwrap()
|
||||
}
|
||||
|
||||
type OpensslVersionInfo = (u8, u8, u8, u8, u8);
|
||||
|
||||
@@ -259,7 +259,7 @@ impl PyBuiltinMethod {
|
||||
vm: &VirtualMachine,
|
||||
) -> (Option<PyObjectRef>, (Option<PyObjectRef>, PyStrRef)) {
|
||||
let builtins_getattr = vm.builtins.get_attr("getattr", vm).ok();
|
||||
let classname = vm.builtins.get_attr(self.class.name().to_string(), vm).ok();
|
||||
let classname = vm.builtins.get_attr(&self.class.__name__(vm), vm).ok();
|
||||
(builtins_getattr, (classname, self.value.name.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -501,10 +501,10 @@ impl Comparable for PyBoundMethod {
|
||||
}
|
||||
|
||||
impl GetAttr for PyBoundMethod {
|
||||
fn getattro(zelf: &Py<Self>, name: PyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn getattro(zelf: &Py<Self>, name: &Py<PyStr>, vm: &VirtualMachine) -> PyResult {
|
||||
let class_attr = vm
|
||||
.ctx
|
||||
.interned_str(&*name)
|
||||
.interned_str(name)
|
||||
.and_then(|attr_name| zelf.get_class_attr(attr_name));
|
||||
if let Some(obj) = class_attr {
|
||||
return vm.call_if_get_descriptor(obj, zelf.to_owned().into());
|
||||
|
||||
@@ -3,7 +3,7 @@ use once_cell::sync::Lazy;
|
||||
use super::type_;
|
||||
use crate::{
|
||||
atomic_func,
|
||||
builtins::{PyList, PyStr, PyStrRef, PyTuple, PyTupleRef, PyType, PyTypeRef},
|
||||
builtins::{PyList, PyStr, PyTuple, PyTupleRef, PyType, PyTypeRef},
|
||||
class::PyClassImpl,
|
||||
common::hash,
|
||||
convert::ToPyObject,
|
||||
@@ -214,9 +214,9 @@ impl PyGenericAlias {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_typevar(obj: &PyObjectRef, vm: &VirtualMachine) -> bool {
|
||||
pub(crate) fn is_typevar(obj: &PyObjectRef, vm: &VirtualMachine) -> bool {
|
||||
let class = obj.class();
|
||||
class.slot_name() == "TypeVar"
|
||||
"TypeVar" == &*class.slot_name()
|
||||
&& class
|
||||
.get_attr(identifier!(vm, __module__))
|
||||
.and_then(|o| o.downcast_ref::<PyStr>().map(|s| s.as_str() == "typing"))
|
||||
@@ -390,7 +390,7 @@ impl Hashable for PyGenericAlias {
|
||||
}
|
||||
|
||||
impl GetAttr for PyGenericAlias {
|
||||
fn getattro(zelf: &Py<Self>, attr: PyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn getattro(zelf: &Py<Self>, attr: &Py<PyStr>, vm: &VirtualMachine) -> PyResult {
|
||||
for exc in ATTR_EXCEPTIONS.iter() {
|
||||
if *(*exc) == attr.to_string() {
|
||||
return zelf.as_object().generic_getattr(attr, vm);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use super::pystr::IntoPyStrRef;
|
||||
use super::{PyDictRef, PyStr, PyStrRef, PyType, PyTypeRef};
|
||||
use crate::{
|
||||
builtins::PyStrInterned,
|
||||
builtins::{pystr::AsPyStr, PyStrInterned},
|
||||
class::PyClassImpl,
|
||||
convert::ToPyObject,
|
||||
function::FuncArgs,
|
||||
@@ -26,33 +25,21 @@ pub struct ModuleInitArgs {
|
||||
doc: Option<PyStrRef>,
|
||||
}
|
||||
|
||||
#[pyclass(with(GetAttr, Initializer, Representable), flags(BASETYPE, HAS_DICT))]
|
||||
impl PyModule {
|
||||
// pub(crate) fn new(d: PyDictRef) -> Self {
|
||||
// PyModule { dict: d.into() }
|
||||
// }
|
||||
}
|
||||
|
||||
// #[inline]
|
||||
// pub fn dict(&self) -> PyDictRef {
|
||||
// self.dict.get()
|
||||
// }
|
||||
|
||||
#[pyslot]
|
||||
fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
PyModule {}.into_ref_with_type(vm, cls).map(Into::into)
|
||||
}
|
||||
|
||||
fn getattr_inner(zelf: &Py<Self>, name: PyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
if let Some(attr) = zelf
|
||||
.as_object()
|
||||
.generic_getattr_opt(name.clone(), None, vm)?
|
||||
{
|
||||
impl Py<PyModule> {
|
||||
fn getattr_inner(&self, name: &Py<PyStr>, vm: &VirtualMachine) -> PyResult {
|
||||
if let Some(attr) = self.as_object().generic_getattr_opt(name, None, vm)? {
|
||||
return Ok(attr);
|
||||
}
|
||||
if let Ok(getattr) = zelf.dict().get_item(identifier!(vm, __getattr__), vm) {
|
||||
return getattr.call((name,), vm);
|
||||
if let Ok(getattr) = self.dict().get_item(identifier!(vm, __getattr__), vm) {
|
||||
return getattr.call((name.to_owned(),), vm);
|
||||
}
|
||||
let module_name = if let Some(name) = Self::name(zelf.to_owned(), vm) {
|
||||
let module_name = if let Some(name) = self.name(vm) {
|
||||
format!(" '{name}'")
|
||||
} else {
|
||||
"".to_owned()
|
||||
@@ -60,26 +47,14 @@ impl PyModule {
|
||||
Err(vm.new_attribute_error(format!("module{module_name} has no attribute '{name}'")))
|
||||
}
|
||||
|
||||
fn name(zelf: PyRef<Self>, vm: &VirtualMachine) -> Option<PyStrRef> {
|
||||
let name = zelf
|
||||
fn name(&self, vm: &VirtualMachine) -> Option<PyStrRef> {
|
||||
let name = self
|
||||
.as_object()
|
||||
.generic_getattr_opt(identifier!(vm, __name__).to_owned(), None, vm)
|
||||
.generic_getattr_opt(identifier!(vm, __name__), None, vm)
|
||||
.unwrap_or_default()?;
|
||||
name.downcast::<PyStr>().ok()
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn dir(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<Vec<PyObjectRef>> {
|
||||
let dict = zelf
|
||||
.as_object()
|
||||
.dict()
|
||||
.ok_or_else(|| vm.new_value_error("module has no dict".to_owned()))?;
|
||||
let attrs = dict.into_iter().map(|(k, _v)| k).collect();
|
||||
Ok(attrs)
|
||||
}
|
||||
}
|
||||
|
||||
impl Py<PyModule> {
|
||||
// TODO: to be replaced by the commented-out dict method above once dictoffsets land
|
||||
pub fn dict(&self) -> PyDictRef {
|
||||
self.as_object().dict().unwrap()
|
||||
@@ -104,12 +79,13 @@ impl Py<PyModule> {
|
||||
.expect("Failed to set __spec__ on module");
|
||||
}
|
||||
|
||||
pub fn get_attr(&self, attr_name: impl IntoPyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
PyModule::getattr_inner(self, attr_name.into_pystr_ref(vm), vm)
|
||||
pub fn get_attr<'a>(&self, attr_name: impl AsPyStr<'a>, vm: &VirtualMachine) -> PyResult {
|
||||
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<()> {
|
||||
@@ -117,6 +93,24 @@ impl Py<PyModule> {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(GetAttr, Initializer, Representable), flags(BASETYPE, HAS_DICT))]
|
||||
impl PyModule {
|
||||
#[pyslot]
|
||||
fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
PyModule {}.into_ref_with_type(vm, cls).map(Into::into)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn dir(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<Vec<PyObjectRef>> {
|
||||
let dict = zelf
|
||||
.as_object()
|
||||
.dict()
|
||||
.ok_or_else(|| vm.new_value_error("module has no dict".to_owned()))?;
|
||||
let attrs = dict.into_iter().map(|(k, _v)| k).collect();
|
||||
Ok(attrs)
|
||||
}
|
||||
}
|
||||
|
||||
impl Initializer for PyModule {
|
||||
type Args = ModuleInitArgs;
|
||||
|
||||
@@ -136,8 +130,8 @@ impl Initializer for PyModule {
|
||||
}
|
||||
|
||||
impl GetAttr for PyModule {
|
||||
fn getattro(zelf: &Py<Self>, name: PyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
Self::getattr_inner(zelf, name, vm)
|
||||
fn getattro(zelf: &Py<Self>, name: &Py<PyStr>, vm: &VirtualMachine) -> PyResult {
|
||||
zelf.getattr_inner(name, vm)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
@@ -82,7 +83,7 @@ impl Representable for PyNamespace {
|
||||
let name = if o.class().is(vm.ctx.types.namespace_type) {
|
||||
"namespace".to_owned()
|
||||
} else {
|
||||
o.class().slot_name()
|
||||
o.class().slot_name().to_owned()
|
||||
};
|
||||
|
||||
let repr = if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
|
||||
|
||||
@@ -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<()> {
|
||||
@@ -296,14 +296,14 @@ impl PyBaseObject {
|
||||
|
||||
/// Return getattr(self, name).
|
||||
#[pyslot]
|
||||
pub(crate) fn getattro(obj: &PyObject, name: PyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
pub(crate) fn getattro(obj: &PyObject, name: &Py<PyStr>, vm: &VirtualMachine) -> PyResult {
|
||||
vm_trace!("object.__getattribute__({:?}, {:?})", obj, name);
|
||||
obj.as_object().generic_getattr(name, vm)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn getattribute(obj: PyObjectRef, name: PyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
Self::getattro(&obj, name, vm)
|
||||
Self::getattro(&obj, &name, vm)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
|
||||
@@ -143,49 +143,39 @@ impl fmt::Display for PyStr {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait IntoPyStrRef {
|
||||
fn into_pystr_ref(self, vm: &VirtualMachine) -> PyStrRef;
|
||||
pub trait AsPyStr<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
{
|
||||
#[allow(clippy::wrong_self_convention)] // to implement on refs
|
||||
fn as_pystr(self, ctx: &Context) -> &'a Py<PyStr>;
|
||||
}
|
||||
|
||||
impl IntoPyStrRef for PyStrRef {
|
||||
impl<'a> AsPyStr<'a> for &'a Py<PyStr> {
|
||||
#[inline]
|
||||
fn into_pystr_ref(self, _vm: &VirtualMachine) -> PyRef<PyStr> {
|
||||
fn as_pystr(self, _ctx: &Context) -> &'a Py<PyStr> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoPyStrRef for PyStr {
|
||||
impl<'a> AsPyStr<'a> for &'a PyStrRef {
|
||||
#[inline]
|
||||
fn into_pystr_ref(self, vm: &VirtualMachine) -> PyRef<PyStr> {
|
||||
self.into_ref(vm)
|
||||
fn as_pystr(self, _ctx: &Context) -> &'a Py<PyStr> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoPyStrRef for AsciiString {
|
||||
impl AsPyStr<'static> for &'static str {
|
||||
#[inline]
|
||||
fn into_pystr_ref(self, vm: &VirtualMachine) -> PyRef<PyStr> {
|
||||
PyStr::from(self).into_ref(vm)
|
||||
fn as_pystr(self, ctx: &Context) -> &'static Py<PyStr> {
|
||||
ctx.intern_str(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoPyStrRef for String {
|
||||
impl<'a> AsPyStr<'a> for &'a PyStrInterned {
|
||||
#[inline]
|
||||
fn into_pystr_ref(self, vm: &VirtualMachine) -> PyRef<PyStr> {
|
||||
PyStr::from(self).into_ref(vm)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoPyStrRef for &str {
|
||||
#[inline]
|
||||
fn into_pystr_ref(self, vm: &VirtualMachine) -> PyRef<PyStr> {
|
||||
PyStr::from(self).into_ref(vm)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoPyStrRef for &'static PyStrInterned {
|
||||
#[inline]
|
||||
fn into_pystr_ref(self, _vm: &VirtualMachine) -> PyRef<PyStr> {
|
||||
self.to_owned()
|
||||
fn as_pystr(self, _ctx: &Context) -> &'a Py<PyStr> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -619,7 +609,7 @@ impl PyStr {
|
||||
if s == stripped {
|
||||
zelf
|
||||
} else {
|
||||
stripped.into_pystr_ref(vm)
|
||||
vm.ctx.new_str(stripped)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -638,7 +628,7 @@ impl PyStr {
|
||||
if s == stripped {
|
||||
zelf
|
||||
} else {
|
||||
stripped.into_pystr_ref(vm)
|
||||
vm.ctx.new_str(stripped)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -949,7 +939,7 @@ impl PyStr {
|
||||
}
|
||||
Err(iter) => zelf.as_str().py_join(iter)?,
|
||||
};
|
||||
Ok(joined.into_pystr_ref(vm))
|
||||
Ok(vm.ctx.new_str(joined))
|
||||
}
|
||||
|
||||
// FIXME: two traversals of str is expensive
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
See also [CPython source code.](https://github.com/python/cpython/blob/50b48572d9a90c5bb36e2bef6179548ea927a35a/Objects/typeobject.c#L7663)
|
||||
*/
|
||||
|
||||
use super::{PyStrRef, PyType, PyTypeRef};
|
||||
use super::{PyStr, PyType, PyTypeRef};
|
||||
use crate::{
|
||||
class::PyClassImpl,
|
||||
function::{IntoFuncArgs, OptionalArg},
|
||||
@@ -126,7 +126,7 @@ impl PySuper {
|
||||
}
|
||||
|
||||
impl GetAttr for PySuper {
|
||||
fn getattro(zelf: &Py<Self>, name: PyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn getattro(zelf: &Py<Self>, name: &Py<PyStr>, vm: &VirtualMachine) -> PyResult {
|
||||
let skip = |zelf: &Py<Self>, name| zelf.as_object().generic_getattr(name, vm);
|
||||
let (obj, start_type): (PyObjectRef, PyTypeRef) = match zelf.obj.clone() {
|
||||
Some(o) => o,
|
||||
@@ -139,7 +139,7 @@ impl GetAttr for PySuper {
|
||||
return skip(zelf, name);
|
||||
}
|
||||
|
||||
if let Some(name) = vm.ctx.interned_str(&*name) {
|
||||
if let Some(name) = vm.ctx.interned_str(name) {
|
||||
// skip the classes in start_type.mro up to and including zelf.typ
|
||||
let mro: Vec<_> = start_type
|
||||
.iter_mro()
|
||||
|
||||
@@ -22,7 +22,8 @@ use crate::{
|
||||
identifier,
|
||||
protocol::{PyIterReturn, PyMappingMethods, PyNumberMethods, PySequenceMethods},
|
||||
types::{AsNumber, Callable, GetAttr, PyTypeFlags, PyTypeSlots, Representable, SetAttr},
|
||||
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
|
||||
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
|
||||
VirtualMachine,
|
||||
};
|
||||
use indexmap::{map::Entry, IndexMap};
|
||||
use itertools::Itertools;
|
||||
@@ -39,8 +40,8 @@ pub struct PyType {
|
||||
pub heaptype_ext: Option<Pin<Box<HeapTypeExt>>>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct HeapTypeExt {
|
||||
pub name: PyRwLock<PyStrRef>,
|
||||
pub slots: Option<PyTupleTyped<PyStrRef>>,
|
||||
pub number_methods: PyNumberMethods,
|
||||
pub sequence_methods: PySequenceMethods,
|
||||
@@ -119,12 +120,12 @@ impl PyPayload for PyType {
|
||||
}
|
||||
|
||||
impl PyType {
|
||||
pub fn new_simple_ref(
|
||||
pub fn new_simple_heap(
|
||||
name: &str,
|
||||
base: &PyTypeRef,
|
||||
ctx: &Context,
|
||||
) -> Result<PyRef<Self>, String> {
|
||||
Self::new_ref(
|
||||
Self::new_heap(
|
||||
name,
|
||||
vec![base.clone()],
|
||||
Default::default(),
|
||||
@@ -133,7 +134,7 @@ impl PyType {
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
pub fn new_ref(
|
||||
pub fn new_heap(
|
||||
name: &str,
|
||||
bases: Vec<PyRef<Self>>,
|
||||
attrs: PyAttributes,
|
||||
@@ -141,21 +142,24 @@ impl PyType {
|
||||
metaclass: PyRef<Self>,
|
||||
ctx: &Context,
|
||||
) -> Result<PyRef<Self>, String> {
|
||||
Self::new_verbose_ref(
|
||||
name,
|
||||
bases[0].clone(),
|
||||
bases,
|
||||
attrs,
|
||||
slots,
|
||||
HeapTypeExt::default(),
|
||||
metaclass,
|
||||
ctx,
|
||||
)
|
||||
// TODO: ensure clean slot name
|
||||
// assert_eq!(slots.name.borrow(), "");
|
||||
|
||||
let name = ctx.new_str(name);
|
||||
let heaptype_ext = HeapTypeExt {
|
||||
name: PyRwLock::new(name),
|
||||
slots: None,
|
||||
number_methods: PyNumberMethods::default(),
|
||||
sequence_methods: PySequenceMethods::default(),
|
||||
mapping_methods: PyMappingMethods::default(),
|
||||
};
|
||||
let base = bases[0].clone();
|
||||
|
||||
Self::new_heap_inner(base, bases, attrs, slots, heaptype_ext, metaclass, ctx)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn new_verbose_ref(
|
||||
name: &str,
|
||||
fn new_heap_inner(
|
||||
base: PyRef<Self>,
|
||||
bases: Vec<PyRef<Self>>,
|
||||
attrs: PyAttributes,
|
||||
@@ -182,8 +186,6 @@ impl PyType {
|
||||
slots.flags |= PyTypeFlags::HAS_DICT
|
||||
}
|
||||
|
||||
*slots.name.get_mut() = Some(String::from(name));
|
||||
|
||||
let new_type = PyRef::new_ref(
|
||||
PyType {
|
||||
base: Some(base),
|
||||
@@ -213,8 +215,7 @@ impl PyType {
|
||||
Ok(new_type)
|
||||
}
|
||||
|
||||
pub fn new_bare_ref(
|
||||
name: &str,
|
||||
pub fn new_static(
|
||||
base: PyRef<Self>,
|
||||
attrs: PyAttributes,
|
||||
mut slots: PyTypeSlots,
|
||||
@@ -224,8 +225,6 @@ impl PyType {
|
||||
slots.flags |= PyTypeFlags::HAS_DICT
|
||||
}
|
||||
|
||||
*slots.name.get_mut() = Some(String::from(name));
|
||||
|
||||
let bases = vec![base.clone()];
|
||||
let mro = base.iter_mro().map(|x| x.to_owned()).collect();
|
||||
|
||||
@@ -280,10 +279,6 @@ impl PyType {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn slot_name(&self) -> String {
|
||||
self.slots.name.read().as_ref().unwrap().to_string()
|
||||
}
|
||||
|
||||
pub fn iter_mro(&self) -> impl Iterator<Item = &PyType> + DoubleEndedIterator {
|
||||
std::iter::once(self).chain(self.mro.iter().map(|cls| -> &PyType { cls }))
|
||||
}
|
||||
@@ -369,16 +364,30 @@ impl PyType {
|
||||
call_slot_new(zelf, subtype, args, vm)
|
||||
}
|
||||
|
||||
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) {
|
||||
static_f(self.slots.name)
|
||||
} else {
|
||||
heap_f(self.heaptype_ext.as_ref().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
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> {
|
||||
PyRwLockReadGuard::map(self.slots.name.read(), |slot_name| {
|
||||
let name = slot_name.as_ref().unwrap();
|
||||
if self.slots.flags.has_feature(PyTypeFlags::HEAPTYPE) {
|
||||
name.as_str()
|
||||
} else {
|
||||
name.rsplit('.').next().unwrap()
|
||||
}
|
||||
})
|
||||
.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(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,8 +434,21 @@ impl PyType {
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn __name__(&self) -> String {
|
||||
self.name().to_string()
|
||||
pub fn __name__(&self, vm: &VirtualMachine) -> PyStrRef {
|
||||
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.slot_name()
|
||||
)
|
||||
})
|
||||
.to_owned()
|
||||
},
|
||||
|ext| ext.name.read().clone(),
|
||||
)
|
||||
}
|
||||
|
||||
#[pygetset(magic)]
|
||||
@@ -608,7 +630,7 @@ impl PyType {
|
||||
let (name, bases, dict, kwargs): (PyStrRef, PyTupleRef, PyDictRef, KwArgs) =
|
||||
args.clone().bind(vm)?;
|
||||
|
||||
if name.as_str().contains(char::from(0)) {
|
||||
if name.as_str().as_bytes().contains(&0) {
|
||||
return Err(vm.new_value_error("type name must not contain null characters".to_owned()));
|
||||
}
|
||||
|
||||
@@ -733,17 +755,24 @@ impl PyType {
|
||||
base.slots.member_count + heaptype_slots.as_ref().map(|x| x.len()).unwrap_or(0);
|
||||
|
||||
let flags = PyTypeFlags::heap_type_flags() | PyTypeFlags::HAS_DICT;
|
||||
let heaptype_ext = HeapTypeExt {
|
||||
slots: heaptype_slots.to_owned(),
|
||||
..HeapTypeExt::default()
|
||||
};
|
||||
let slots = PyTypeSlots {
|
||||
member_count,
|
||||
..PyTypeSlots::from_flags(flags)
|
||||
let (slots, heaptype_ext) = unsafe {
|
||||
// # Safety
|
||||
// `slots.name` live long enough because `heaptype_ext` is alive.
|
||||
let slots = PyTypeSlots {
|
||||
member_count,
|
||||
..PyTypeSlots::new(&*(name.as_str() as *const _), flags)
|
||||
};
|
||||
let heaptype_ext = HeapTypeExt {
|
||||
name: PyRwLock::new(name),
|
||||
slots: heaptype_slots.to_owned(),
|
||||
number_methods: PyNumberMethods::default(),
|
||||
sequence_methods: PySequenceMethods::default(),
|
||||
mapping_methods: PyMappingMethods::default(),
|
||||
};
|
||||
(slots, heaptype_ext)
|
||||
};
|
||||
|
||||
let typ = Self::new_verbose_ref(
|
||||
name.as_str(),
|
||||
let typ = Self::new_heap_inner(
|
||||
base,
|
||||
bases,
|
||||
attributes,
|
||||
@@ -837,26 +866,38 @@ impl PyType {
|
||||
))
|
||||
}
|
||||
|
||||
#[pygetset(magic, setter)]
|
||||
fn set_name(&self, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
if !self.slots.flags.has_feature(PyTypeFlags::HEAPTYPE) {
|
||||
fn check_set_special_type_attr(
|
||||
&self,
|
||||
_value: &PyObject,
|
||||
name: &PyStrInterned,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
if self.slots.flags.has_feature(PyTypeFlags::IMMUTABLETYPE) {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"cannot set '{}' attribute of immutable type '{}'",
|
||||
"__name__",
|
||||
self.name()
|
||||
name,
|
||||
self.slot_name()
|
||||
)));
|
||||
}
|
||||
let name = value.downcast_ref::<PyStr>().ok_or_else(|| {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[pygetset(magic, setter)]
|
||||
fn set_name(&self, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
self.check_set_special_type_attr(&value, identifier!(vm, __name__), vm)?;
|
||||
let name = value.downcast::<PyStr>().map_err(|value| {
|
||||
vm.new_type_error(format!(
|
||||
"can only assign string to {}.__name__, not '{}'",
|
||||
self.name(),
|
||||
value.class().name()
|
||||
self.slot_name(),
|
||||
value.class().slot_name(),
|
||||
))
|
||||
})?;
|
||||
if name.as_str().contains(char::from(0)) {
|
||||
if name.as_str().as_bytes().contains(&0) {
|
||||
return Err(vm.new_value_error("type name must not contain null characters".to_owned()));
|
||||
}
|
||||
*self.slots.name.write() = Some(name.as_str().to_string());
|
||||
|
||||
*self.heaptype_ext.as_ref().unwrap().name.write() = name;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -932,7 +973,7 @@ pub(crate) fn get_text_signature_from_internal_doc<'a>(
|
||||
}
|
||||
|
||||
impl GetAttr for PyType {
|
||||
fn getattro(zelf: &Py<Self>, name_str: PyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn getattro(zelf: &Py<Self>, name_str: &Py<PyStr>, vm: &VirtualMachine) -> PyResult {
|
||||
#[cold]
|
||||
fn attribute_error(
|
||||
zelf: &Py<PyType>,
|
||||
@@ -946,7 +987,7 @@ impl GetAttr for PyType {
|
||||
))
|
||||
}
|
||||
|
||||
let Some(name) = vm.ctx.interned_str(&*name_str) else {
|
||||
let Some(name) = vm.ctx.interned_str(name_str) else {
|
||||
return Err(attribute_error(zelf, name_str.as_str(), vm));
|
||||
};
|
||||
vm_trace!("type.__getattribute__({:?}, {:?})", zelf, name);
|
||||
@@ -989,7 +1030,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<()> {
|
||||
@@ -1302,7 +1343,7 @@ mod tests {
|
||||
let object = context.types.object_type.to_owned();
|
||||
let type_type = context.types.type_type.to_owned();
|
||||
|
||||
let a = PyType::new_ref(
|
||||
let a = PyType::new_heap(
|
||||
"A",
|
||||
vec![object.clone()],
|
||||
PyAttributes::default(),
|
||||
@@ -1311,7 +1352,7 @@ mod tests {
|
||||
context,
|
||||
)
|
||||
.unwrap();
|
||||
let b = PyType::new_ref(
|
||||
let b = PyType::new_heap(
|
||||
"B",
|
||||
vec![object.clone()],
|
||||
PyAttributes::default(),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use super::{genericalias, type_};
|
||||
use crate::{
|
||||
atomic_func,
|
||||
builtins::{PyFrozenSet, PyStr, PyStrRef, PyTuple, PyTupleRef, PyType},
|
||||
builtins::{PyFrozenSet, PyStr, PyTuple, PyTupleRef, PyType},
|
||||
class::PyClassImpl,
|
||||
common::hash,
|
||||
convert::{ToPyObject, ToPyResult},
|
||||
@@ -139,19 +139,10 @@ pub fn is_unionable(obj: PyObjectRef, vm: &VirtualMachine) -> bool {
|
||||
|| obj.class().is(vm.ctx.types.union_type)
|
||||
}
|
||||
|
||||
fn is_typevar(obj: &PyObjectRef, vm: &VirtualMachine) -> bool {
|
||||
let class = obj.class();
|
||||
class.slot_name() == "TypeVar"
|
||||
&& class
|
||||
.get_attr(identifier!(vm, __module__))
|
||||
.and_then(|o| o.downcast_ref::<PyStr>().map(|s| s.as_str() == "typing"))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
fn make_parameters(args: &PyTupleRef, vm: &VirtualMachine) -> PyTupleRef {
|
||||
let mut parameters: Vec<PyObjectRef> = Vec::with_capacity(args.len());
|
||||
for arg in args {
|
||||
if is_typevar(arg, vm) {
|
||||
if genericalias::is_typevar(arg, vm) {
|
||||
if !parameters.iter().any(|param| param.is(arg)) {
|
||||
parameters.push(arg.clone());
|
||||
}
|
||||
@@ -301,7 +292,7 @@ impl Hashable for PyUnion {
|
||||
}
|
||||
|
||||
impl GetAttr for PyUnion {
|
||||
fn getattro(zelf: &Py<Self>, attr: PyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn getattro(zelf: &Py<Self>, attr: &Py<PyStr>, vm: &VirtualMachine) -> PyResult {
|
||||
for &exc in CLS_ATTRS {
|
||||
if *exc == attr.to_string() {
|
||||
return zelf.as_object().generic_getattr(attr, vm);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use super::{PyStrRef, PyType, PyTypeRef, PyWeak};
|
||||
use super::{PyStr, PyStrRef, PyType, PyTypeRef, PyWeak};
|
||||
use crate::{
|
||||
atomic_func,
|
||||
class::PyClassImpl,
|
||||
@@ -132,7 +132,7 @@ fn new_reference_error(vm: &VirtualMachine) -> PyRef<super::PyBaseException> {
|
||||
|
||||
impl GetAttr for PyWeakProxy {
|
||||
// TODO: callbacks
|
||||
fn getattro(zelf: &Py<Self>, name: PyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn getattro(zelf: &Py<Self>, name: &Py<PyStr>, vm: &VirtualMachine) -> PyResult {
|
||||
let obj = zelf.try_upgrade(vm)?;
|
||||
obj.get_attr(name, vm)
|
||||
}
|
||||
@@ -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<()> {
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::{
|
||||
types::{hash_not_implemented, PyTypeFlags, PyTypeSlots},
|
||||
vm::Context,
|
||||
};
|
||||
use rustpython_common::{lock::PyRwLock, static_cell};
|
||||
use rustpython_common::static_cell;
|
||||
|
||||
pub trait StaticType {
|
||||
// Ideally, saving PyType is better than PyTypeRef
|
||||
@@ -29,22 +29,21 @@ pub trait StaticType {
|
||||
.unwrap_or_else(|_| panic!("double initialization from init_manually"));
|
||||
cell.get().unwrap()
|
||||
}
|
||||
fn init_bare_type() -> &'static Py<PyType>
|
||||
fn init_builtin_type() -> &'static Py<PyType>
|
||||
where
|
||||
Self: PyClassImpl,
|
||||
{
|
||||
let typ = Self::create_bare_type();
|
||||
let typ = Self::create_static_type();
|
||||
let cell = Self::static_cell();
|
||||
cell.set(typ)
|
||||
.unwrap_or_else(|_| panic!("double initialization of {}", Self::NAME));
|
||||
cell.get().unwrap()
|
||||
}
|
||||
fn create_bare_type() -> PyTypeRef
|
||||
fn create_static_type() -> PyTypeRef
|
||||
where
|
||||
Self: PyClassImpl,
|
||||
{
|
||||
PyType::new_bare_ref(
|
||||
Self::NAME,
|
||||
PyType::new_static(
|
||||
Self::static_baseclass().to_owned(),
|
||||
Default::default(),
|
||||
Self::make_slots(),
|
||||
@@ -73,6 +72,9 @@ pub trait PyClassImpl: PyClassDef {
|
||||
{
|
||||
assert!(class.slots.flags.is_created_with_flags());
|
||||
}
|
||||
|
||||
let _ = ctx.intern_str(Self::NAME); // intern type name
|
||||
|
||||
if Self::TP_FLAGS.has_feature(PyTypeFlags::HAS_DICT) {
|
||||
let __dict__ = identifier!(ctx, __dict__);
|
||||
class.set_attr(
|
||||
@@ -113,7 +115,7 @@ pub trait PyClassImpl: PyClassDef {
|
||||
Self: StaticType,
|
||||
{
|
||||
(*Self::static_cell().get_or_init(|| {
|
||||
let typ = Self::create_bare_type();
|
||||
let typ = Self::create_static_type();
|
||||
Self::extend_class(ctx, unsafe {
|
||||
// typ will be saved in static_cell
|
||||
let r: &Py<PyType> = &typ;
|
||||
@@ -129,7 +131,7 @@ pub trait PyClassImpl: PyClassDef {
|
||||
fn make_slots() -> PyTypeSlots {
|
||||
let mut slots = PyTypeSlots {
|
||||
flags: Self::TP_FLAGS,
|
||||
name: PyRwLock::new(Some(Self::TP_NAME.to_owned())),
|
||||
name: Self::TP_NAME,
|
||||
basicsize: Self::BASICSIZE,
|
||||
doc: Self::DOC,
|
||||
..Default::default()
|
||||
|
||||
@@ -414,7 +414,6 @@ macro_rules! extend_exception {
|
||||
};
|
||||
}
|
||||
|
||||
#[pyclass(with(Constructor, Initializer), flags(BASETYPE, HAS_DICT))]
|
||||
impl PyBaseException {
|
||||
pub(crate) fn new(args: Vec<PyObjectRef>, vm: &VirtualMachine) -> PyBaseException {
|
||||
PyBaseException {
|
||||
@@ -429,7 +428,10 @@ impl PyBaseException {
|
||||
pub fn get_arg(&self, idx: usize) -> Option<PyObjectRef> {
|
||||
self.args.read().get(idx).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(Constructor, Initializer), flags(BASETYPE, HAS_DICT))]
|
||||
impl PyBaseException {
|
||||
#[pygetset]
|
||||
pub fn args(&self) -> PyTupleRef {
|
||||
self.args.read().clone()
|
||||
@@ -540,92 +542,92 @@ impl ExceptionZoo {
|
||||
pub(crate) fn init() -> Self {
|
||||
use self::types::*;
|
||||
|
||||
let base_exception_type = PyBaseException::init_bare_type();
|
||||
let base_exception_type = PyBaseException::init_builtin_type();
|
||||
|
||||
// Sorted By Hierarchy then alphabetized.
|
||||
let base_exception_group = PyBaseExceptionGroup::init_bare_type();
|
||||
let system_exit = PySystemExit::init_bare_type();
|
||||
let keyboard_interrupt = PyKeyboardInterrupt::init_bare_type();
|
||||
let generator_exit = PyGeneratorExit::init_bare_type();
|
||||
let base_exception_group = PyBaseExceptionGroup::init_builtin_type();
|
||||
let system_exit = PySystemExit::init_builtin_type();
|
||||
let keyboard_interrupt = PyKeyboardInterrupt::init_builtin_type();
|
||||
let generator_exit = PyGeneratorExit::init_builtin_type();
|
||||
|
||||
let exception_type = PyException::init_bare_type();
|
||||
let stop_iteration = PyStopIteration::init_bare_type();
|
||||
let stop_async_iteration = PyStopAsyncIteration::init_bare_type();
|
||||
let arithmetic_error = PyArithmeticError::init_bare_type();
|
||||
let floating_point_error = PyFloatingPointError::init_bare_type();
|
||||
let overflow_error = PyOverflowError::init_bare_type();
|
||||
let zero_division_error = PyZeroDivisionError::init_bare_type();
|
||||
let exception_type = PyException::init_builtin_type();
|
||||
let stop_iteration = PyStopIteration::init_builtin_type();
|
||||
let stop_async_iteration = PyStopAsyncIteration::init_builtin_type();
|
||||
let arithmetic_error = PyArithmeticError::init_builtin_type();
|
||||
let floating_point_error = PyFloatingPointError::init_builtin_type();
|
||||
let overflow_error = PyOverflowError::init_builtin_type();
|
||||
let zero_division_error = PyZeroDivisionError::init_builtin_type();
|
||||
|
||||
let assertion_error = PyAssertionError::init_bare_type();
|
||||
let attribute_error = PyAttributeError::init_bare_type();
|
||||
let buffer_error = PyBufferError::init_bare_type();
|
||||
let eof_error = PyEOFError::init_bare_type();
|
||||
let assertion_error = PyAssertionError::init_builtin_type();
|
||||
let attribute_error = PyAttributeError::init_builtin_type();
|
||||
let buffer_error = PyBufferError::init_builtin_type();
|
||||
let eof_error = PyEOFError::init_builtin_type();
|
||||
|
||||
let import_error = PyImportError::init_bare_type();
|
||||
let module_not_found_error = PyModuleNotFoundError::init_bare_type();
|
||||
let import_error = PyImportError::init_builtin_type();
|
||||
let module_not_found_error = PyModuleNotFoundError::init_builtin_type();
|
||||
|
||||
let lookup_error = PyLookupError::init_bare_type();
|
||||
let index_error = PyIndexError::init_bare_type();
|
||||
let key_error = PyKeyError::init_bare_type();
|
||||
let lookup_error = PyLookupError::init_builtin_type();
|
||||
let index_error = PyIndexError::init_builtin_type();
|
||||
let key_error = PyKeyError::init_builtin_type();
|
||||
|
||||
let memory_error = PyMemoryError::init_bare_type();
|
||||
let memory_error = PyMemoryError::init_builtin_type();
|
||||
|
||||
let name_error = PyNameError::init_bare_type();
|
||||
let unbound_local_error = PyUnboundLocalError::init_bare_type();
|
||||
let name_error = PyNameError::init_builtin_type();
|
||||
let unbound_local_error = PyUnboundLocalError::init_builtin_type();
|
||||
|
||||
// os errors
|
||||
let os_error = PyOSError::init_bare_type();
|
||||
let blocking_io_error = PyBlockingIOError::init_bare_type();
|
||||
let child_process_error = PyChildProcessError::init_bare_type();
|
||||
let os_error = PyOSError::init_builtin_type();
|
||||
let blocking_io_error = PyBlockingIOError::init_builtin_type();
|
||||
let child_process_error = PyChildProcessError::init_builtin_type();
|
||||
|
||||
let connection_error = PyConnectionError::init_bare_type();
|
||||
let broken_pipe_error = PyBrokenPipeError::init_bare_type();
|
||||
let connection_aborted_error = PyConnectionAbortedError::init_bare_type();
|
||||
let connection_refused_error = PyConnectionRefusedError::init_bare_type();
|
||||
let connection_reset_error = PyConnectionResetError::init_bare_type();
|
||||
let connection_error = PyConnectionError::init_builtin_type();
|
||||
let broken_pipe_error = PyBrokenPipeError::init_builtin_type();
|
||||
let connection_aborted_error = PyConnectionAbortedError::init_builtin_type();
|
||||
let connection_refused_error = PyConnectionRefusedError::init_builtin_type();
|
||||
let connection_reset_error = PyConnectionResetError::init_builtin_type();
|
||||
|
||||
let file_exists_error = PyFileExistsError::init_bare_type();
|
||||
let file_not_found_error = PyFileNotFoundError::init_bare_type();
|
||||
let interrupted_error = PyInterruptedError::init_bare_type();
|
||||
let is_a_directory_error = PyIsADirectoryError::init_bare_type();
|
||||
let not_a_directory_error = PyNotADirectoryError::init_bare_type();
|
||||
let permission_error = PyPermissionError::init_bare_type();
|
||||
let process_lookup_error = PyProcessLookupError::init_bare_type();
|
||||
let timeout_error = PyTimeoutError::init_bare_type();
|
||||
let file_exists_error = PyFileExistsError::init_builtin_type();
|
||||
let file_not_found_error = PyFileNotFoundError::init_builtin_type();
|
||||
let interrupted_error = PyInterruptedError::init_builtin_type();
|
||||
let is_a_directory_error = PyIsADirectoryError::init_builtin_type();
|
||||
let not_a_directory_error = PyNotADirectoryError::init_builtin_type();
|
||||
let permission_error = PyPermissionError::init_builtin_type();
|
||||
let process_lookup_error = PyProcessLookupError::init_builtin_type();
|
||||
let timeout_error = PyTimeoutError::init_builtin_type();
|
||||
|
||||
let reference_error = PyReferenceError::init_bare_type();
|
||||
let reference_error = PyReferenceError::init_builtin_type();
|
||||
|
||||
let runtime_error = PyRuntimeError::init_bare_type();
|
||||
let not_implemented_error = PyNotImplementedError::init_bare_type();
|
||||
let recursion_error = PyRecursionError::init_bare_type();
|
||||
let runtime_error = PyRuntimeError::init_builtin_type();
|
||||
let not_implemented_error = PyNotImplementedError::init_builtin_type();
|
||||
let recursion_error = PyRecursionError::init_builtin_type();
|
||||
|
||||
let syntax_error = PySyntaxError::init_bare_type();
|
||||
let indentation_error = PyIndentationError::init_bare_type();
|
||||
let tab_error = PyTabError::init_bare_type();
|
||||
let syntax_error = PySyntaxError::init_builtin_type();
|
||||
let indentation_error = PyIndentationError::init_builtin_type();
|
||||
let tab_error = PyTabError::init_builtin_type();
|
||||
|
||||
let system_error = PySystemError::init_bare_type();
|
||||
let type_error = PyTypeError::init_bare_type();
|
||||
let value_error = PyValueError::init_bare_type();
|
||||
let unicode_error = PyUnicodeError::init_bare_type();
|
||||
let unicode_decode_error = PyUnicodeDecodeError::init_bare_type();
|
||||
let unicode_encode_error = PyUnicodeEncodeError::init_bare_type();
|
||||
let unicode_translate_error = PyUnicodeTranslateError::init_bare_type();
|
||||
let system_error = PySystemError::init_builtin_type();
|
||||
let type_error = PyTypeError::init_builtin_type();
|
||||
let value_error = PyValueError::init_builtin_type();
|
||||
let unicode_error = PyUnicodeError::init_builtin_type();
|
||||
let unicode_decode_error = PyUnicodeDecodeError::init_builtin_type();
|
||||
let unicode_encode_error = PyUnicodeEncodeError::init_builtin_type();
|
||||
let unicode_translate_error = PyUnicodeTranslateError::init_builtin_type();
|
||||
|
||||
#[cfg(feature = "jit")]
|
||||
let jit_error = PyJitError::init_bare_type();
|
||||
let jit_error = PyJitError::init_builtin_type();
|
||||
|
||||
let warning = PyWarning::init_bare_type();
|
||||
let deprecation_warning = PyDeprecationWarning::init_bare_type();
|
||||
let pending_deprecation_warning = PyPendingDeprecationWarning::init_bare_type();
|
||||
let runtime_warning = PyRuntimeWarning::init_bare_type();
|
||||
let syntax_warning = PySyntaxWarning::init_bare_type();
|
||||
let user_warning = PyUserWarning::init_bare_type();
|
||||
let future_warning = PyFutureWarning::init_bare_type();
|
||||
let import_warning = PyImportWarning::init_bare_type();
|
||||
let unicode_warning = PyUnicodeWarning::init_bare_type();
|
||||
let bytes_warning = PyBytesWarning::init_bare_type();
|
||||
let resource_warning = PyResourceWarning::init_bare_type();
|
||||
let encoding_warning = PyEncodingWarning::init_bare_type();
|
||||
let warning = PyWarning::init_builtin_type();
|
||||
let deprecation_warning = PyDeprecationWarning::init_builtin_type();
|
||||
let pending_deprecation_warning = PyPendingDeprecationWarning::init_builtin_type();
|
||||
let runtime_warning = PyRuntimeWarning::init_builtin_type();
|
||||
let syntax_warning = PySyntaxWarning::init_builtin_type();
|
||||
let user_warning = PyUserWarning::init_builtin_type();
|
||||
let future_warning = PyFutureWarning::init_builtin_type();
|
||||
let import_warning = PyImportWarning::init_builtin_type();
|
||||
let unicode_warning = PyUnicodeWarning::init_builtin_type();
|
||||
let bytes_warning = PyBytesWarning::init_builtin_type();
|
||||
let resource_warning = PyResourceWarning::init_builtin_type();
|
||||
let encoding_warning = PyEncodingWarning::init_builtin_type();
|
||||
|
||||
Self {
|
||||
base_exception_type,
|
||||
|
||||
@@ -79,7 +79,7 @@ fn format_internal(
|
||||
for name_part in parts {
|
||||
match name_part {
|
||||
FieldNamePart::Attribute(attribute) => {
|
||||
argument = argument.get_attr(attribute.as_str(), vm)?;
|
||||
argument = argument.get_attr(&vm.ctx.new_str(attribute), vm)?;
|
||||
}
|
||||
FieldNamePart::Index(index) => {
|
||||
argument = argument.get_item(&index, vm)?;
|
||||
|
||||
@@ -516,7 +516,7 @@ impl ExecutingFrame<'_> {
|
||||
Ok(None)
|
||||
}
|
||||
bytecode::Instruction::ImportName { idx } => {
|
||||
self.import(vm, Some(self.code.names[idx.get(arg) as usize].to_owned()))?;
|
||||
self.import(vm, Some(self.code.names[idx.get(arg) as usize]))?;
|
||||
Ok(None)
|
||||
}
|
||||
bytecode::Instruction::ImportNameless => {
|
||||
@@ -1020,7 +1020,7 @@ impl ExecutingFrame<'_> {
|
||||
bytecode::Instruction::LoadMethod { idx } => {
|
||||
let obj = self.pop_value();
|
||||
let method_name = self.code.names[idx.get(arg) as usize];
|
||||
let method = PyMethod::get(obj, method_name.to_owned(), vm)?;
|
||||
let method = PyMethod::get(obj, method_name, vm)?;
|
||||
let (target, is_method, func) = match method {
|
||||
PyMethod::Function { target, func } => (target, true, func),
|
||||
PyMethod::Attribute(val) => (vm.ctx.none(), false, val),
|
||||
@@ -1129,8 +1129,8 @@ impl ExecutingFrame<'_> {
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "flame-it", flame("Frame"))]
|
||||
fn import(&mut self, vm: &VirtualMachine, module: Option<PyStrRef>) -> PyResult<()> {
|
||||
let module = module.unwrap_or_else(|| vm.ctx.empty_str.clone());
|
||||
fn import(&mut self, vm: &VirtualMachine, module: Option<&Py<PyStr>>) -> PyResult<()> {
|
||||
let module = module.unwrap_or(&vm.ctx.empty_str);
|
||||
let from_list = <Option<PyTupleTyped<PyStrRef>>>::try_from_object(vm, self.pop_value())?;
|
||||
let level = usize::try_from_object(vm, self.pop_value())?;
|
||||
|
||||
@@ -1144,7 +1144,7 @@ impl ExecutingFrame<'_> {
|
||||
fn import_from(&mut self, vm: &VirtualMachine, idx: bytecode::NameIdx) -> PyResult {
|
||||
let module = self.last_value();
|
||||
let name = self.code.names[idx as usize];
|
||||
let err = || vm.new_import_error(format!("cannot import name '{name}'"), name);
|
||||
let err = || vm.new_import_error(format!("cannot import name '{name}'"), name.to_owned());
|
||||
// Load attribute, and transform any error into import error.
|
||||
if let Some(obj) = vm.get_attribute_opt(module.clone(), name)? {
|
||||
return Ok(obj);
|
||||
|
||||
@@ -27,7 +27,7 @@ pub(crate) fn init_importlib_base(vm: &mut VirtualMachine) -> PyResult<PyObjectR
|
||||
install.call((vm.sys_module.clone(), imp), vm)?;
|
||||
Ok(bootstrap)
|
||||
})?;
|
||||
vm.import_func = importlib.get_attr(identifier!(vm, __import__).to_owned(), vm)?;
|
||||
vm.import_func = importlib.get_attr(identifier!(vm, __import__), vm)?;
|
||||
Ok(importlib)
|
||||
}
|
||||
|
||||
@@ -73,10 +73,12 @@ pub(crate) fn init_importlib_package(
|
||||
}
|
||||
|
||||
pub fn make_frozen(vm: &VirtualMachine, name: &str) -> PyResult<PyRef<PyCode>> {
|
||||
let frozen =
|
||||
vm.state.frozen.get(name).ok_or_else(|| {
|
||||
vm.new_import_error(format!("No such frozen object named {name}"), name)
|
||||
})?;
|
||||
let frozen = vm.state.frozen.get(name).ok_or_else(|| {
|
||||
vm.new_import_error(
|
||||
format!("No such frozen object named {name}"),
|
||||
vm.ctx.new_str(name),
|
||||
)
|
||||
})?;
|
||||
Ok(vm.ctx.new_code(frozen.code))
|
||||
}
|
||||
|
||||
@@ -92,7 +94,7 @@ pub fn import_builtin(vm: &VirtualMachine, module_name: &str) -> PyResult {
|
||||
let make_module_func = vm.state.module_inits.get(module_name).ok_or_else(|| {
|
||||
vm.new_import_error(
|
||||
format!("Cannot import builtin module {module_name}"),
|
||||
module_name,
|
||||
vm.ctx.new_str(module_name),
|
||||
)
|
||||
})?;
|
||||
let module = make_module_func(vm);
|
||||
|
||||
@@ -32,7 +32,11 @@ impl Clone for StringPool {
|
||||
|
||||
impl StringPool {
|
||||
#[inline]
|
||||
pub unsafe fn intern<S: Internable>(&self, s: S, typ: PyTypeRef) -> &'static PyStrInterned {
|
||||
pub unsafe fn intern<S: InternableString>(
|
||||
&self,
|
||||
s: S,
|
||||
typ: PyTypeRef,
|
||||
) -> &'static PyStrInterned {
|
||||
if let Some(found) = self.interned(s.as_ref()) {
|
||||
return found;
|
||||
}
|
||||
@@ -60,7 +64,10 @@ impl StringPool {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn interned<S: MaybeInterned + ?Sized>(&self, s: &S) -> Option<&'static PyStrInterned> {
|
||||
pub fn interned<S: MaybeInternedString + ?Sized>(
|
||||
&self,
|
||||
s: &S,
|
||||
) -> Option<&'static PyStrInterned> {
|
||||
if let Some(interned) = s.as_interned() {
|
||||
return Some(interned);
|
||||
}
|
||||
@@ -164,6 +171,13 @@ impl<T: PyPayload> std::hash::Hash for PyInterned<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyPayload> AsRef<Py<T>> for PyInterned<T> {
|
||||
#[inline(always)]
|
||||
fn as_ref(&self) -> &Py<T> {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyPayload> Deref for PyInterned<T> {
|
||||
type Target = Py<T>;
|
||||
#[inline(always)]
|
||||
@@ -214,16 +228,16 @@ mod sealed {
|
||||
}
|
||||
|
||||
/// A sealed marker trait for `DictKey` types that always become an exact instance of `str`
|
||||
pub trait Internable
|
||||
pub trait InternableString
|
||||
where
|
||||
Self: sealed::SealedInternable + ToPyObject + AsRef<Self::Interned>,
|
||||
Self::Interned: MaybeInterned,
|
||||
Self::Interned: MaybeInternedString,
|
||||
{
|
||||
type Interned: ?Sized;
|
||||
fn into_pyref_exact(self, str_type: PyTypeRef) -> PyRefExact<PyStr>;
|
||||
}
|
||||
|
||||
impl Internable for String {
|
||||
impl InternableString for String {
|
||||
type Interned = str;
|
||||
#[inline]
|
||||
fn into_pyref_exact(self, str_type: PyTypeRef) -> PyRefExact<PyStr> {
|
||||
@@ -232,7 +246,7 @@ impl Internable for String {
|
||||
}
|
||||
}
|
||||
|
||||
impl Internable for &str {
|
||||
impl InternableString for &str {
|
||||
type Interned = str;
|
||||
#[inline]
|
||||
fn into_pyref_exact(self, str_type: PyTypeRef) -> PyRefExact<PyStr> {
|
||||
@@ -240,7 +254,7 @@ impl Internable for &str {
|
||||
}
|
||||
}
|
||||
|
||||
impl Internable for PyRefExact<PyStr> {
|
||||
impl InternableString for PyRefExact<PyStr> {
|
||||
type Interned = Py<PyStr>;
|
||||
#[inline]
|
||||
fn into_pyref_exact(self, _str_type: PyTypeRef) -> PyRefExact<PyStr> {
|
||||
@@ -248,27 +262,27 @@ impl Internable for PyRefExact<PyStr> {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait MaybeInterned:
|
||||
pub trait MaybeInternedString:
|
||||
AsRef<str> + crate::dictdatatype::DictKey + sealed::SealedMaybeInterned
|
||||
{
|
||||
fn as_interned(&self) -> Option<&'static PyStrInterned>;
|
||||
}
|
||||
|
||||
impl MaybeInterned for str {
|
||||
impl MaybeInternedString for str {
|
||||
#[inline(always)]
|
||||
fn as_interned(&self) -> Option<&'static PyStrInterned> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl MaybeInterned for PyExact<PyStr> {
|
||||
impl MaybeInternedString for PyExact<PyStr> {
|
||||
#[inline(always)]
|
||||
fn as_interned(&self) -> Option<&'static PyStrInterned> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl MaybeInterned for Py<PyStr> {
|
||||
impl MaybeInternedString for Py<PyStr> {
|
||||
#[inline(always)]
|
||||
fn as_interned(&self) -> Option<&'static PyStrInterned> {
|
||||
if self.as_object().is_interned() {
|
||||
|
||||
@@ -17,7 +17,7 @@ macro_rules! py_class {
|
||||
( $ctx:expr, $class_name:expr, $class_base:expr, $flags:expr, { $($name:tt => $value:expr),* $(,)* }) => {
|
||||
{
|
||||
#[allow(unused_mut)]
|
||||
let mut slots = $crate::types::PyTypeSlots::from_flags($crate::types::PyTypeFlags::DEFAULT | $flags);
|
||||
let mut slots = $crate::types::PyTypeSlots::new($class_name, $crate::types::PyTypeFlags::DEFAULT | $flags);
|
||||
$($crate::py_class!(@extract_slots($ctx, &mut slots, $name, $value));)*
|
||||
let py_class = $ctx.new_class(None, $class_name, $class_base, slots);
|
||||
$($crate::py_class!(@extract_attrs($ctx, &py_class, $name, $value));)*
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
use crate::{
|
||||
builtins::{
|
||||
pystr::IntoPyStrRef, PyBytes, PyDict, PyDictRef, PyGenericAlias, PyInt, PyStr, PyStrRef,
|
||||
pystr::AsPyStr, PyBytes, PyDict, PyDictRef, PyGenericAlias, PyInt, PyStr, PyStrRef,
|
||||
PyTupleRef, PyTypeRef,
|
||||
},
|
||||
bytesinner::ByteInnerNewOptions,
|
||||
@@ -13,7 +13,7 @@ use crate::{
|
||||
function::{Either, OptionalArg, PyArithmeticValue, PySetterValue},
|
||||
protocol::{PyIter, PyMapping, PySequence},
|
||||
types::{Constructor, PyComparisonOp},
|
||||
AsObject, PyObject, PyObjectRef, PyResult, TryFromObject, VirtualMachine,
|
||||
AsObject, Py, PyObject, PyObjectRef, PyResult, TryFromObject, VirtualMachine,
|
||||
};
|
||||
|
||||
// RustPython doesn't need these items
|
||||
@@ -75,26 +75,26 @@ impl PyObjectRef {
|
||||
}
|
||||
|
||||
impl PyObject {
|
||||
pub fn has_attr(&self, attr_name: impl IntoPyStrRef, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
self.get_attr(attr_name, vm).map(|o| vm.is_none(&o))
|
||||
pub fn has_attr<'a>(&self, attr_name: impl AsPyStr<'a>, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
self.get_attr(attr_name, vm).map(|o| !vm.is_none(&o))
|
||||
}
|
||||
|
||||
pub fn get_attr(&self, attr_name: impl IntoPyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
let attr_name = attr_name.into_pystr_ref(vm);
|
||||
self._get_attr(attr_name, vm)
|
||||
pub fn get_attr<'a>(&self, attr_name: impl AsPyStr<'a>, vm: &VirtualMachine) -> PyResult {
|
||||
let attr_name = attr_name.as_pystr(&vm.ctx);
|
||||
self.get_attr_inner(attr_name, vm)
|
||||
}
|
||||
|
||||
// get_attribute should be used for full attribute access (usually from user code).
|
||||
#[cfg_attr(feature = "flame-it", flame("PyObjectRef"))]
|
||||
#[inline]
|
||||
fn _get_attr(&self, attr_name: PyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
pub(crate) fn get_attr_inner(&self, attr_name: &Py<PyStr>, vm: &VirtualMachine) -> PyResult {
|
||||
vm_trace!("object.__getattribute__: {:?} {:?}", self, attr_name);
|
||||
let getattro = self
|
||||
.class()
|
||||
.mro_find_map(|cls| cls.slots.getattro.load())
|
||||
.unwrap();
|
||||
getattro(self, attr_name.clone(), vm).map_err(|exc| {
|
||||
vm.set_attribute_error_context(&exc, self.to_owned(), attr_name);
|
||||
getattro(self, attr_name, vm).map_err(|exc| {
|
||||
vm.set_attribute_error_context(&exc, self.to_owned(), attr_name.to_owned());
|
||||
exc
|
||||
})
|
||||
}
|
||||
@@ -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 '{}'",
|
||||
@@ -182,27 +182,26 @@ impl PyObject {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generic_getattr(&self, name: PyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
self.generic_getattr_opt(name.clone(), None, vm)?
|
||||
.ok_or_else(|| {
|
||||
vm.new_attribute_error(format!(
|
||||
"'{}' object has no attribute '{}'",
|
||||
self.class().name(),
|
||||
name
|
||||
))
|
||||
})
|
||||
pub fn generic_getattr(&self, name: &Py<PyStr>, vm: &VirtualMachine) -> PyResult {
|
||||
self.generic_getattr_opt(name, None, vm)?.ok_or_else(|| {
|
||||
vm.new_attribute_error(format!(
|
||||
"'{}' object has no attribute '{}'",
|
||||
self.class().name(),
|
||||
name
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
/// CPython _PyObject_GenericGetAttrWithDict
|
||||
pub fn generic_getattr_opt(
|
||||
&self,
|
||||
name_str: PyStrRef,
|
||||
name_str: &Py<PyStr>,
|
||||
dict: Option<PyDictRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<Option<PyObjectRef>> {
|
||||
let name = name_str.as_str();
|
||||
let obj_cls = self.class();
|
||||
let cls_attr_name = vm.ctx.interned_str(&*name_str);
|
||||
let cls_attr_name = vm.ctx.interned_str(name_str);
|
||||
let cls_attr = match cls_attr_name.and_then(|name| obj_cls.get_attr(name)) {
|
||||
Some(descr) => {
|
||||
let descr_cls = descr.class();
|
||||
@@ -244,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)
|
||||
}
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ impl Scope {
|
||||
// impl Sealed for super::PyStrRef {}
|
||||
// }
|
||||
// pub trait PyName:
|
||||
// sealed::Sealed + crate::dictdatatype::DictKey + Clone + ToPyObject + IntoPyStrRef
|
||||
// sealed::Sealed + crate::dictdatatype::DictKey + Clone + ToPyObject
|
||||
// {
|
||||
// }
|
||||
// impl PyName for str {}
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
@@ -77,7 +77,7 @@ mod _ast {
|
||||
use super::PY_COMPILE_FLAG_AST_ONLY;
|
||||
}
|
||||
|
||||
fn get_node_field(vm: &VirtualMachine, obj: &PyObject, field: &str, typ: &str) -> PyResult {
|
||||
fn get_node_field(vm: &VirtualMachine, obj: &PyObject, field: &'static str, typ: &str) -> PyResult {
|
||||
vm.get_attribute_opt(obj.to_owned(), field)?
|
||||
.ok_or_else(|| vm.new_type_error(format!("required field \"{field}\" missing from {typ}")))
|
||||
}
|
||||
@@ -85,7 +85,7 @@ fn get_node_field(vm: &VirtualMachine, obj: &PyObject, field: &str, typ: &str) -
|
||||
fn get_node_field_opt(
|
||||
vm: &VirtualMachine,
|
||||
obj: &PyObject,
|
||||
field: &str,
|
||||
field: &'static str,
|
||||
) -> PyResult<Option<PyObjectRef>> {
|
||||
Ok(vm
|
||||
.get_attribute_opt(obj.to_owned(), field)?
|
||||
|
||||
@@ -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]
|
||||
@@ -326,9 +326,9 @@ mod builtins {
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult {
|
||||
if let OptionalArg::Present(default) = default {
|
||||
Ok(vm.get_attribute_opt(obj, attr)?.unwrap_or(default))
|
||||
Ok(vm.get_attribute_opt(obj, &attr)?.unwrap_or(default))
|
||||
} else {
|
||||
obj.get_attr(attr, vm)
|
||||
obj.get_attr(&attr, vm)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,7 +339,7 @@ mod builtins {
|
||||
|
||||
#[pyfunction]
|
||||
fn hasattr(obj: PyObjectRef, attr: PyStrRef, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
Ok(vm.get_attribute_opt(obj, attr)?.is_some())
|
||||
Ok(vm.get_attribute_opt(obj, &attr)?.is_some())
|
||||
}
|
||||
|
||||
#[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(())
|
||||
}
|
||||
|
||||
@@ -803,10 +803,9 @@ mod builtins {
|
||||
#[pyfunction]
|
||||
fn vars(obj: OptionalArg, vm: &VirtualMachine) -> PyResult {
|
||||
if let OptionalArg::Present(obj) = obj {
|
||||
obj.get_attr(identifier!(vm, __dict__).to_owned(), vm)
|
||||
.map_err(|_| {
|
||||
vm.new_type_error("vars() argument must have __dict__ attribute".to_owned())
|
||||
})
|
||||
obj.get_attr(identifier!(vm, __dict__), vm).map_err(|_| {
|
||||
vm.new_type_error("vars() argument must have __dict__ attribute".to_owned())
|
||||
})
|
||||
} else {
|
||||
Ok(vm.current_locals()?.into())
|
||||
}
|
||||
@@ -882,7 +881,7 @@ mod builtins {
|
||||
}
|
||||
}
|
||||
let meta_name = metaclass.slot_name();
|
||||
(metaclass.into(), meta_name)
|
||||
(metaclass.to_owned().into(), meta_name.to_owned())
|
||||
}
|
||||
Err(obj) => (obj, "<metaclass>".to_owned()),
|
||||
};
|
||||
|
||||
@@ -350,7 +350,7 @@ mod _codecs {
|
||||
#[inline]
|
||||
fn delegate_pycodecs(
|
||||
cell: &'static StaticCell<PyObjectRef>,
|
||||
name: &str,
|
||||
name: &'static str,
|
||||
args: FuncArgs,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -69,7 +69,7 @@ impl FrozenError {
|
||||
Excluded => format!("Excluded frozen object named {mod_name}"),
|
||||
Invalid => format!("Frozen object named {mod_name} is invalid"),
|
||||
};
|
||||
vm.new_import_error(msg, mod_name)
|
||||
vm.new_import_error(msg, vm.ctx.new_str(mod_name))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3637,7 +3637,7 @@ mod _io {
|
||||
}
|
||||
|
||||
pub(super) fn make_unsupportedop(ctx: &Context) -> PyTypeRef {
|
||||
PyType::new_ref(
|
||||
PyType::new_heap(
|
||||
"UnsupportedOperation",
|
||||
vec![
|
||||
ctx.exceptions.os_error.to_owned(),
|
||||
|
||||
@@ -4,7 +4,7 @@ pub(crate) use _operator::make_module;
|
||||
mod _operator {
|
||||
use crate::common::cmp;
|
||||
use crate::{
|
||||
builtins::{PyInt, PyIntRef, PyStrRef, PyTupleRef, PyTypeRef},
|
||||
builtins::{PyInt, PyIntRef, PyStr, PyStrRef, PyTupleRef, PyTypeRef},
|
||||
function::Either,
|
||||
function::{ArgBytesLike, FuncArgs, KwArgs, OptionalArg},
|
||||
identifier,
|
||||
@@ -383,16 +383,17 @@ mod _operator {
|
||||
// Go through dotted parts of string and call getattr on whatever is returned.
|
||||
fn get_single_attr(
|
||||
obj: PyObjectRef,
|
||||
attr: &str,
|
||||
attr: &Py<PyStr>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyObjectRef> {
|
||||
let parts = attr.split('.').collect::<Vec<_>>();
|
||||
let attr_str = attr.as_str();
|
||||
let parts = attr_str.split('.').collect::<Vec<_>>();
|
||||
if parts.len() == 1 {
|
||||
return obj.get_attr(parts[0], vm);
|
||||
return obj.get_attr(attr, vm);
|
||||
}
|
||||
let mut obj = obj;
|
||||
for part in parts {
|
||||
obj = obj.get_attr(part, vm)?;
|
||||
obj = obj.get_attr(&vm.ctx.new_str(part), vm)?;
|
||||
}
|
||||
Ok(obj)
|
||||
}
|
||||
@@ -429,12 +430,12 @@ mod _operator {
|
||||
fn call(zelf: &Py<Self>, obj: Self::Args, vm: &VirtualMachine) -> PyResult {
|
||||
// Handle case where we only have one attribute.
|
||||
if zelf.attrs.len() == 1 {
|
||||
return Self::get_single_attr(obj, zelf.attrs[0].as_str(), vm);
|
||||
return Self::get_single_attr(obj, &zelf.attrs[0], vm);
|
||||
}
|
||||
// Build tuple and call get_single on each element in attrs.
|
||||
let mut results = Vec::with_capacity(zelf.attrs.len());
|
||||
for o in &zelf.attrs {
|
||||
results.push(Self::get_single_attr(obj.clone(), o.as_str(), vm)?);
|
||||
results.push(Self::get_single_attr(obj.clone(), o, vm)?);
|
||||
}
|
||||
Ok(vm.ctx.new_tuple(results).into())
|
||||
}
|
||||
|
||||
@@ -336,27 +336,24 @@ mod sys {
|
||||
#[pyfunction(name = "__breakpointhook__")]
|
||||
#[pyfunction]
|
||||
pub fn breakpointhook(args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
let envar = std::env::var("PYTHONBREAKPOINT")
|
||||
.and_then(|envar| {
|
||||
if envar.is_empty() {
|
||||
let env_var = std::env::var("PYTHONBREAKPOINT")
|
||||
.and_then(|env_var| {
|
||||
if env_var.is_empty() {
|
||||
Err(VarError::NotPresent)
|
||||
} else {
|
||||
Ok(envar)
|
||||
Ok(env_var)
|
||||
}
|
||||
})
|
||||
.unwrap_or_else(|_| "pdb.set_trace".to_owned());
|
||||
|
||||
if envar.eq("0") {
|
||||
if env_var.eq("0") {
|
||||
return Ok(vm.ctx.none());
|
||||
};
|
||||
|
||||
let print_unimportable_module_warn = || {
|
||||
warn(
|
||||
vm.ctx.exceptions.runtime_warning,
|
||||
format!(
|
||||
"Ignoring unimportable $PYTHONBREAKPOINT: \"{}\"",
|
||||
envar.to_owned(),
|
||||
),
|
||||
format!("Ignoring unimportable $PYTHONBREAKPOINT: \"{env_var}\"",),
|
||||
0,
|
||||
vm,
|
||||
)
|
||||
@@ -364,30 +361,26 @@ mod sys {
|
||||
Ok(vm.ctx.none())
|
||||
};
|
||||
|
||||
let last = match envar.split('.').last() {
|
||||
Some(last) => last,
|
||||
None => {
|
||||
return print_unimportable_module_warn();
|
||||
}
|
||||
let last = match env_var.rsplit_once('.') {
|
||||
Some((_, last)) => last,
|
||||
None if !env_var.is_empty() => env_var.as_str(),
|
||||
_ => return print_unimportable_module_warn(),
|
||||
};
|
||||
|
||||
let (modulepath, attrname) = if last.eq(&envar) {
|
||||
("builtins".to_owned(), envar.to_owned())
|
||||
let (module_path, attr_name) = if last == env_var {
|
||||
("builtins", env_var.as_str())
|
||||
} else {
|
||||
(
|
||||
envar[..(envar.len() - last.len() - 1)].to_owned(),
|
||||
last.to_owned(),
|
||||
)
|
||||
(&env_var[..(env_var.len() - last.len() - 1)], last)
|
||||
};
|
||||
|
||||
let module = match vm.import(modulepath, None, 0) {
|
||||
let module = match vm.import(&vm.ctx.new_str(module_path), None, 0) {
|
||||
Ok(module) => module,
|
||||
Err(_) => {
|
||||
return print_unimportable_module_warn();
|
||||
}
|
||||
};
|
||||
|
||||
match vm.get_attribute_opt(module, attrname) {
|
||||
match vm.get_attribute_opt(module, &vm.ctx.new_str(attr_name)) {
|
||||
Ok(Some(hook)) => hook.as_ref().call(args, vm),
|
||||
_ => print_unimportable_module_warn(),
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ pub(crate) use _thread::{make_module, RawRMutex};
|
||||
#[pymodule]
|
||||
pub(crate) mod _thread {
|
||||
use crate::{
|
||||
builtins::{PyDictRef, PyStrRef, PyTupleRef, PyTypeRef},
|
||||
builtins::{PyDictRef, PyStr, PyTupleRef, PyTypeRef},
|
||||
convert::ToPyException,
|
||||
function::{ArgCallable, Either, FuncArgs, KwArgs, OptionalArg, PySetterValue},
|
||||
types::{Constructor, GetAttr, SetAttr},
|
||||
@@ -360,13 +360,13 @@ pub(crate) mod _thread {
|
||||
}
|
||||
|
||||
impl GetAttr for Local {
|
||||
fn getattro(zelf: &Py<Self>, attr: PyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn getattro(zelf: &Py<Self>, attr: &Py<PyStr>, vm: &VirtualMachine) -> PyResult {
|
||||
let ldict = zelf.ldict(vm);
|
||||
if attr.as_str() == "__dict__" {
|
||||
Ok(ldict.into())
|
||||
} else {
|
||||
zelf.as_object()
|
||||
.generic_getattr_opt(attr.clone(), Some(ldict), vm)?
|
||||
.generic_getattr_opt(attr, Some(ldict), vm)?
|
||||
.ok_or_else(|| {
|
||||
vm.new_attribute_error(format!(
|
||||
"{} has no attribute '{}'",
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::{
|
||||
type_::PointerSlot, PyFloat, PyInt, PyStr, PyStrInterned, PyStrRef, PyType, PyTypeRef,
|
||||
},
|
||||
bytecode::ComparisonOperator,
|
||||
common::{hash::PyHash, lock::PyRwLock},
|
||||
common::hash::PyHash,
|
||||
convert::{ToPyObject, ToPyResult},
|
||||
function::{Either, FromArgs, FuncArgs, OptionalArg, PyComparisonValue, PySetterValue},
|
||||
identifier,
|
||||
@@ -30,7 +30,10 @@ macro_rules! atomic_func {
|
||||
#[derive(Default)]
|
||||
#[non_exhaustive]
|
||||
pub struct PyTypeSlots {
|
||||
pub name: PyRwLock<Option<String>>, // tp_name, not class name
|
||||
/// # Safety
|
||||
/// For static types, always safe.
|
||||
/// For heap types, `__name__` must alive
|
||||
pub(crate) name: &'static str, // tp_name with <module>.<class> for print, not class name
|
||||
|
||||
pub basicsize: usize,
|
||||
// tp_itemsize
|
||||
@@ -91,8 +94,9 @@ pub struct PyTypeSlots {
|
||||
}
|
||||
|
||||
impl PyTypeSlots {
|
||||
pub fn from_flags(flags: PyTypeFlags) -> Self {
|
||||
pub fn new(name: &'static str, flags: PyTypeFlags) -> Self {
|
||||
Self {
|
||||
name,
|
||||
flags,
|
||||
..Default::default()
|
||||
}
|
||||
@@ -277,9 +281,9 @@ pub(crate) type GenericMethod = fn(&PyObject, FuncArgs, &VirtualMachine) -> PyRe
|
||||
pub(crate) type HashFunc = fn(&PyObject, &VirtualMachine) -> PyResult<PyHash>;
|
||||
// CallFunc = GenericMethod
|
||||
pub(crate) type StringifyFunc = fn(&PyObject, &VirtualMachine) -> PyResult<PyStrRef>;
|
||||
pub(crate) type GetattroFunc = fn(&PyObject, PyStrRef, &VirtualMachine) -> PyResult;
|
||||
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,
|
||||
@@ -400,13 +404,13 @@ fn call_wrapper(zelf: &PyObject, args: FuncArgs, vm: &VirtualMachine) -> PyResul
|
||||
vm.call_special_method(zelf.to_owned(), identifier!(vm, __call__), args)
|
||||
}
|
||||
|
||||
fn getattro_wrapper(zelf: &PyObject, name: PyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn getattro_wrapper(zelf: &PyObject, name: &Py<PyStr>, vm: &VirtualMachine) -> PyResult {
|
||||
let __getattribute__ = identifier!(vm, __getattribute__);
|
||||
let __getattr__ = identifier!(vm, __getattr__);
|
||||
match vm.call_special_method(zelf.to_owned(), __getattribute__, (name.clone(),)) {
|
||||
match vm.call_special_method(zelf.to_owned(), __getattribute__, (name.to_owned(),)) {
|
||||
Ok(r) => Ok(r),
|
||||
Err(_) if zelf.class().has_attr(__getattr__) => {
|
||||
vm.call_special_method(zelf.to_owned(), __getattr__, (name,))
|
||||
vm.call_special_method(zelf.to_owned(), __getattr__, (name.to_owned(),))
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
@@ -414,11 +418,12 @@ fn getattro_wrapper(zelf: &PyObject, name: PyStrRef, vm: &VirtualMachine) -> PyR
|
||||
|
||||
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))?;
|
||||
@@ -1215,19 +1220,19 @@ impl PyComparisonOp {
|
||||
#[pyclass]
|
||||
pub trait GetAttr: PyPayload {
|
||||
#[pyslot]
|
||||
fn slot_getattro(obj: &PyObject, name: PyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn slot_getattro(obj: &PyObject, name: &Py<PyStr>, vm: &VirtualMachine) -> PyResult {
|
||||
let zelf = obj.downcast_ref().ok_or_else(|| {
|
||||
vm.new_type_error("unexpected payload for __getattribute__".to_owned())
|
||||
})?;
|
||||
Self::getattro(zelf, name, vm)
|
||||
}
|
||||
|
||||
fn getattro(zelf: &Py<Self>, name: PyStrRef, vm: &VirtualMachine) -> PyResult;
|
||||
fn getattro(zelf: &Py<Self>, name: &Py<PyStr>, vm: &VirtualMachine) -> PyResult;
|
||||
|
||||
#[inline]
|
||||
#[pymethod(magic)]
|
||||
fn getattribute(zelf: PyRef<Self>, name: PyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
Self::getattro(&zelf, name, vm)
|
||||
Self::getattro(&zelf, &name, vm)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1237,7 +1242,7 @@ pub trait SetAttr: PyPayload {
|
||||
#[inline]
|
||||
fn slot_setattro(
|
||||
obj: &PyObject,
|
||||
name: PyStrRef,
|
||||
name: &Py<PyStr>,
|
||||
value: PySetterValue,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
@@ -1249,7 +1254,7 @@ pub trait SetAttr: PyPayload {
|
||||
|
||||
fn setattro(
|
||||
zelf: &Py<Self>,
|
||||
name: PyStrRef,
|
||||
name: &Py<PyStr>,
|
||||
value: PySetterValue,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()>;
|
||||
@@ -1262,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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -102,81 +102,82 @@ impl TypeZoo {
|
||||
type_type: type_::PyType::init_manually(type_type),
|
||||
object_type: object::PyBaseObject::init_manually(object_type),
|
||||
weakref_type: weakref::PyWeak::init_manually(weakref_type),
|
||||
int_type: int::PyInt::init_bare_type(),
|
||||
int_type: int::PyInt::init_builtin_type(),
|
||||
|
||||
// types exposed as builtins
|
||||
bool_type: bool_::PyBool::init_bare_type(),
|
||||
bytearray_type: bytearray::PyByteArray::init_bare_type(),
|
||||
bytes_type: bytes::PyBytes::init_bare_type(),
|
||||
classmethod_type: classmethod::PyClassMethod::init_bare_type(),
|
||||
complex_type: complex::PyComplex::init_bare_type(),
|
||||
dict_type: dict::PyDict::init_bare_type(),
|
||||
enumerate_type: enumerate::PyEnumerate::init_bare_type(),
|
||||
float_type: float::PyFloat::init_bare_type(),
|
||||
frozenset_type: set::PyFrozenSet::init_bare_type(),
|
||||
filter_type: filter::PyFilter::init_bare_type(),
|
||||
list_type: list::PyList::init_bare_type(),
|
||||
map_type: map::PyMap::init_bare_type(),
|
||||
memoryview_type: memory::PyMemoryView::init_bare_type(),
|
||||
property_type: property::PyProperty::init_bare_type(),
|
||||
range_type: range::PyRange::init_bare_type(),
|
||||
set_type: set::PySet::init_bare_type(),
|
||||
slice_type: slice::PySlice::init_bare_type(),
|
||||
staticmethod_type: staticmethod::PyStaticMethod::init_bare_type(),
|
||||
str_type: pystr::PyStr::init_bare_type(),
|
||||
super_type: super_::PySuper::init_bare_type(),
|
||||
tuple_type: tuple::PyTuple::init_bare_type(),
|
||||
zip_type: zip::PyZip::init_bare_type(),
|
||||
bool_type: bool_::PyBool::init_builtin_type(),
|
||||
bytearray_type: bytearray::PyByteArray::init_builtin_type(),
|
||||
bytes_type: bytes::PyBytes::init_builtin_type(),
|
||||
classmethod_type: classmethod::PyClassMethod::init_builtin_type(),
|
||||
complex_type: complex::PyComplex::init_builtin_type(),
|
||||
dict_type: dict::PyDict::init_builtin_type(),
|
||||
enumerate_type: enumerate::PyEnumerate::init_builtin_type(),
|
||||
float_type: float::PyFloat::init_builtin_type(),
|
||||
frozenset_type: set::PyFrozenSet::init_builtin_type(),
|
||||
filter_type: filter::PyFilter::init_builtin_type(),
|
||||
list_type: list::PyList::init_builtin_type(),
|
||||
map_type: map::PyMap::init_builtin_type(),
|
||||
memoryview_type: memory::PyMemoryView::init_builtin_type(),
|
||||
property_type: property::PyProperty::init_builtin_type(),
|
||||
range_type: range::PyRange::init_builtin_type(),
|
||||
set_type: set::PySet::init_builtin_type(),
|
||||
slice_type: slice::PySlice::init_builtin_type(),
|
||||
staticmethod_type: staticmethod::PyStaticMethod::init_builtin_type(),
|
||||
str_type: pystr::PyStr::init_builtin_type(),
|
||||
super_type: super_::PySuper::init_builtin_type(),
|
||||
tuple_type: tuple::PyTuple::init_builtin_type(),
|
||||
zip_type: zip::PyZip::init_builtin_type(),
|
||||
|
||||
// hidden internal types. is this really need to be cached here?
|
||||
async_generator: asyncgenerator::PyAsyncGen::init_bare_type(),
|
||||
async_generator_asend: asyncgenerator::PyAsyncGenASend::init_bare_type(),
|
||||
async_generator_athrow: asyncgenerator::PyAsyncGenAThrow::init_bare_type(),
|
||||
async_generator_wrapped_value: asyncgenerator::PyAsyncGenWrappedValue::init_bare_type(),
|
||||
bound_method_type: function::PyBoundMethod::init_bare_type(),
|
||||
builtin_function_or_method_type: builtin_func::PyBuiltinFunction::init_bare_type(),
|
||||
bytearray_iterator_type: bytearray::PyByteArrayIterator::init_bare_type(),
|
||||
bytes_iterator_type: bytes::PyBytesIterator::init_bare_type(),
|
||||
callable_iterator: iter::PyCallableIterator::init_bare_type(),
|
||||
cell_type: function::PyCell::init_bare_type(),
|
||||
code_type: code::PyCode::init_bare_type(),
|
||||
coroutine_type: coroutine::PyCoroutine::init_bare_type(),
|
||||
coroutine_wrapper_type: coroutine::PyCoroutineWrapper::init_bare_type(),
|
||||
dict_keys_type: dict::PyDictKeys::init_bare_type(),
|
||||
dict_values_type: dict::PyDictValues::init_bare_type(),
|
||||
dict_items_type: dict::PyDictItems::init_bare_type(),
|
||||
dict_keyiterator_type: dict::PyDictKeyIterator::init_bare_type(),
|
||||
dict_reversekeyiterator_type: dict::PyDictReverseKeyIterator::init_bare_type(),
|
||||
dict_valueiterator_type: dict::PyDictValueIterator::init_bare_type(),
|
||||
dict_reversevalueiterator_type: dict::PyDictReverseValueIterator::init_bare_type(),
|
||||
dict_itemiterator_type: dict::PyDictItemIterator::init_bare_type(),
|
||||
dict_reverseitemiterator_type: dict::PyDictReverseItemIterator::init_bare_type(),
|
||||
ellipsis_type: slice::PyEllipsis::init_bare_type(),
|
||||
frame_type: crate::frame::Frame::init_bare_type(),
|
||||
function_type: function::PyFunction::init_bare_type(),
|
||||
generator_type: generator::PyGenerator::init_bare_type(),
|
||||
getset_type: getset::PyGetSet::init_bare_type(),
|
||||
iter_type: iter::PySequenceIterator::init_bare_type(),
|
||||
reverse_iter_type: enumerate::PyReverseSequenceIterator::init_bare_type(),
|
||||
list_iterator_type: list::PyListIterator::init_bare_type(),
|
||||
list_reverseiterator_type: list::PyListReverseIterator::init_bare_type(),
|
||||
mappingproxy_type: mappingproxy::PyMappingProxy::init_bare_type(),
|
||||
memoryviewiterator_type: memory::PyMemoryViewIterator::init_bare_type(),
|
||||
module_type: module::PyModule::init_bare_type(),
|
||||
namespace_type: namespace::PyNamespace::init_bare_type(),
|
||||
range_iterator_type: range::PyRangeIterator::init_bare_type(),
|
||||
long_range_iterator_type: range::PyLongRangeIterator::init_bare_type(),
|
||||
set_iterator_type: set::PySetIterator::init_bare_type(),
|
||||
str_iterator_type: pystr::PyStrIterator::init_bare_type(),
|
||||
traceback_type: traceback::PyTraceback::init_bare_type(),
|
||||
tuple_iterator_type: tuple::PyTupleIterator::init_bare_type(),
|
||||
weakproxy_type: weakproxy::PyWeakProxy::init_bare_type(),
|
||||
method_descriptor_type: builtin_func::PyBuiltinMethod::init_bare_type(),
|
||||
none_type: singletons::PyNone::init_bare_type(),
|
||||
not_implemented_type: singletons::PyNotImplemented::init_bare_type(),
|
||||
generic_alias_type: genericalias::PyGenericAlias::init_bare_type(),
|
||||
union_type: union_::PyUnion::init_bare_type(),
|
||||
member_descriptor_type: descriptor::MemberDescrObject::init_bare_type(),
|
||||
async_generator: asyncgenerator::PyAsyncGen::init_builtin_type(),
|
||||
async_generator_asend: asyncgenerator::PyAsyncGenASend::init_builtin_type(),
|
||||
async_generator_athrow: asyncgenerator::PyAsyncGenAThrow::init_builtin_type(),
|
||||
async_generator_wrapped_value:
|
||||
asyncgenerator::PyAsyncGenWrappedValue::init_builtin_type(),
|
||||
bound_method_type: function::PyBoundMethod::init_builtin_type(),
|
||||
builtin_function_or_method_type: builtin_func::PyBuiltinFunction::init_builtin_type(),
|
||||
bytearray_iterator_type: bytearray::PyByteArrayIterator::init_builtin_type(),
|
||||
bytes_iterator_type: bytes::PyBytesIterator::init_builtin_type(),
|
||||
callable_iterator: iter::PyCallableIterator::init_builtin_type(),
|
||||
cell_type: function::PyCell::init_builtin_type(),
|
||||
code_type: code::PyCode::init_builtin_type(),
|
||||
coroutine_type: coroutine::PyCoroutine::init_builtin_type(),
|
||||
coroutine_wrapper_type: coroutine::PyCoroutineWrapper::init_builtin_type(),
|
||||
dict_keys_type: dict::PyDictKeys::init_builtin_type(),
|
||||
dict_values_type: dict::PyDictValues::init_builtin_type(),
|
||||
dict_items_type: dict::PyDictItems::init_builtin_type(),
|
||||
dict_keyiterator_type: dict::PyDictKeyIterator::init_builtin_type(),
|
||||
dict_reversekeyiterator_type: dict::PyDictReverseKeyIterator::init_builtin_type(),
|
||||
dict_valueiterator_type: dict::PyDictValueIterator::init_builtin_type(),
|
||||
dict_reversevalueiterator_type: dict::PyDictReverseValueIterator::init_builtin_type(),
|
||||
dict_itemiterator_type: dict::PyDictItemIterator::init_builtin_type(),
|
||||
dict_reverseitemiterator_type: dict::PyDictReverseItemIterator::init_builtin_type(),
|
||||
ellipsis_type: slice::PyEllipsis::init_builtin_type(),
|
||||
frame_type: crate::frame::Frame::init_builtin_type(),
|
||||
function_type: function::PyFunction::init_builtin_type(),
|
||||
generator_type: generator::PyGenerator::init_builtin_type(),
|
||||
getset_type: getset::PyGetSet::init_builtin_type(),
|
||||
iter_type: iter::PySequenceIterator::init_builtin_type(),
|
||||
reverse_iter_type: enumerate::PyReverseSequenceIterator::init_builtin_type(),
|
||||
list_iterator_type: list::PyListIterator::init_builtin_type(),
|
||||
list_reverseiterator_type: list::PyListReverseIterator::init_builtin_type(),
|
||||
mappingproxy_type: mappingproxy::PyMappingProxy::init_builtin_type(),
|
||||
memoryviewiterator_type: memory::PyMemoryViewIterator::init_builtin_type(),
|
||||
module_type: module::PyModule::init_builtin_type(),
|
||||
namespace_type: namespace::PyNamespace::init_builtin_type(),
|
||||
range_iterator_type: range::PyRangeIterator::init_builtin_type(),
|
||||
long_range_iterator_type: range::PyLongRangeIterator::init_builtin_type(),
|
||||
set_iterator_type: set::PySetIterator::init_builtin_type(),
|
||||
str_iterator_type: pystr::PyStrIterator::init_builtin_type(),
|
||||
traceback_type: traceback::PyTraceback::init_builtin_type(),
|
||||
tuple_iterator_type: tuple::PyTupleIterator::init_builtin_type(),
|
||||
weakproxy_type: weakproxy::PyWeakProxy::init_builtin_type(),
|
||||
method_descriptor_type: builtin_func::PyBuiltinMethod::init_builtin_type(),
|
||||
none_type: singletons::PyNone::init_builtin_type(),
|
||||
not_implemented_type: singletons::PyNotImplemented::init_builtin_type(),
|
||||
generic_alias_type: genericalias::PyGenericAlias::init_builtin_type(),
|
||||
union_type: union_::PyUnion::init_builtin_type(),
|
||||
member_descriptor_type: descriptor::MemberDescrObject::init_builtin_type(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ use crate::{
|
||||
common::rc::PyRc,
|
||||
exceptions,
|
||||
function::{IntoPyGetterFunc, IntoPyNativeFunc, IntoPySetterFunc},
|
||||
intern::{Internable, MaybeInterned, StringPool},
|
||||
intern::{InternableString, MaybeInternedString, StringPool},
|
||||
object::{Py, PyObjectPayload, PyObjectRef, PyPayload, PyRef},
|
||||
types::{PyTypeFlags, PyTypeSlots, TypeZoo},
|
||||
PyResult, VirtualMachine,
|
||||
@@ -320,11 +320,14 @@ impl Context {
|
||||
context
|
||||
}
|
||||
|
||||
pub fn intern_str<S: Internable>(&self, s: S) -> &'static PyStrInterned {
|
||||
pub fn intern_str<S: InternableString>(&self, s: S) -> &'static PyStrInterned {
|
||||
unsafe { self.string_pool.intern(s, self.types.str_type.to_owned()) }
|
||||
}
|
||||
|
||||
pub fn interned_str<S: MaybeInterned + ?Sized>(&self, s: &S) -> Option<&'static PyStrInterned> {
|
||||
pub fn interned_str<S: MaybeInternedString + ?Sized>(
|
||||
&self,
|
||||
s: &S,
|
||||
) -> Option<&'static PyStrInterned> {
|
||||
self.string_pool.interned(s)
|
||||
}
|
||||
|
||||
@@ -386,6 +389,17 @@ impl Context {
|
||||
pystr::PyStr::new_ref(s, self)
|
||||
}
|
||||
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_bytes(&self, data: Vec<u8>) -> PyRef<bytes::PyBytes> {
|
||||
bytes::PyBytes::new_ref(data, self)
|
||||
@@ -427,7 +441,7 @@ impl Context {
|
||||
if let Some(module) = module {
|
||||
attrs.insert(identifier!(self, __module__), self.new_str(module).into());
|
||||
};
|
||||
PyType::new_ref(
|
||||
PyType::new_heap(
|
||||
name,
|
||||
vec![base],
|
||||
attrs,
|
||||
@@ -452,11 +466,15 @@ impl Context {
|
||||
let mut attrs = PyAttributes::default();
|
||||
attrs.insert(identifier!(self, __module__), self.new_str(module).into());
|
||||
|
||||
PyType::new_ref(
|
||||
let interned_name = self.intern_str(name);
|
||||
PyType::new_heap(
|
||||
name,
|
||||
bases,
|
||||
attrs,
|
||||
PyBaseException::make_slots(),
|
||||
PyTypeSlots {
|
||||
name: interned_name.as_str(),
|
||||
..PyBaseException::make_slots()
|
||||
},
|
||||
self.types.type_type.to_owned(),
|
||||
self,
|
||||
)
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
|
||||
use super::VirtualMachine;
|
||||
use crate::{
|
||||
builtins::{PyBaseObject, PyStrInterned, PyStrRef},
|
||||
builtins::{PyBaseObject, PyStr, PyStrInterned},
|
||||
function::IntoFuncArgs,
|
||||
object::{AsObject, PyObjectRef, PyResult},
|
||||
object::{AsObject, Py, PyObjectRef, PyResult},
|
||||
types::PyTypeFlags,
|
||||
};
|
||||
|
||||
@@ -19,14 +19,15 @@ pub enum PyMethod {
|
||||
}
|
||||
|
||||
impl PyMethod {
|
||||
pub fn get(obj: PyObjectRef, name: PyStrRef, vm: &VirtualMachine) -> PyResult<Self> {
|
||||
pub fn get(obj: PyObjectRef, name: &Py<PyStr>, vm: &VirtualMachine) -> PyResult<Self> {
|
||||
let cls = obj.class();
|
||||
let getattro = cls.mro_find_map(|cls| cls.slots.getattro.load()).unwrap();
|
||||
if getattro as usize != PyBaseObject::getattro as usize {
|
||||
return obj.get_attr(name, vm).map(Self::Attribute);
|
||||
}
|
||||
|
||||
let interned_name = vm.ctx.interned_str(&*name);
|
||||
// any correct method name is always interned already.
|
||||
let interned_name = vm.ctx.interned_str(name);
|
||||
let mut is_method = false;
|
||||
|
||||
let cls_attr = match interned_name.and_then(|name| cls.get_attr(name)) {
|
||||
@@ -54,7 +55,7 @@ impl PyMethod {
|
||||
};
|
||||
|
||||
if let Some(dict) = obj.dict() {
|
||||
if let Some(attr) = dict.get_item_opt(&*name, vm)? {
|
||||
if let Some(attr) = dict.get_item_opt(name, vm)? {
|
||||
return Ok(Self::Attribute(attr));
|
||||
}
|
||||
}
|
||||
@@ -72,14 +73,14 @@ impl PyMethod {
|
||||
None => Ok(Self::Attribute(attr)),
|
||||
}
|
||||
} else if let Some(getter) = cls.get_attr(identifier!(vm, __getattr__)) {
|
||||
getter.call((obj, name), vm).map(Self::Attribute)
|
||||
getter.call((obj, name.to_owned()), vm).map(Self::Attribute)
|
||||
} else {
|
||||
let exc = vm.new_attribute_error(format!(
|
||||
"'{}' object has no attribute '{}'",
|
||||
cls.name(),
|
||||
name
|
||||
));
|
||||
vm.set_attribute_error_context(&exc, obj.clone(), name);
|
||||
vm.set_attribute_error_context(&exc, obj.clone(), name.to_owned());
|
||||
Err(exc)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,10 @@ mod vm_ops;
|
||||
use crate::{
|
||||
builtins::{
|
||||
code::PyCode,
|
||||
pystr::IntoPyStrRef,
|
||||
pystr::AsPyStr,
|
||||
tuple::{PyTuple, PyTupleTyped},
|
||||
PyBaseExceptionRef, PyDictRef, PyInt, PyList, PyModule, PyStrInterned, PyStrRef, PyTypeRef,
|
||||
PyBaseExceptionRef, PyDictRef, PyInt, PyList, PyModule, PyStr, PyStrInterned, PyStrRef,
|
||||
PyTypeRef,
|
||||
},
|
||||
bytecode::frozen_lib::FrozenModule,
|
||||
codecs::CodecsRegistry,
|
||||
@@ -33,7 +34,7 @@ use crate::{
|
||||
scope::Scope,
|
||||
signal, stdlib,
|
||||
warn::WarningsState,
|
||||
AsObject, PyObject, PyObjectRef, PyPayload, PyRef, PyResult,
|
||||
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult,
|
||||
};
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
#[cfg(unix)]
|
||||
@@ -269,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,
|
||||
)?;
|
||||
@@ -444,7 +446,7 @@ impl VirtualMachine {
|
||||
Ref::map(frame, |f| &f.globals)
|
||||
}
|
||||
|
||||
pub fn try_class(&self, module: &str, class: &str) -> PyResult<PyTypeRef> {
|
||||
pub fn try_class(&self, module: &'static str, class: &'static str) -> PyResult<PyTypeRef> {
|
||||
let class = self
|
||||
.import(module, None, 0)?
|
||||
.get_attr(class, self)?
|
||||
@@ -453,10 +455,11 @@ impl VirtualMachine {
|
||||
Ok(class)
|
||||
}
|
||||
|
||||
pub fn class(&self, module: &str, class: &str) -> PyTypeRef {
|
||||
pub fn class(&self, module: &'static str, class: &'static str) -> PyTypeRef {
|
||||
let module = self
|
||||
.import(module, None, 0)
|
||||
.unwrap_or_else(|_| panic!("unable to import {module}"));
|
||||
|
||||
let class = module
|
||||
.get_attr(class, self)
|
||||
.unwrap_or_else(|_| panic!("module {module:?} has no class {class}"));
|
||||
@@ -464,18 +467,18 @@ impl VirtualMachine {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn import(
|
||||
pub fn import<'a>(
|
||||
&self,
|
||||
module: impl IntoPyStrRef,
|
||||
module: impl AsPyStr<'a>,
|
||||
from_list: Option<PyTupleTyped<PyStrRef>>,
|
||||
level: usize,
|
||||
) -> PyResult {
|
||||
self._import_inner(module.into_pystr_ref(self), from_list, level)
|
||||
self.import_inner(module.as_pystr(&self.ctx), from_list, level)
|
||||
}
|
||||
|
||||
fn _import_inner(
|
||||
fn import_inner(
|
||||
&self,
|
||||
module: PyStrRef,
|
||||
module: &Py<PyStr>,
|
||||
from_list: Option<PyTupleTyped<PyStrRef>>,
|
||||
level: usize,
|
||||
) -> PyResult {
|
||||
@@ -489,7 +492,7 @@ impl VirtualMachine {
|
||||
None
|
||||
} else {
|
||||
let sys_modules = self.sys_module.get_attr("modules", self)?;
|
||||
sys_modules.get_item(&*module, self).ok()
|
||||
sys_modules.get_item(module, self).ok()
|
||||
};
|
||||
|
||||
match cached_module {
|
||||
@@ -497,7 +500,7 @@ impl VirtualMachine {
|
||||
if self.is_none(&cached_module) {
|
||||
Err(self.new_import_error(
|
||||
format!("import of {module} halted; None in sys.modules"),
|
||||
module,
|
||||
module.to_owned(),
|
||||
))
|
||||
} else {
|
||||
Ok(cached_module)
|
||||
@@ -509,7 +512,7 @@ impl VirtualMachine {
|
||||
.clone()
|
||||
.get_attr(identifier!(self, __import__), self)
|
||||
.map_err(|_| {
|
||||
self.new_import_error("__import__ not found".to_owned(), module.clone())
|
||||
self.new_import_error("__import__ not found".to_owned(), module.to_owned())
|
||||
})?;
|
||||
|
||||
let (locals, globals) = if let Some(frame) = self.current_frame() {
|
||||
@@ -522,7 +525,7 @@ impl VirtualMachine {
|
||||
None => self.new_tuple(()).into(),
|
||||
};
|
||||
import_func
|
||||
.call((module, globals, locals, from_list, level), self)
|
||||
.call((module.to_owned(), globals, locals, from_list, level), self)
|
||||
.map_err(|exc| import::remove_importlib_frames(self, &exc))
|
||||
}
|
||||
}
|
||||
@@ -606,15 +609,13 @@ impl VirtualMachine {
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
pub fn get_attribute_opt<T>(
|
||||
pub fn get_attribute_opt<'a>(
|
||||
&self,
|
||||
obj: PyObjectRef,
|
||||
attr_name: T,
|
||||
) -> PyResult<Option<PyObjectRef>>
|
||||
where
|
||||
T: IntoPyStrRef,
|
||||
{
|
||||
match obj.get_attr(attr_name, self) {
|
||||
attr_name: impl AsPyStr<'a>,
|
||||
) -> PyResult<Option<PyObjectRef>> {
|
||||
let attr_name = attr_name.as_pystr(&self.ctx);
|
||||
match obj.get_attr_inner(attr_name, self) {
|
||||
Ok(attr) => Ok(Some(attr)),
|
||||
Err(e) if e.fast_isinstance(self.ctx.exceptions.attribute_error) => Ok(None),
|
||||
Err(e) => Err(e),
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use crate::{
|
||||
builtins::{
|
||||
pystr::IntoPyStrRef,
|
||||
tuple::{IntoPyTuple, PyTupleRef},
|
||||
PyBaseException, PyBaseExceptionRef, PyDictRef, PyModule, PyStrRef, PyType, PyTypeRef,
|
||||
},
|
||||
@@ -268,12 +267,10 @@ impl VirtualMachine {
|
||||
syntax_error
|
||||
}
|
||||
|
||||
pub fn new_import_error(&self, msg: String, name: impl IntoPyStrRef) -> PyBaseExceptionRef {
|
||||
pub fn new_import_error(&self, msg: String, name: PyStrRef) -> PyBaseExceptionRef {
|
||||
let import_error = self.ctx.exceptions.import_error.to_owned();
|
||||
let exc = self.new_exception_msg(import_error, msg);
|
||||
exc.as_object()
|
||||
.set_attr("name", name.into_pystr_ref(self), self)
|
||||
.unwrap();
|
||||
exc.as_object().set_attr("name", name, self).unwrap();
|
||||
exc
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use super::PyMethod;
|
||||
use crate::{
|
||||
builtins::{PyBaseExceptionRef, PyList, PyStr, PyStrInterned},
|
||||
builtins::{pystr::AsPyStr, PyBaseExceptionRef, PyList, PyStrInterned},
|
||||
function::IntoFuncArgs,
|
||||
identifier,
|
||||
object::{AsObject, PyObject, PyObjectRef, PyPayload, PyResult},
|
||||
object::{AsObject, PyObject, PyObjectRef, PyResult},
|
||||
vm::VirtualMachine,
|
||||
};
|
||||
|
||||
@@ -104,10 +104,14 @@ impl VirtualMachine {
|
||||
{
|
||||
flame_guard!(format!("call_method({:?})", method_name));
|
||||
|
||||
let name = self
|
||||
.ctx
|
||||
.interned_str(method_name)
|
||||
.map_or_else(|| PyStr::from(method_name).into_ref(self), |s| s.to_owned());
|
||||
let dynamic_name;
|
||||
let name = match self.ctx.interned_str(method_name) {
|
||||
Some(name) => name.as_pystr(&self.ctx),
|
||||
None => {
|
||||
dynamic_name = self.ctx.new_str(method_name);
|
||||
&dynamic_name
|
||||
}
|
||||
};
|
||||
PyMethod::get(obj.to_owned(), name, self)?.invoke(args, self)
|
||||
}
|
||||
|
||||
|
||||
@@ -619,7 +619,7 @@ mod _js {
|
||||
fn js_error(vm: &VirtualMachine) -> PyTypeRef {
|
||||
let ctx = &vm.ctx;
|
||||
let js_error = PyRef::leak(
|
||||
PyType::new_simple_ref("JSError", &vm.ctx.exceptions.exception_type.to_owned(), ctx)
|
||||
PyType::new_simple_heap("JSError", &vm.ctx.exceptions.exception_type.to_owned(), ctx)
|
||||
.unwrap(),
|
||||
);
|
||||
extend_class!(ctx, js_error, {
|
||||
|
||||
@@ -314,7 +314,7 @@ impl WASMVirtualMachine {
|
||||
let (key, value) = entry?;
|
||||
let key = Object::from(key).to_string();
|
||||
extend_module!(vm, py_module, {
|
||||
String::from(key) => convert::js_to_py(vm, value),
|
||||
&String::from(key) => convert::js_to_py(vm, value),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user