mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Merge pull request #4706 from youknowone/py-type
#[pyclass] impl Py<PyType>
This commit is contained in:
38 files changed
+1374
-1206
No files matched your search
@@ -61,6 +61,7 @@
|
||||
"rsplitn",
|
||||
"rustc",
|
||||
"rustfmt",
|
||||
"seekfrom",
|
||||
"splitn",
|
||||
"subsec",
|
||||
"timsort",
|
||||
|
||||
+114
-24
@@ -105,39 +105,114 @@ pub(crate) fn impl_pyimpl(attr: AttributeArgs, item: Item) -> Result<TokenStream
|
||||
Item::Impl(mut imp) => {
|
||||
extract_items_into_context(&mut context, imp.items.iter_mut());
|
||||
|
||||
let ty = &imp.self_ty;
|
||||
let (impl_ty, payload_guess) = match imp.self_ty.as_ref() {
|
||||
syn::Type::Path(syn::TypePath {
|
||||
path: syn::Path { segments, .. },
|
||||
..
|
||||
}) if segments.len() == 1 => {
|
||||
let segment = &segments[0];
|
||||
let payload_ty = if segment.ident == "Py" || segment.ident == "PyRef" {
|
||||
match &segment.arguments {
|
||||
syn::PathArguments::AngleBracketed(
|
||||
syn::AngleBracketedGenericArguments { args, .. },
|
||||
) if args.len() == 1 => {
|
||||
let arg = &args[0];
|
||||
match arg {
|
||||
syn::GenericArgument::Type(syn::Type::Path(
|
||||
syn::TypePath {
|
||||
path: syn::Path { segments, .. },
|
||||
..
|
||||
},
|
||||
)) if segments.len() == 1 => segments[0].ident.clone(),
|
||||
_ => {
|
||||
return Err(syn::Error::new_spanned(
|
||||
segment,
|
||||
"Py{Ref}<T> is expected but Py{Ref}<?> is found",
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(syn::Error::new_spanned(
|
||||
segment,
|
||||
"Py{Ref}<T> is expected but Py{Ref}? is found",
|
||||
))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if !matches!(segment.arguments, syn::PathArguments::None) {
|
||||
return Err(syn::Error::new_spanned(
|
||||
segment,
|
||||
"PyImpl can only be implemented for Py{Ref}<T> or T",
|
||||
));
|
||||
}
|
||||
segment.ident.clone()
|
||||
};
|
||||
(segment.ident.clone(), payload_ty)
|
||||
}
|
||||
_ => {
|
||||
return Err(syn::Error::new_spanned(
|
||||
imp.self_ty,
|
||||
"PyImpl can only be implemented for Py{Ref}<T> or T",
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
let ExtractedImplAttrs {
|
||||
payload: attr_payload,
|
||||
with_impl,
|
||||
flags,
|
||||
with_slots,
|
||||
} = extract_impl_attrs(attr, &Ident::new("e!(ty).to_string(), ty.span()))?;
|
||||
|
||||
} = extract_impl_attrs(attr, &impl_ty)?;
|
||||
let payload_ty = attr_payload.unwrap_or(payload_guess);
|
||||
let getset_impl = &context.getset_items;
|
||||
let member_impl = &context.member_items;
|
||||
let extend_impl = context.impl_extend_items.validate()?;
|
||||
let slots_impl = context.extend_slots_items.validate()?;
|
||||
let class_extensions = &context.class_extensions;
|
||||
quote! {
|
||||
#imp
|
||||
impl ::rustpython_vm::class::PyClassImpl for #ty {
|
||||
const TP_FLAGS: ::rustpython_vm::types::PyTypeFlags = #flags;
|
||||
|
||||
fn impl_extend_class(
|
||||
let extra_methods = iter_chain![
|
||||
parse_quote! {
|
||||
fn __extend_py_class(
|
||||
ctx: &::rustpython_vm::Context,
|
||||
class: &'static ::rustpython_vm::Py<::rustpython_vm::builtins::PyType>,
|
||||
) {
|
||||
#getset_impl
|
||||
#member_impl
|
||||
#extend_impl
|
||||
#with_impl
|
||||
#(#class_extensions)*
|
||||
}
|
||||
|
||||
fn extend_slots(slots: &mut ::rustpython_vm::types::PyTypeSlots) {
|
||||
#with_slots
|
||||
},
|
||||
parse_quote! {
|
||||
fn __extend_slots(slots: &mut ::rustpython_vm::types::PyTypeSlots) {
|
||||
#slots_impl
|
||||
}
|
||||
},
|
||||
];
|
||||
imp.items.extend(extra_methods);
|
||||
let is_main_impl = impl_ty == payload_ty;
|
||||
if is_main_impl {
|
||||
quote! {
|
||||
#imp
|
||||
impl ::rustpython_vm::class::PyClassImpl for #payload_ty {
|
||||
const TP_FLAGS: ::rustpython_vm::types::PyTypeFlags = #flags;
|
||||
|
||||
fn impl_extend_class(
|
||||
ctx: &::rustpython_vm::Context,
|
||||
class: &'static ::rustpython_vm::Py<::rustpython_vm::builtins::PyType>,
|
||||
) {
|
||||
#impl_ty::__extend_py_class(ctx, class);
|
||||
#with_impl
|
||||
}
|
||||
|
||||
fn extend_slots(slots: &mut ::rustpython_vm::types::PyTypeSlots) {
|
||||
#impl_ty::__extend_slots(slots);
|
||||
#with_slots
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
imp.into_token_stream()
|
||||
}
|
||||
}
|
||||
Item::Trait(mut trai) => {
|
||||
@@ -1163,6 +1238,7 @@ impl MemberItemMeta {
|
||||
}
|
||||
|
||||
struct ExtractedImplAttrs {
|
||||
payload: Option<Ident>,
|
||||
with_impl: TokenStream,
|
||||
with_slots: TokenStream,
|
||||
flags: TokenStream,
|
||||
@@ -1182,6 +1258,7 @@ fn extract_impl_attrs(attr: AttributeArgs, item: &Ident) -> Result<ExtractedImpl
|
||||
}
|
||||
}
|
||||
}];
|
||||
let mut payload = None;
|
||||
|
||||
for attr in attr {
|
||||
match attr {
|
||||
@@ -1191,18 +1268,19 @@ fn extract_impl_attrs(attr: AttributeArgs, item: &Ident) -> Result<ExtractedImpl
|
||||
let NestedMeta::Meta(Meta::Path(path)) = meta else {
|
||||
bail_span!(meta, "#[pyclass(with(...))] arguments should be paths")
|
||||
};
|
||||
let (extend_class, extend_slots) = if path.is_ident("PyRef") {
|
||||
// special handling for PyRef
|
||||
(
|
||||
quote!(PyRef::<Self>::impl_extend_class),
|
||||
quote!(PyRef::<Self>::extend_slots),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
quote!(<Self as #path>::__extend_py_class),
|
||||
quote!(<Self as #path>::__extend_slots),
|
||||
)
|
||||
};
|
||||
let (extend_class, extend_slots) =
|
||||
if path.is_ident("PyRef") || path.is_ident("Py") {
|
||||
// special handling for PyRef
|
||||
(
|
||||
quote!(#path::<Self>::__extend_py_class),
|
||||
quote!(#path::<Self>::__extend_slots),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
quote!(<Self as #path>::__extend_py_class),
|
||||
quote!(<Self as #path>::__extend_slots),
|
||||
)
|
||||
};
|
||||
let item_span = item.span().resolved_at(Span::call_site());
|
||||
withs.push(quote_spanned! { path.span() =>
|
||||
#extend_class(ctx, class);
|
||||
@@ -1227,11 +1305,23 @@ fn extract_impl_attrs(attr: AttributeArgs, item: &Ident) -> Result<ExtractedImpl
|
||||
bail_span!(path, "Unknown pyimpl attribute")
|
||||
}
|
||||
}
|
||||
NestedMeta::Meta(Meta::NameValue(syn::MetaNameValue { path, lit, .. })) => {
|
||||
if path.is_ident("payload") {
|
||||
if let syn::Lit::Str(lit) = lit {
|
||||
payload = Some(Ident::new(&lit.value(), lit.span()));
|
||||
} else {
|
||||
bail_span!(lit, "payload must be a string literal")
|
||||
}
|
||||
} else {
|
||||
bail_span!(path, "Unknown pyimpl attribute")
|
||||
}
|
||||
}
|
||||
attr => bail_span!(attr, "Unknown pyimpl attribute"),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(ExtractedImplAttrs {
|
||||
payload,
|
||||
with_impl: quote! {
|
||||
#(#withs)*
|
||||
},
|
||||
|
||||
@@ -86,8 +86,8 @@ python_person.name: {}",
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl TryFromBorrowedObject for PythonPerson {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult<Self> {
|
||||
impl<'a> TryFromBorrowedObject<'a> for PythonPerson {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult<Self> {
|
||||
let name = obj.get_attr("name", vm)?.try_into_value::<String>(vm)?;
|
||||
Ok(PythonPerson { name })
|
||||
}
|
||||
|
||||
+13
-18
@@ -746,7 +746,7 @@ mod array {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn append(zelf: PyRef<Self>, x: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
fn append(zelf: &Py<Self>, x: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
zelf.try_resizable(vm)?.push(x, vm)
|
||||
}
|
||||
|
||||
@@ -762,12 +762,12 @@ mod array {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn remove(zelf: PyRef<Self>, x: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
fn remove(zelf: &Py<Self>, x: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
zelf.try_resizable(vm)?.remove(x, vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn extend(zelf: PyRef<Self>, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
fn extend(zelf: &Py<Self>, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let mut w = zelf.try_resizable(vm)?;
|
||||
if zelf.is(&obj) {
|
||||
w.imul(2, vm)
|
||||
@@ -828,7 +828,7 @@ mod array {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn fromunicode(zelf: PyRef<Self>, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
fn fromunicode(zelf: &Py<Self>, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let utf8 = PyStrRef::try_from_object(vm, obj.clone()).map_err(|_| {
|
||||
vm.new_type_error(format!(
|
||||
"fromunicode() argument must be str, not {}",
|
||||
@@ -922,18 +922,13 @@ mod array {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn insert(
|
||||
zelf: PyRef<Self>,
|
||||
i: isize,
|
||||
x: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
fn insert(zelf: &Py<Self>, i: isize, x: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let mut w = zelf.try_resizable(vm)?;
|
||||
w.insert(i, x, vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn pop(zelf: PyRef<Self>, i: OptionalArg<isize>, vm: &VirtualMachine) -> PyResult {
|
||||
fn pop(zelf: &Py<Self>, i: OptionalArg<isize>, vm: &VirtualMachine) -> PyResult {
|
||||
let mut w = zelf.try_resizable(vm)?;
|
||||
if w.len() == 0 {
|
||||
Err(vm.new_index_error("pop from empty array".to_owned()))
|
||||
@@ -982,7 +977,7 @@ mod array {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn fromlist(zelf: PyRef<Self>, list: PyListRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
fn fromlist(zelf: &Py<Self>, list: PyListRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
zelf.try_resizable(vm)?.fromlist(&list, vm)
|
||||
}
|
||||
|
||||
@@ -1014,7 +1009,7 @@ mod array {
|
||||
}
|
||||
|
||||
fn _setitem(
|
||||
zelf: PyRef<Self>,
|
||||
zelf: &Py<Self>,
|
||||
needle: &PyObject,
|
||||
value: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
@@ -1052,7 +1047,7 @@ mod array {
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn setitem(
|
||||
zelf: PyRef<Self>,
|
||||
zelf: &Py<Self>,
|
||||
needle: PyObjectRef,
|
||||
value: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
@@ -1120,7 +1115,7 @@ mod array {
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<String> {
|
||||
fn repr(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
|
||||
let class = zelf.class();
|
||||
let class_name = class.name();
|
||||
if zelf.read().typecode() == 'u' {
|
||||
@@ -1167,7 +1162,7 @@ mod array {
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn reduce_ex(
|
||||
zelf: PyRef<Self>,
|
||||
zelf: &Py<Self>,
|
||||
proto: usize,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<(PyObjectRef, PyTupleRef, Option<PyDictRef>)> {
|
||||
@@ -1191,7 +1186,7 @@ mod array {
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn reduce(
|
||||
zelf: PyRef<Self>,
|
||||
zelf: &Py<Self>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<(PyObjectRef, PyTupleRef, Option<PyDictRef>)> {
|
||||
let array = zelf.read();
|
||||
@@ -1325,7 +1320,7 @@ mod array {
|
||||
ass_subscript: atomic_func!(|mapping, needle, value, vm| {
|
||||
let zelf = PyArray::mapping_downcast(mapping);
|
||||
if let Some(value) = value {
|
||||
PyArray::_setitem(zelf.to_owned(), needle, value, vm)
|
||||
PyArray::_setitem(zelf, needle, value, vm)
|
||||
} else {
|
||||
zelf._delitem(needle, vm)
|
||||
}
|
||||
|
||||
@@ -2,11 +2,9 @@ pub(crate) use decl::make_module;
|
||||
|
||||
#[pymodule(name = "faulthandler")]
|
||||
mod decl {
|
||||
use crate::vm::{
|
||||
frame::FrameRef, function::OptionalArg, stdlib::sys::PyStderr, VirtualMachine,
|
||||
};
|
||||
use crate::vm::{frame::Frame, function::OptionalArg, stdlib::sys::PyStderr, VirtualMachine};
|
||||
|
||||
fn dump_frame(frame: &FrameRef, vm: &VirtualMachine) {
|
||||
fn dump_frame(frame: &Frame, vm: &VirtualMachine) {
|
||||
let stderr = PyStderr(vm);
|
||||
writeln!(
|
||||
stderr,
|
||||
|
||||
+2
-2
@@ -72,8 +72,8 @@ mod mmap {
|
||||
Copy = 3,
|
||||
}
|
||||
|
||||
impl TryFromBorrowedObject for AccessMode {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult<Self> {
|
||||
impl<'a> TryFromBorrowedObject<'a> for AccessMode {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult<Self> {
|
||||
let i = u32::try_from_borrowed_object(vm, obj)?;
|
||||
Ok(match i {
|
||||
0 => Self::Default,
|
||||
|
||||
@@ -129,8 +129,8 @@ mod resource {
|
||||
}
|
||||
|
||||
struct Limits(libc::rlimit);
|
||||
impl TryFromBorrowedObject for Limits {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult<Self> {
|
||||
impl<'a> TryFromBorrowedObject<'a> for Limits {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult<Self> {
|
||||
let seq: Vec<libc::rlim_t> = obj.try_to_value(vm)?;
|
||||
match *seq {
|
||||
[cur, max] => Ok(Self(libc::rlimit {
|
||||
|
||||
+15
-15
@@ -883,7 +883,8 @@ mod _sqlite {
|
||||
unsafe { cursor.row_factory.swap(zelf.row_factory.to_owned()) };
|
||||
cursor
|
||||
} else {
|
||||
Cursor::new(zelf.clone(), zelf.row_factory.to_owned(), vm).into_ref(vm)
|
||||
let row_factory = zelf.row_factory.to_owned();
|
||||
Cursor::new(zelf, row_factory, vm).into_ref(vm)
|
||||
};
|
||||
Ok(cursor)
|
||||
}
|
||||
@@ -952,7 +953,8 @@ mod _sqlite {
|
||||
parameters: OptionalArg<PyObjectRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Cursor>> {
|
||||
let cursor = Cursor::new(zelf.clone(), zelf.row_factory.to_owned(), vm).into_ref(vm);
|
||||
let row_factory = zelf.row_factory.to_owned();
|
||||
let cursor = Cursor::new(zelf, row_factory, vm).into_ref(vm);
|
||||
Cursor::execute(cursor, sql, parameters, vm)
|
||||
}
|
||||
|
||||
@@ -963,7 +965,8 @@ mod _sqlite {
|
||||
seq_of_params: ArgIterable,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Cursor>> {
|
||||
let cursor = Cursor::new(zelf.clone(), zelf.row_factory.to_owned(), vm).into_ref(vm);
|
||||
let row_factory = zelf.row_factory.to_owned();
|
||||
let cursor = Cursor::new(zelf, row_factory, vm).into_ref(vm);
|
||||
Cursor::executemany(cursor, sql, seq_of_params, vm)
|
||||
}
|
||||
|
||||
@@ -973,15 +976,12 @@ mod _sqlite {
|
||||
script: PyStrRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Cursor>> {
|
||||
Cursor::executescript(
|
||||
Cursor::new(zelf.clone(), zelf.row_factory.to_owned(), vm).into_ref(vm),
|
||||
script,
|
||||
vm,
|
||||
)
|
||||
let row_factory = zelf.row_factory.to_owned();
|
||||
Cursor::executescript(Cursor::new(zelf, row_factory, vm).into_ref(vm), script, vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn backup(zelf: PyRef<Self>, args: BackupArgs, vm: &VirtualMachine) -> PyResult<()> {
|
||||
fn backup(zelf: &Py<Self>, args: BackupArgs, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let BackupArgs {
|
||||
target,
|
||||
pages,
|
||||
@@ -1550,8 +1550,8 @@ mod _sqlite {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn fetchone(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
Self::next(&zelf, vm).map(|x| match x {
|
||||
fn fetchone(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
Self::next(zelf, vm).map(|x| match x {
|
||||
PyIterReturn::Return(row) => row,
|
||||
PyIterReturn::StopIteration(_) => vm.ctx.none(),
|
||||
})
|
||||
@@ -1559,13 +1559,13 @@ mod _sqlite {
|
||||
|
||||
#[pymethod]
|
||||
fn fetchmany(
|
||||
zelf: PyRef<Self>,
|
||||
zelf: &Py<Self>,
|
||||
max_rows: OptionalArg<c_int>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<Vec<PyObjectRef>> {
|
||||
let max_rows = max_rows.unwrap_or_else(|| zelf.arraysize.load(Ordering::Relaxed));
|
||||
let mut list = vec![];
|
||||
while let PyIterReturn::Return(row) = Self::next(&zelf, vm)? {
|
||||
while let PyIterReturn::Return(row) = Self::next(zelf, vm)? {
|
||||
list.push(row);
|
||||
if list.len() as c_int >= max_rows {
|
||||
break;
|
||||
@@ -1575,9 +1575,9 @@ mod _sqlite {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn fetchall(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<Vec<PyObjectRef>> {
|
||||
fn fetchall(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<Vec<PyObjectRef>> {
|
||||
let mut list = vec![];
|
||||
while let PyIterReturn::Return(row) = Self::next(&zelf, vm)? {
|
||||
while let PyIterReturn::Return(row) = Self::next(zelf, vm)? {
|
||||
list.push(row);
|
||||
}
|
||||
Ok(list)
|
||||
|
||||
@@ -41,8 +41,8 @@ enum NormalizeForm {
|
||||
Nfkd,
|
||||
}
|
||||
|
||||
impl TryFromBorrowedObject for NormalizeForm {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult<Self> {
|
||||
impl<'a> TryFromBorrowedObject<'a> for NormalizeForm {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult<Self> {
|
||||
obj.try_value_with(
|
||||
|form: &PyStr| {
|
||||
Ok(match form.as_str() {
|
||||
|
||||
+2
-2
@@ -581,8 +581,8 @@ mod zlib {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFromBorrowedObject for Level {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult<Self> {
|
||||
impl<'a> TryFromBorrowedObject<'a> for Level {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult<Self> {
|
||||
let int: i32 = obj.try_index(vm)?.try_to_primitive(vm)?;
|
||||
Ok(Self::new(int))
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ impl PyPayload for PyAsyncGen {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(Constructor, Representable))]
|
||||
#[pyclass(with(PyRef, Constructor, Representable))]
|
||||
impl PyAsyncGen {
|
||||
pub fn as_coro(&self) -> &Coro {
|
||||
&self.inner
|
||||
@@ -49,59 +49,6 @@ impl PyAsyncGen {
|
||||
self.inner.set_name(name)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn aiter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn anext(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyAsyncGenASend {
|
||||
Self::asend(zelf, vm.ctx.none(), vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn asend(zelf: PyRef<Self>, value: PyObjectRef, _vm: &VirtualMachine) -> PyAsyncGenASend {
|
||||
PyAsyncGenASend {
|
||||
ag: zelf,
|
||||
state: AtomicCell::new(AwaitableState::Init),
|
||||
value,
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn athrow(
|
||||
zelf: PyRef<Self>,
|
||||
exc_type: PyObjectRef,
|
||||
exc_val: OptionalArg,
|
||||
exc_tb: OptionalArg,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyAsyncGenAThrow {
|
||||
PyAsyncGenAThrow {
|
||||
ag: zelf,
|
||||
aclose: false,
|
||||
state: AtomicCell::new(AwaitableState::Init),
|
||||
value: (
|
||||
exc_type,
|
||||
exc_val.unwrap_or_none(vm),
|
||||
exc_tb.unwrap_or_none(vm),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn aclose(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyAsyncGenAThrow {
|
||||
PyAsyncGenAThrow {
|
||||
ag: zelf,
|
||||
aclose: true,
|
||||
state: AtomicCell::new(AwaitableState::Init),
|
||||
value: (
|
||||
vm.ctx.exceptions.generator_exit.to_owned().into(),
|
||||
vm.ctx.none(),
|
||||
vm.ctx.none(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn ag_await(&self, _vm: &VirtualMachine) -> Option<PyObjectRef> {
|
||||
self.inner.frame().yield_from_target()
|
||||
@@ -125,6 +72,62 @@ impl PyAsyncGen {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
impl PyRef<PyAsyncGen> {
|
||||
#[pymethod(magic)]
|
||||
fn aiter(self, _vm: &VirtualMachine) -> PyRef<PyAsyncGen> {
|
||||
self
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn anext(self, vm: &VirtualMachine) -> PyAsyncGenASend {
|
||||
Self::asend(self, vm.ctx.none(), vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn asend(self, value: PyObjectRef, _vm: &VirtualMachine) -> PyAsyncGenASend {
|
||||
PyAsyncGenASend {
|
||||
ag: self,
|
||||
state: AtomicCell::new(AwaitableState::Init),
|
||||
value,
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn athrow(
|
||||
self,
|
||||
exc_type: PyObjectRef,
|
||||
exc_val: OptionalArg,
|
||||
exc_tb: OptionalArg,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyAsyncGenAThrow {
|
||||
PyAsyncGenAThrow {
|
||||
ag: self,
|
||||
aclose: false,
|
||||
state: AtomicCell::new(AwaitableState::Init),
|
||||
value: (
|
||||
exc_type,
|
||||
exc_val.unwrap_or_none(vm),
|
||||
exc_tb.unwrap_or_none(vm),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn aclose(self, vm: &VirtualMachine) -> PyAsyncGenAThrow {
|
||||
PyAsyncGenAThrow {
|
||||
ag: self,
|
||||
aclose: true,
|
||||
state: AtomicCell::new(AwaitableState::Init),
|
||||
value: (
|
||||
vm.ctx.exceptions.generator_exit.to_owned().into(),
|
||||
vm.ctx.none(),
|
||||
vm.ctx.none(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Representable for PyAsyncGen {
|
||||
#[inline]
|
||||
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
|
||||
|
||||
@@ -19,8 +19,8 @@ impl ToPyObject for bool {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFromBorrowedObject for bool {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult<bool> {
|
||||
impl<'a> TryFromBorrowedObject<'a> for bool {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult<bool> {
|
||||
if obj.fast_isinstance(vm.ctx.types.int_type) {
|
||||
Ok(get_value(obj))
|
||||
} else {
|
||||
|
||||
+210
-225
@@ -48,31 +48,6 @@ pub struct PyByteArray {
|
||||
|
||||
pub type PyByteArrayRef = PyRef<PyByteArray>;
|
||||
|
||||
impl PyByteArray {
|
||||
pub fn new_ref(data: Vec<u8>, ctx: &Context) -> PyRef<Self> {
|
||||
PyRef::new_ref(Self::from(data), ctx.types.bytearray_type.to_owned(), None)
|
||||
}
|
||||
|
||||
fn from_inner(inner: PyBytesInner) -> Self {
|
||||
PyByteArray {
|
||||
inner: PyRwLock::new(inner),
|
||||
exports: AtomicUsize::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn borrow_buf(&self) -> PyMappedRwLockReadGuard<'_, [u8]> {
|
||||
PyRwLockReadGuard::map(self.inner.read(), |inner| &*inner.elements)
|
||||
}
|
||||
|
||||
pub fn borrow_buf_mut(&self) -> PyMappedRwLockWriteGuard<'_, Vec<u8>> {
|
||||
PyRwLockWriteGuard::map(self.inner.write(), |inner| &mut inner.elements)
|
||||
}
|
||||
|
||||
fn repeat(&self, value: isize, vm: &VirtualMachine) -> PyResult<Self> {
|
||||
self.inner().mul(value, vm).map(|x| x.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PyBytesInner> for PyByteArray {
|
||||
fn from(inner: PyBytesInner) -> Self {
|
||||
Self::from_inner(inner)
|
||||
@@ -97,9 +72,107 @@ pub(crate) fn init(context: &Context) {
|
||||
PyByteArrayIterator::extend_class(context, context.types.bytearray_iterator_type);
|
||||
}
|
||||
|
||||
impl PyByteArray {
|
||||
pub fn new_ref(data: Vec<u8>, ctx: &Context) -> PyRef<Self> {
|
||||
PyRef::new_ref(Self::from(data), ctx.types.bytearray_type.to_owned(), None)
|
||||
}
|
||||
|
||||
fn from_inner(inner: PyBytesInner) -> Self {
|
||||
PyByteArray {
|
||||
inner: PyRwLock::new(inner),
|
||||
exports: AtomicUsize::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn borrow_buf(&self) -> PyMappedRwLockReadGuard<'_, [u8]> {
|
||||
PyRwLockReadGuard::map(self.inner.read(), |inner| &*inner.elements)
|
||||
}
|
||||
|
||||
pub fn borrow_buf_mut(&self) -> PyMappedRwLockWriteGuard<'_, Vec<u8>> {
|
||||
PyRwLockWriteGuard::map(self.inner.write(), |inner| &mut inner.elements)
|
||||
}
|
||||
|
||||
fn repeat(&self, value: isize, vm: &VirtualMachine) -> PyResult<Self> {
|
||||
self.inner().mul(value, vm).map(|x| x.into())
|
||||
}
|
||||
|
||||
fn _setitem_by_index(&self, i: isize, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let value = value_from_object(vm, &value)?;
|
||||
self.borrow_buf_mut().setitem_by_index(vm, i, value)
|
||||
}
|
||||
|
||||
fn _setitem(
|
||||
zelf: &Py<Self>,
|
||||
needle: &PyObject,
|
||||
value: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
match SequenceIndex::try_from_borrowed_object(vm, needle, "bytearray")? {
|
||||
SequenceIndex::Int(i) => zelf._setitem_by_index(i, value, vm),
|
||||
SequenceIndex::Slice(slice) => {
|
||||
let items = if zelf.is(&value) {
|
||||
zelf.borrow_buf().to_vec()
|
||||
} else {
|
||||
bytes_from_object(vm, &value)?
|
||||
};
|
||||
if let Some(mut w) = zelf.try_resizable_opt() {
|
||||
w.elements.setitem_by_slice(vm, slice, &items)
|
||||
} else {
|
||||
zelf.borrow_buf_mut()
|
||||
.setitem_by_slice_no_resize(vm, slice, &items)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn _getitem(&self, needle: &PyObject, vm: &VirtualMachine) -> PyResult {
|
||||
match SequenceIndex::try_from_borrowed_object(vm, needle, "bytearray")? {
|
||||
SequenceIndex::Int(i) => self
|
||||
.borrow_buf()
|
||||
.getitem_by_index(vm, i)
|
||||
.map(|x| vm.ctx.new_int(x).into()),
|
||||
SequenceIndex::Slice(slice) => self
|
||||
.borrow_buf()
|
||||
.getitem_by_slice(vm, slice)
|
||||
.map(|x| Self::new_ref(x, &vm.ctx).into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn _delitem(&self, needle: &PyObject, vm: &VirtualMachine) -> PyResult<()> {
|
||||
match SequenceIndex::try_from_borrowed_object(vm, needle, "bytearray")? {
|
||||
SequenceIndex::Int(i) => self.try_resizable(vm)?.elements.delitem_by_index(vm, i),
|
||||
SequenceIndex::Slice(slice) => {
|
||||
// TODO: delete 0 elements don't need resizable
|
||||
self.try_resizable(vm)?.elements.delitem_by_slice(vm, slice)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn irepeat(zelf: &Py<Self>, n: isize, vm: &VirtualMachine) -> PyResult<()> {
|
||||
if n == 1 {
|
||||
return Ok(());
|
||||
}
|
||||
let mut w = match zelf.try_resizable(vm) {
|
||||
Ok(w) => w,
|
||||
Err(err) => {
|
||||
return if zelf.borrow_buf().is_empty() {
|
||||
// We can multiple an empty vector by any integer
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err)
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
w.imul(n, vm)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(
|
||||
flags(BASETYPE),
|
||||
with(
|
||||
Py,
|
||||
PyRef,
|
||||
Constructor,
|
||||
Initializer,
|
||||
Comparable,
|
||||
@@ -156,45 +229,6 @@ impl PyByteArray {
|
||||
self.inner().contains(needle, vm)
|
||||
}
|
||||
|
||||
fn _setitem_by_index(&self, i: isize, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let value = value_from_object(vm, &value)?;
|
||||
self.borrow_buf_mut().setitem_by_index(vm, i, value)
|
||||
}
|
||||
|
||||
fn _setitem(
|
||||
zelf: PyRef<Self>,
|
||||
needle: &PyObject,
|
||||
value: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
match SequenceIndex::try_from_borrowed_object(vm, needle, "bytearray")? {
|
||||
SequenceIndex::Int(i) => zelf._setitem_by_index(i, value, vm),
|
||||
SequenceIndex::Slice(slice) => {
|
||||
let items = if zelf.is(&value) {
|
||||
zelf.borrow_buf().to_vec()
|
||||
} else {
|
||||
bytes_from_object(vm, &value)?
|
||||
};
|
||||
if let Some(mut w) = zelf.try_resizable_opt() {
|
||||
w.elements.setitem_by_slice(vm, slice, &items)
|
||||
} else {
|
||||
zelf.borrow_buf_mut()
|
||||
.setitem_by_slice_no_resize(vm, slice, &items)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn setitem(
|
||||
zelf: PyRef<Self>,
|
||||
needle: PyObjectRef,
|
||||
value: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
Self::_setitem(zelf, &needle, value, vm)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn iadd(zelf: PyRef<Self>, other: ArgBytesLike, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
zelf.try_resizable(vm)?
|
||||
@@ -203,34 +237,11 @@ impl PyByteArray {
|
||||
Ok(zelf)
|
||||
}
|
||||
|
||||
fn _getitem(&self, needle: &PyObject, vm: &VirtualMachine) -> PyResult {
|
||||
match SequenceIndex::try_from_borrowed_object(vm, needle, "bytearray")? {
|
||||
SequenceIndex::Int(i) => self
|
||||
.borrow_buf()
|
||||
.getitem_by_index(vm, i)
|
||||
.map(|x| vm.ctx.new_int(x).into()),
|
||||
SequenceIndex::Slice(slice) => self
|
||||
.borrow_buf()
|
||||
.getitem_by_slice(vm, slice)
|
||||
.map(|x| Self::new_ref(x, &vm.ctx).into()),
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn getitem(&self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
self._getitem(&needle, vm)
|
||||
}
|
||||
|
||||
pub fn _delitem(&self, needle: &PyObject, vm: &VirtualMachine) -> PyResult<()> {
|
||||
match SequenceIndex::try_from_borrowed_object(vm, needle, "bytearray")? {
|
||||
SequenceIndex::Int(i) => self.try_resizable(vm)?.elements.delitem_by_index(vm, i),
|
||||
SequenceIndex::Slice(slice) => {
|
||||
// TODO: delete 0 elements don't need resizable
|
||||
self.try_resizable(vm)?.elements.delitem_by_slice(vm, slice)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
pub fn delitem(&self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
self._delitem(&needle, vm)
|
||||
@@ -241,78 +252,6 @@ impl PyByteArray {
|
||||
PyBytesInner::maketrans(from, to, vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn pop(zelf: PyRef<Self>, index: OptionalArg<isize>, vm: &VirtualMachine) -> PyResult<u8> {
|
||||
let elements = &mut zelf.try_resizable(vm)?.elements;
|
||||
let index = elements
|
||||
.wrap_index(index.unwrap_or(-1))
|
||||
.ok_or_else(|| vm.new_index_error("index out of range".to_owned()))?;
|
||||
Ok(elements.remove(index))
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn insert(
|
||||
zelf: PyRef<Self>,
|
||||
index: isize,
|
||||
object: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
let value = value_from_object(vm, &object)?;
|
||||
let elements = &mut zelf.try_resizable(vm)?.elements;
|
||||
let index = elements.saturate_index(index);
|
||||
elements.insert(index, value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn append(zelf: PyRef<Self>, object: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let value = value_from_object(vm, &object)?;
|
||||
zelf.try_resizable(vm)?.elements.push(value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn remove(zelf: PyRef<Self>, object: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let value = value_from_object(vm, &object)?;
|
||||
let elements = &mut zelf.try_resizable(vm)?.elements;
|
||||
if let Some(index) = elements.find_byte(value) {
|
||||
elements.remove(index);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(vm.new_value_error("value not found in bytearray".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn extend(zelf: PyRef<Self>, object: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
if zelf.is(&object) {
|
||||
Self::irepeat(&zelf, 2, vm)
|
||||
} else {
|
||||
let items = bytes_from_object(vm, &object)?;
|
||||
zelf.try_resizable(vm)?.elements.extend(items);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn irepeat(zelf: &Py<Self>, n: isize, vm: &VirtualMachine) -> PyResult<()> {
|
||||
if n == 1 {
|
||||
return Ok(());
|
||||
}
|
||||
let mut w = match zelf.try_resizable(vm) {
|
||||
Ok(w) => w,
|
||||
Err(err) => {
|
||||
return if zelf.borrow_buf().is_empty() {
|
||||
// We can multiple an empty vector by any integer
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err)
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
w.imul(n, vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn isalnum(&self) -> bool {
|
||||
self.inner().isalnum()
|
||||
@@ -503,59 +442,11 @@ impl PyByteArray {
|
||||
self.inner().strip(chars).into()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn lstrip(
|
||||
zelf: PyRef<Self>,
|
||||
chars: OptionalOption<PyBytesInner>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyRef<Self> {
|
||||
let inner = zelf.inner();
|
||||
let stripped = inner.lstrip(chars);
|
||||
let elements = &inner.elements;
|
||||
if stripped == elements {
|
||||
drop(inner);
|
||||
zelf
|
||||
} else {
|
||||
vm.new_pyref(PyByteArray::from(stripped.to_vec()))
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn rstrip(
|
||||
zelf: PyRef<Self>,
|
||||
chars: OptionalOption<PyBytesInner>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyRef<Self> {
|
||||
let inner = zelf.inner();
|
||||
let stripped = inner.rstrip(chars);
|
||||
let elements = &inner.elements;
|
||||
if stripped == elements {
|
||||
drop(inner);
|
||||
zelf
|
||||
} else {
|
||||
vm.new_pyref(PyByteArray::from(stripped.to_vec()))
|
||||
}
|
||||
}
|
||||
|
||||
/// removeprefix($self, prefix, /)
|
||||
///
|
||||
///
|
||||
/// Return a bytearray object with the given prefix string removed if present.
|
||||
///
|
||||
/// If the bytearray starts with the prefix string, return string[len(prefix):]
|
||||
/// Otherwise, return a copy of the original bytearray.
|
||||
#[pymethod]
|
||||
fn removeprefix(&self, prefix: PyBytesInner) -> Self {
|
||||
self.inner().removeprefix(prefix).into()
|
||||
}
|
||||
|
||||
/// removesuffix(self, prefix, /)
|
||||
///
|
||||
///
|
||||
/// Return a bytearray object with the given suffix string removed if present.
|
||||
///
|
||||
/// If the bytearray ends with the suffix string, return string[:len(suffix)]
|
||||
/// Otherwise, return a copy of the original bytearray.
|
||||
#[pymethod]
|
||||
fn removesuffix(&self, suffix: PyBytesInner) -> Self {
|
||||
self.inner().removesuffix(suffix).to_vec().into()
|
||||
@@ -638,12 +529,6 @@ impl PyByteArray {
|
||||
Ok(self.inner().replace(old, new, count, vm)?.into())
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn clear(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<()> {
|
||||
zelf.try_resizable(vm)?.elements.clear();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn copy(&self) -> Self {
|
||||
self.borrow_buf().to_vec().into()
|
||||
@@ -681,35 +566,135 @@ impl PyByteArray {
|
||||
fn reverse(&self) {
|
||||
self.borrow_buf_mut().reverse();
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
impl Py<PyByteArray> {
|
||||
#[pymethod(magic)]
|
||||
fn setitem(
|
||||
&self,
|
||||
needle: PyObjectRef,
|
||||
value: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
PyByteArray::_setitem(self, &needle, value, vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn decode(zelf: PyRef<Self>, args: DecodeArgs, vm: &VirtualMachine) -> PyResult<PyStrRef> {
|
||||
bytes_decode(zelf.into(), args, vm)
|
||||
fn pop(&self, index: OptionalArg<isize>, vm: &VirtualMachine) -> PyResult<u8> {
|
||||
let elements = &mut self.try_resizable(vm)?.elements;
|
||||
let index = elements
|
||||
.wrap_index(index.unwrap_or(-1))
|
||||
.ok_or_else(|| vm.new_index_error("index out of range".to_owned()))?;
|
||||
Ok(elements.remove(index))
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn insert(&self, index: isize, object: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let value = value_from_object(vm, &object)?;
|
||||
let elements = &mut self.try_resizable(vm)?.elements;
|
||||
let index = elements.saturate_index(index);
|
||||
elements.insert(index, value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn append(&self, object: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let value = value_from_object(vm, &object)?;
|
||||
self.try_resizable(vm)?.elements.push(value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn remove(&self, object: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let value = value_from_object(vm, &object)?;
|
||||
let elements = &mut self.try_resizable(vm)?.elements;
|
||||
let index = elements
|
||||
.find_byte(value)
|
||||
.ok_or_else(|| vm.new_value_error("value not found in bytearray".to_owned()))?;
|
||||
elements.remove(index);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn extend(&self, object: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
if self.is(&object) {
|
||||
PyByteArray::irepeat(self, 2, vm)
|
||||
} else {
|
||||
let items = bytes_from_object(vm, &object)?;
|
||||
self.try_resizable(vm)?.elements.extend(items);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn clear(&self, vm: &VirtualMachine) -> PyResult<()> {
|
||||
self.try_resizable(vm)?.elements.clear();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn reduce_ex(
|
||||
zelf: PyRef<Self>,
|
||||
&self,
|
||||
_proto: usize,
|
||||
vm: &VirtualMachine,
|
||||
) -> (PyTypeRef, PyTupleRef, Option<PyDictRef>) {
|
||||
Self::reduce(zelf, vm)
|
||||
Self::reduce(self, vm)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn reduce(
|
||||
zelf: PyRef<Self>,
|
||||
vm: &VirtualMachine,
|
||||
) -> (PyTypeRef, PyTupleRef, Option<PyDictRef>) {
|
||||
let bytes = PyBytes::from(zelf.borrow_buf().to_vec()).to_pyobject(vm);
|
||||
fn reduce(&self, vm: &VirtualMachine) -> (PyTypeRef, PyTupleRef, Option<PyDictRef>) {
|
||||
let bytes = PyBytes::from(self.borrow_buf().to_vec()).to_pyobject(vm);
|
||||
(
|
||||
zelf.class().to_owned(),
|
||||
self.class().to_owned(),
|
||||
PyTuple::new_ref(vec![bytes], &vm.ctx),
|
||||
zelf.as_object().dict(),
|
||||
self.as_object().dict(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
impl PyRef<PyByteArray> {
|
||||
#[pymethod]
|
||||
fn lstrip(
|
||||
self,
|
||||
chars: OptionalOption<PyBytesInner>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyRef<PyByteArray> {
|
||||
let inner = self.inner();
|
||||
let stripped = inner.lstrip(chars);
|
||||
let elements = &inner.elements;
|
||||
if stripped == elements {
|
||||
drop(inner);
|
||||
self
|
||||
} else {
|
||||
vm.new_pyref(PyByteArray::from(stripped.to_vec()))
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn rstrip(
|
||||
self,
|
||||
chars: OptionalOption<PyBytesInner>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyRef<PyByteArray> {
|
||||
let inner = self.inner();
|
||||
let stripped = inner.rstrip(chars);
|
||||
let elements = &inner.elements;
|
||||
if stripped == elements {
|
||||
drop(inner);
|
||||
self
|
||||
} else {
|
||||
vm.new_pyref(PyByteArray::from(stripped.to_vec()))
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn decode(self, args: DecodeArgs, vm: &VirtualMachine) -> PyResult<PyStrRef> {
|
||||
bytes_decode(self.into(), args, vm)
|
||||
}
|
||||
}
|
||||
|
||||
impl Constructor for PyByteArray {
|
||||
type Args = FuncArgs;
|
||||
|
||||
@@ -796,7 +781,7 @@ impl AsMapping for PyByteArray {
|
||||
ass_subscript: atomic_func!(|mapping, needle, value, vm| {
|
||||
let zelf = PyByteArray::mapping_downcast(mapping);
|
||||
if let Some(value) = value {
|
||||
PyByteArray::setitem(zelf.to_owned(), needle.to_owned(), value, vm)
|
||||
Py::setitem(zelf, needle.to_owned(), value, vm)
|
||||
} else {
|
||||
zelf.delitem(needle.to_owned(), vm)
|
||||
}
|
||||
|
||||
+89
-105
@@ -101,23 +101,38 @@ impl PyBytes {
|
||||
PyRef::new_ref(Self::from(data), ctx.types.bytes_type.to_owned(), None)
|
||||
}
|
||||
|
||||
fn repeat(zelf: PyRef<Self>, count: isize, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
if count == 1 && zelf.class().is(vm.ctx.types.bytes_type) {
|
||||
fn _getitem(&self, needle: &PyObject, vm: &VirtualMachine) -> PyResult {
|
||||
match SequenceIndex::try_from_borrowed_object(vm, needle, "byte")? {
|
||||
SequenceIndex::Int(i) => self
|
||||
.getitem_by_index(vm, i)
|
||||
.map(|x| vm.ctx.new_int(x).into()),
|
||||
SequenceIndex::Slice(slice) => self
|
||||
.getitem_by_slice(vm, slice)
|
||||
.map(|x| vm.ctx.new_bytes(x).into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PyRef<PyBytes> {
|
||||
fn repeat(self, count: isize, vm: &VirtualMachine) -> PyResult<PyRef<PyBytes>> {
|
||||
if count == 1 && self.class().is(vm.ctx.types.bytes_type) {
|
||||
// Special case: when some `bytes` is multiplied by `1`,
|
||||
// nothing really happens, we need to return an object itself
|
||||
// with the same `id()` to be compatible with CPython.
|
||||
// This only works for `bytes` itself, not its subclasses.
|
||||
return Ok(zelf);
|
||||
return Ok(self);
|
||||
}
|
||||
zelf.inner
|
||||
self.inner
|
||||
.mul(count, vm)
|
||||
.map(|x| Self::from(x).into_ref(vm))
|
||||
.map(|x| PyBytes::from(x).into_ref(vm))
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(
|
||||
flags(BASETYPE),
|
||||
with(
|
||||
Py,
|
||||
PyRef,
|
||||
AsMapping,
|
||||
AsSequence,
|
||||
Hashable,
|
||||
@@ -146,15 +161,6 @@ impl PyBytes {
|
||||
self.inner.as_bytes()
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn bytes(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyRef<Self> {
|
||||
if zelf.is(vm.ctx.types.bytes_type) {
|
||||
zelf
|
||||
} else {
|
||||
PyBytes::from(zelf.inner.clone()).into_ref(vm)
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn sizeof(&self) -> usize {
|
||||
size_of::<Self>() + self.len() * size_of::<u8>()
|
||||
@@ -179,17 +185,6 @@ impl PyBytes {
|
||||
PyBytesInner::maketrans(from, to, vm)
|
||||
}
|
||||
|
||||
fn _getitem(&self, needle: &PyObject, vm: &VirtualMachine) -> PyResult {
|
||||
match SequenceIndex::try_from_borrowed_object(vm, needle, "byte")? {
|
||||
SequenceIndex::Int(i) => self
|
||||
.getitem_by_index(vm, i)
|
||||
.map(|x| vm.ctx.new_int(x).into()),
|
||||
SequenceIndex::Slice(slice) => self
|
||||
.getitem_by_slice(vm, slice)
|
||||
.map(|x| vm.ctx.new_bytes(x).into()),
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn getitem(&self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
self._getitem(&needle, vm)
|
||||
@@ -371,53 +366,11 @@ impl PyBytes {
|
||||
self.inner.strip(chars).into()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn lstrip(
|
||||
zelf: PyRef<Self>,
|
||||
chars: OptionalOption<PyBytesInner>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyRef<Self> {
|
||||
let stripped = zelf.inner.lstrip(chars);
|
||||
if stripped == zelf.as_bytes() {
|
||||
zelf
|
||||
} else {
|
||||
vm.ctx.new_bytes(stripped.to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn rstrip(
|
||||
zelf: PyRef<Self>,
|
||||
chars: OptionalOption<PyBytesInner>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyRef<Self> {
|
||||
let stripped = zelf.inner.rstrip(chars);
|
||||
if stripped == zelf.as_bytes() {
|
||||
zelf
|
||||
} else {
|
||||
vm.ctx.new_bytes(stripped.to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
/// removeprefix($self, prefix, /)
|
||||
///
|
||||
///
|
||||
/// Return a bytes object with the given prefix string removed if present.
|
||||
///
|
||||
/// If the bytes starts with the prefix string, return string[len(prefix):]
|
||||
/// Otherwise, return a copy of the original bytes.
|
||||
#[pymethod]
|
||||
fn removeprefix(&self, prefix: PyBytesInner) -> Self {
|
||||
self.inner.removeprefix(prefix).into()
|
||||
}
|
||||
|
||||
/// removesuffix(self, prefix, /)
|
||||
///
|
||||
///
|
||||
/// Return a bytes object with the given suffix string removed if present.
|
||||
///
|
||||
/// If the bytes ends with the suffix string, return string[:len(suffix)]
|
||||
/// Otherwise, return a copy of the original bytes.
|
||||
#[pymethod]
|
||||
fn removesuffix(&self, suffix: PyBytesInner) -> Self {
|
||||
self.inner.removesuffix(suffix).into()
|
||||
@@ -508,7 +461,7 @@ impl PyBytes {
|
||||
#[pymethod(name = "__rmul__")]
|
||||
#[pymethod(magic)]
|
||||
fn mul(zelf: PyRef<Self>, value: ArgIndex, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
Self::repeat(zelf, value.try_to_primitive(vm)?, vm)
|
||||
zelf.repeat(value.try_to_primitive(vm)?, vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__mod__")]
|
||||
@@ -522,6 +475,66 @@ impl PyBytes {
|
||||
vm.ctx.not_implemented()
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn getnewargs(&self, vm: &VirtualMachine) -> PyTupleRef {
|
||||
let param: Vec<PyObjectRef> = self.elements().map(|x| x.to_pyobject(vm)).collect();
|
||||
PyTuple::new_ref(param, &vm.ctx)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
impl Py<PyBytes> {
|
||||
#[pymethod(magic)]
|
||||
fn reduce_ex(
|
||||
&self,
|
||||
_proto: usize,
|
||||
vm: &VirtualMachine,
|
||||
) -> (PyTypeRef, PyTupleRef, Option<PyDictRef>) {
|
||||
Self::reduce(self, vm)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn reduce(&self, vm: &VirtualMachine) -> (PyTypeRef, PyTupleRef, Option<PyDictRef>) {
|
||||
let bytes = PyBytes::from(self.to_vec()).to_pyobject(vm);
|
||||
(
|
||||
self.class().to_owned(),
|
||||
PyTuple::new_ref(vec![bytes], &vm.ctx),
|
||||
self.as_object().dict(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
impl PyRef<PyBytes> {
|
||||
#[pymethod(magic)]
|
||||
fn bytes(self, vm: &VirtualMachine) -> PyRef<PyBytes> {
|
||||
if self.is(vm.ctx.types.bytes_type) {
|
||||
self
|
||||
} else {
|
||||
PyBytes::from(self.inner.clone()).into_ref(vm)
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn lstrip(self, chars: OptionalOption<PyBytesInner>, vm: &VirtualMachine) -> PyRef<PyBytes> {
|
||||
let stripped = self.inner.lstrip(chars);
|
||||
if stripped == self.as_bytes() {
|
||||
self
|
||||
} else {
|
||||
vm.ctx.new_bytes(stripped.to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn rstrip(self, chars: OptionalOption<PyBytesInner>, vm: &VirtualMachine) -> PyRef<PyBytes> {
|
||||
let stripped = self.inner.rstrip(chars);
|
||||
if stripped == self.as_bytes() {
|
||||
self
|
||||
} else {
|
||||
vm.ctx.new_bytes(stripped.to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a string decoded from the given bytes.
|
||||
/// Default encoding is 'utf-8'.
|
||||
/// Default errors is 'strict', meaning that encoding errors raise a UnicodeError.
|
||||
@@ -530,36 +543,8 @@ impl PyBytes {
|
||||
/// see https://docs.python.org/3/library/codecs.html#standard-encodings
|
||||
/// currently, only 'utf-8' and 'ascii' emplemented
|
||||
#[pymethod]
|
||||
fn decode(zelf: PyRef<Self>, args: DecodeArgs, vm: &VirtualMachine) -> PyResult<PyStrRef> {
|
||||
bytes_decode(zelf.into(), args, vm)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn getnewargs(&self, vm: &VirtualMachine) -> PyTupleRef {
|
||||
let param: Vec<PyObjectRef> = self.elements().map(|x| x.to_pyobject(vm)).collect();
|
||||
PyTuple::new_ref(param, &vm.ctx)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn reduce_ex(
|
||||
zelf: PyRef<Self>,
|
||||
_proto: usize,
|
||||
vm: &VirtualMachine,
|
||||
) -> (PyTypeRef, PyTupleRef, Option<PyDictRef>) {
|
||||
Self::reduce(zelf, vm)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn reduce(
|
||||
zelf: PyRef<Self>,
|
||||
vm: &VirtualMachine,
|
||||
) -> (PyTypeRef, PyTupleRef, Option<PyDictRef>) {
|
||||
let bytes = PyBytes::from(zelf.to_vec()).to_pyobject(vm);
|
||||
(
|
||||
zelf.class().to_owned(),
|
||||
PyTuple::new_ref(vec![bytes], &vm.ctx),
|
||||
zelf.as_object().dict(),
|
||||
)
|
||||
fn decode(self, args: DecodeArgs, vm: &VirtualMachine) -> PyResult<PyStrRef> {
|
||||
bytes_decode(self.into(), args, vm)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -605,11 +590,10 @@ impl AsSequence for PyBytes {
|
||||
.map(|x| vm.ctx.new_bytes(x).into())
|
||||
}),
|
||||
repeat: atomic_func!(|seq, n, vm| {
|
||||
if let Ok(zelf) = seq.obj.to_owned().downcast::<PyBytes>() {
|
||||
PyBytes::repeat(zelf, n, vm).to_pyresult(vm)
|
||||
} else {
|
||||
Err(vm.new_type_error("bad argument type for built-in operation".to_owned()))
|
||||
}
|
||||
let zelf = seq.obj.to_owned().downcast::<PyBytes>().map_err(|_| {
|
||||
vm.new_type_error("bad argument type for built-in operation".to_owned())
|
||||
})?;
|
||||
zelf.repeat(n, vm).to_pyresult(vm)
|
||||
}),
|
||||
item: atomic_func!(|seq, i, vm| {
|
||||
PyBytes::sequence_downcast(seq)
|
||||
@@ -742,8 +726,8 @@ impl IterNext for PyBytesIterator {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFromBorrowedObject for PyBytes {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult<Self> {
|
||||
impl<'a> TryFromBorrowedObject<'a> for PyBytes {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult<Self> {
|
||||
PyBytesInner::try_from_borrowed_object(vm, obj).map(|x| x.into())
|
||||
}
|
||||
}
|
||||
+34
-22
@@ -10,7 +10,7 @@ use crate::{
|
||||
convert::ToPyObject,
|
||||
function::{FuncArgs, OptionalArg},
|
||||
types::Representable,
|
||||
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
|
||||
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyResult, VirtualMachine,
|
||||
};
|
||||
use num_traits::Zero;
|
||||
use std::{borrow::Borrow, fmt, ops::Deref};
|
||||
@@ -216,9 +216,6 @@ impl PyPayload for PyCode {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(PyRef, Representable))]
|
||||
impl PyCode {}
|
||||
|
||||
impl Representable for PyCode {
|
||||
#[inline]
|
||||
fn repr_str(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> {
|
||||
@@ -233,35 +230,35 @@ impl Representable for PyCode {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
impl PyRef<PyCode> {
|
||||
#[pyclass(with(Py))]
|
||||
impl PyCode {
|
||||
#[pyslot]
|
||||
fn slot_new(_cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Err(vm.new_type_error("Cannot directly create code object".to_owned()))
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn co_posonlyargcount(self) -> usize {
|
||||
fn co_posonlyargcount(&self) -> usize {
|
||||
self.code.posonlyarg_count as usize
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn co_argcount(self) -> usize {
|
||||
fn co_argcount(&self) -> usize {
|
||||
self.code.arg_count as usize
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn co_stacksize(self) -> u32 {
|
||||
fn co_stacksize(&self) -> u32 {
|
||||
self.code.max_stackdepth
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
pub fn co_filename(self) -> PyStrRef {
|
||||
pub fn co_filename(&self) -> PyStrRef {
|
||||
self.code.source_path.to_owned()
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
pub fn co_cellvars(self, vm: &VirtualMachine) -> PyTupleRef {
|
||||
pub fn co_cellvars(&self, vm: &VirtualMachine) -> PyTupleRef {
|
||||
let cellvars = self
|
||||
.code
|
||||
.cellvars
|
||||
@@ -273,33 +270,33 @@ impl PyRef<PyCode> {
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn co_nlocals(self) -> usize {
|
||||
fn co_nlocals(&self) -> usize {
|
||||
self.varnames.len()
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn co_firstlineno(self) -> usize {
|
||||
fn co_firstlineno(&self) -> usize {
|
||||
self.code.first_line_number as usize
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn co_kwonlyargcount(self) -> usize {
|
||||
fn co_kwonlyargcount(&self) -> usize {
|
||||
self.code.kwonlyarg_count as usize
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn co_consts(self, vm: &VirtualMachine) -> PyTupleRef {
|
||||
fn co_consts(&self, vm: &VirtualMachine) -> PyTupleRef {
|
||||
let consts = self.code.constants.iter().map(|x| x.0.clone()).collect();
|
||||
vm.ctx.new_tuple(consts)
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn co_name(self) -> PyStrRef {
|
||||
fn co_name(&self) -> PyStrRef {
|
||||
self.code.obj_name.to_owned()
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn co_names(self, vm: &VirtualMachine) -> PyTupleRef {
|
||||
fn co_names(&self, vm: &VirtualMachine) -> PyTupleRef {
|
||||
let names = self
|
||||
.code
|
||||
.names
|
||||
@@ -311,18 +308,18 @@ impl PyRef<PyCode> {
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn co_flags(self) -> u16 {
|
||||
fn co_flags(&self) -> u16 {
|
||||
self.code.flags.bits()
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
pub fn co_varnames(self, vm: &VirtualMachine) -> PyTupleRef {
|
||||
pub fn co_varnames(&self, vm: &VirtualMachine) -> PyTupleRef {
|
||||
let varnames = self.code.varnames.iter().map(|s| s.to_object()).collect();
|
||||
vm.ctx.new_tuple(varnames)
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
pub fn co_freevars(self, vm: &VirtualMachine) -> PyTupleRef {
|
||||
pub fn co_freevars(&self, vm: &VirtualMachine) -> PyTupleRef {
|
||||
let names = self
|
||||
.code
|
||||
.freevars
|
||||
@@ -334,7 +331,7 @@ impl PyRef<PyCode> {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
pub fn replace(self, args: ReplaceArgs, vm: &VirtualMachine) -> PyResult<PyCode> {
|
||||
pub fn replace(&self, args: ReplaceArgs, vm: &VirtualMachine) -> PyResult<PyCode> {
|
||||
let posonlyarg_count = match args.co_posonlyargcount {
|
||||
OptionalArg::Present(posonlyarg_count) => posonlyarg_count,
|
||||
OptionalArg::Missing => self.code.posonlyarg_count,
|
||||
@@ -421,6 +418,21 @@ impl PyRef<PyCode> {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
impl Py<PyCode> {
|
||||
#[pymethod(magic)]
|
||||
fn repr(&self) -> String {
|
||||
let code = &self.code;
|
||||
format!(
|
||||
"<code object {} at {:#x} file {:?}, line {}>",
|
||||
code.obj_name,
|
||||
self.get_id(),
|
||||
code.source_path.as_str(),
|
||||
code.first_line_number
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PyCode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
(**self).fmt(f)
|
||||
@@ -440,5 +452,5 @@ impl ToPyObject for bytecode::CodeObject {
|
||||
}
|
||||
|
||||
pub fn init(ctx: &Context) {
|
||||
PyRef::<PyCode>::extend_class(ctx, ctx.types.code_type);
|
||||
PyCode::extend_class(ctx, ctx.types.code_type);
|
||||
}
|
||||
@@ -45,13 +45,13 @@ impl PyCoroutine {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn send(zelf: PyRef<Self>, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
|
||||
fn send(zelf: &Py<Self>, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
|
||||
zelf.inner.send(zelf.as_object(), value, vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn throw(
|
||||
zelf: PyRef<Self>,
|
||||
zelf: &Py<Self>,
|
||||
exc_type: PyObjectRef,
|
||||
exc_val: OptionalArg,
|
||||
exc_tb: OptionalArg,
|
||||
@@ -67,7 +67,7 @@ impl PyCoroutine {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn close(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<()> {
|
||||
fn close(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<()> {
|
||||
zelf.inner.close(zelf.as_object(), vm)
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ impl Representable for PyCoroutine {
|
||||
impl IterNextIterable for PyCoroutine {}
|
||||
impl IterNext for PyCoroutine {
|
||||
fn next(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
|
||||
Self::send(zelf.to_owned(), vm.ctx.none(), vm)
|
||||
Self::send(zelf, vm.ctx.none(), vm)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,8 +131,8 @@ impl PyPayload for PyCoroutineWrapper {
|
||||
#[pyclass(with(IterNext))]
|
||||
impl PyCoroutineWrapper {
|
||||
#[pymethod]
|
||||
fn send(zelf: PyRef<Self>, val: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
|
||||
PyCoroutine::send(zelf.coro.clone(), val, vm)
|
||||
fn send(&self, val: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
|
||||
PyCoroutine::send(&self.coro, val, vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
@@ -143,14 +143,14 @@ impl PyCoroutineWrapper {
|
||||
exc_tb: OptionalArg,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyIterReturn> {
|
||||
PyCoroutine::throw(self.coro.clone(), exc_type, exc_val, exc_tb, vm)
|
||||
PyCoroutine::throw(&self.coro, exc_type, exc_val, exc_tb, vm)
|
||||
}
|
||||
}
|
||||
|
||||
impl IterNextIterable for PyCoroutineWrapper {}
|
||||
impl IterNext for PyCoroutineWrapper {
|
||||
fn next(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
|
||||
Self::send(zelf.to_owned(), vm.ctx.none(), vm)
|
||||
Self::send(zelf, vm.ctx.none(), vm)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::{
|
||||
class::PyClassImpl,
|
||||
function::PySetterValue,
|
||||
types::{Constructor, GetDescriptor, Representable, Unconstructible},
|
||||
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
|
||||
AsObject, Context, Py, PyObjectRef, PyPayload, PyResult, VirtualMachine,
|
||||
};
|
||||
use rustpython_common::lock::PyRwLock;
|
||||
|
||||
@@ -103,8 +103,8 @@ fn calculate_qualname(descr: &DescrObject, vm: &VirtualMachine) -> PyResult<Opti
|
||||
#[pyclass(with(GetDescriptor, Constructor, Representable), flags(BASETYPE))]
|
||||
impl MemberDescrObject {
|
||||
#[pygetset(magic)]
|
||||
fn doc(zelf: PyRef<Self>) -> Option<String> {
|
||||
zelf.member.doc.to_owned()
|
||||
fn doc(&self) -> Option<String> {
|
||||
self.member.doc.to_owned()
|
||||
}
|
||||
|
||||
#[pygetset(magic)]
|
||||
|
||||
+39
-31
@@ -203,6 +203,8 @@ impl PyDict {
|
||||
#[allow(clippy::len_without_is_empty)]
|
||||
#[pyclass(
|
||||
with(
|
||||
Py,
|
||||
PyRef,
|
||||
Constructor,
|
||||
Initializer,
|
||||
AsMapping,
|
||||
@@ -270,32 +272,11 @@ impl PyDict {
|
||||
self.entries.clear()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn keys(zelf: PyRef<Self>) -> PyDictKeys {
|
||||
PyDictKeys::new(zelf)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn values(zelf: PyRef<Self>) -> PyDictValues {
|
||||
PyDictValues::new(zelf)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn items(zelf: PyRef<Self>) -> PyDictItems {
|
||||
PyDictItems::new(zelf)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn setitem(&self, key: PyObjectRef, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
self.inner_setitem(&*key, value, vm)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
#[cfg_attr(feature = "flame-it", flame("PyDictRef"))]
|
||||
fn getitem(zelf: PyRef<Self>, key: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
zelf.inner_getitem(&*key, vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn get(
|
||||
&self,
|
||||
@@ -396,17 +377,44 @@ impl PyDict {
|
||||
Ok((key, value))
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn reversed(zelf: PyRef<Self>) -> PyDictReverseKeyIterator {
|
||||
PyDictReverseKeyIterator::new(zelf)
|
||||
}
|
||||
|
||||
#[pyclassmethod(magic)]
|
||||
fn class_getitem(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
|
||||
PyGenericAlias::new(cls, args, vm)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
impl Py<PyDict> {
|
||||
#[pymethod(magic)]
|
||||
#[cfg_attr(feature = "flame-it", flame("PyDictRef"))]
|
||||
fn getitem(&self, key: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
self.inner_getitem(&*key, vm)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
impl PyRef<PyDict> {
|
||||
#[pymethod]
|
||||
fn keys(self) -> PyDictKeys {
|
||||
PyDictKeys::new(self)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn values(self) -> PyDictValues {
|
||||
PyDictValues::new(self)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn items(self) -> PyDictItems {
|
||||
PyDictItems::new(self)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn reversed(self) -> PyDictReverseKeyIterator {
|
||||
PyDictReverseKeyIterator::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Constructor for PyDict {
|
||||
type Args = FuncArgs;
|
||||
|
||||
@@ -847,9 +855,9 @@ macro_rules! dict_view {
|
||||
|
||||
#[allow(clippy::redundant_closure_call)]
|
||||
#[pymethod(magic)]
|
||||
fn reduce(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyTupleRef {
|
||||
fn reduce(&self, vm: &VirtualMachine) -> PyTupleRef {
|
||||
let iter = builtins_iter(vm).to_owned();
|
||||
let internal = zelf.internal.lock();
|
||||
let internal = self.internal.lock();
|
||||
let entries = match &internal.status {
|
||||
IterStatus::Active(dict) => dict
|
||||
.into_iter()
|
||||
@@ -917,9 +925,9 @@ macro_rules! dict_view {
|
||||
|
||||
#[allow(clippy::redundant_closure_call)]
|
||||
#[pymethod(magic)]
|
||||
fn reduce(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyTupleRef {
|
||||
fn reduce(&self, vm: &VirtualMachine) -> PyTupleRef {
|
||||
let iter = builtins_reversed(vm).to_owned();
|
||||
let internal = zelf.internal.lock();
|
||||
let internal = self.internal.lock();
|
||||
// TODO: entries must be reversed too
|
||||
let entries = match &internal.status {
|
||||
IterStatus::Active(dict) => dict
|
||||
@@ -1240,7 +1248,7 @@ impl PyDictItems {
|
||||
return Ok(false);
|
||||
}
|
||||
let value = needle.fast_getitem(1);
|
||||
let found = PyDict::getitem(zelf.dict().clone(), key, vm)?;
|
||||
let found = zelf.dict().getitem(key, vm)?;
|
||||
vm.identical_or_equal(&found, &value)
|
||||
}
|
||||
#[pygetset]
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::{
|
||||
function::OptionalArg,
|
||||
protocol::{PyIter, PyIterReturn},
|
||||
types::{Constructor, IterNext, IterNextIterable},
|
||||
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
|
||||
AsObject, Context, Py, PyObjectRef, PyPayload, PyResult, VirtualMachine,
|
||||
};
|
||||
use num_bigint::BigInt;
|
||||
use num_traits::Zero;
|
||||
@@ -51,17 +51,21 @@ impl Constructor for PyEnumerate {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(IterNext, Constructor), flags(BASETYPE))]
|
||||
#[pyclass(with(Py, IterNext, Constructor), flags(BASETYPE))]
|
||||
impl PyEnumerate {
|
||||
#[pyclassmethod(magic)]
|
||||
fn class_getitem(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
|
||||
PyGenericAlias::new(cls, args, vm)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
impl Py<PyEnumerate> {
|
||||
#[pymethod(magic)]
|
||||
fn reduce(zelf: PyRef<Self>) -> (PyTypeRef, (PyIter, BigInt)) {
|
||||
fn reduce(&self) -> (PyTypeRef, (PyIter, BigInt)) {
|
||||
(
|
||||
zelf.class().to_owned(),
|
||||
(zelf.iterator.clone(), zelf.counter.read().clone()),
|
||||
self.class().to_owned(),
|
||||
(self.iterator.clone(), self.counter.read().clone()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+29
-29
@@ -13,12 +13,9 @@ use crate::{
|
||||
use num_traits::Zero;
|
||||
|
||||
pub fn init(context: &Context) {
|
||||
FrameRef::extend_class(context, context.types.frame_type);
|
||||
Frame::extend_class(context, context.types.frame_type);
|
||||
}
|
||||
|
||||
#[pyclass(with(Constructor, PyRef, Representable))]
|
||||
impl Frame {}
|
||||
|
||||
impl Unconstructible for Frame {}
|
||||
|
||||
impl Representable for Frame {
|
||||
@@ -34,61 +31,46 @@ impl Representable for Frame {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
impl FrameRef {
|
||||
#[pyclass(with(Constructor, Py))]
|
||||
impl Frame {
|
||||
#[pymethod]
|
||||
fn clear(self) {
|
||||
fn clear(&self) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn f_globals(self) -> PyDictRef {
|
||||
fn f_globals(&self) -> PyDictRef {
|
||||
self.globals.clone()
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn f_locals(self, vm: &VirtualMachine) -> PyResult {
|
||||
fn f_locals(&self, vm: &VirtualMachine) -> PyResult {
|
||||
self.locals(vm).map(Into::into)
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
pub fn f_code(self) -> PyRef<PyCode> {
|
||||
pub fn f_code(&self) -> PyRef<PyCode> {
|
||||
self.code.clone()
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
pub fn f_back(self, vm: &VirtualMachine) -> Option<Self> {
|
||||
// TODO: actually store f_back inside Frame struct
|
||||
|
||||
// get the frame in the frame stack that appears before this one.
|
||||
// won't work if this frame isn't in the frame stack, hence the todo above
|
||||
vm.frames
|
||||
.borrow()
|
||||
.iter()
|
||||
.rev()
|
||||
.skip_while(|p| !p.is(&self))
|
||||
.nth(1)
|
||||
.cloned()
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn f_lasti(self) -> u32 {
|
||||
fn f_lasti(&self) -> u32 {
|
||||
self.lasti()
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
pub fn f_lineno(self) -> usize {
|
||||
pub fn f_lineno(&self) -> usize {
|
||||
self.current_location().row()
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn f_trace(self) -> PyObjectRef {
|
||||
fn f_trace(&self) -> PyObjectRef {
|
||||
let boxed = self.trace.lock();
|
||||
boxed.clone()
|
||||
}
|
||||
|
||||
#[pygetset(setter)]
|
||||
fn set_f_trace(self, value: PySetterValue, vm: &VirtualMachine) {
|
||||
fn set_f_trace(&self, value: PySetterValue, vm: &VirtualMachine) {
|
||||
let mut storage = self.trace.lock();
|
||||
*storage = value.unwrap_or_none(vm);
|
||||
}
|
||||
@@ -126,3 +108,21 @@ impl FrameRef {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
impl Py<Frame> {
|
||||
#[pygetset]
|
||||
pub fn f_back(&self, vm: &VirtualMachine) -> Option<PyRef<Frame>> {
|
||||
// TODO: actually store f_back inside Frame struct
|
||||
|
||||
// get the frame in the frame stack that appears before this one.
|
||||
// won't work if this frame isn't in the frame stack, hence the todo above
|
||||
vm.frames
|
||||
.borrow()
|
||||
.iter()
|
||||
.rev()
|
||||
.skip_while(|p| !p.is(self.as_object()))
|
||||
.nth(1)
|
||||
.cloned()
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ impl PyPayload for PyGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(Constructor, IterNext))]
|
||||
#[pyclass(with(Py, Constructor, IterNext))]
|
||||
impl PyGenerator {
|
||||
pub fn as_coro(&self) -> &Coro {
|
||||
&self.inner
|
||||
@@ -47,33 +47,6 @@ impl PyGenerator {
|
||||
self.inner.set_name(name)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn send(zelf: PyRef<Self>, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
|
||||
zelf.inner.send(zelf.as_object(), value, vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn throw(
|
||||
zelf: PyRef<Self>,
|
||||
exc_type: PyObjectRef,
|
||||
exc_val: OptionalArg,
|
||||
exc_tb: OptionalArg,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyIterReturn> {
|
||||
zelf.inner.throw(
|
||||
zelf.as_object(),
|
||||
exc_type,
|
||||
exc_val.unwrap_or_none(vm),
|
||||
exc_tb.unwrap_or_none(vm),
|
||||
vm,
|
||||
)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn close(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<()> {
|
||||
zelf.inner.close(zelf.as_object(), vm)
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn gi_frame(&self, _vm: &VirtualMachine) -> FrameRef {
|
||||
self.inner.frame()
|
||||
@@ -92,6 +65,36 @@ impl PyGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
impl Py<PyGenerator> {
|
||||
#[pymethod]
|
||||
fn send(&self, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
|
||||
self.inner.send(self.as_object(), value, vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn throw(
|
||||
&self,
|
||||
exc_type: PyObjectRef,
|
||||
exc_val: OptionalArg,
|
||||
exc_tb: OptionalArg,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyIterReturn> {
|
||||
self.inner.throw(
|
||||
self.as_object(),
|
||||
exc_type,
|
||||
exc_val.unwrap_or_none(vm),
|
||||
exc_tb.unwrap_or_none(vm),
|
||||
vm,
|
||||
)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn close(&self, vm: &VirtualMachine) -> PyResult<()> {
|
||||
self.inner.close(self.as_object(), vm)
|
||||
}
|
||||
}
|
||||
|
||||
impl Unconstructible for PyGenerator {}
|
||||
|
||||
impl Representable for PyGenerator {
|
||||
@@ -104,7 +107,7 @@ impl Representable for PyGenerator {
|
||||
impl IterNextIterable for PyGenerator {}
|
||||
impl IterNext for PyGenerator {
|
||||
fn next(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
|
||||
Self::send(zelf.to_owned(), vm.ctx.none(), vm)
|
||||
zelf.send(vm.ctx.none(), vm)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ impl PyGenericAlias {
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn reduce(zelf: PyRef<Self>, vm: &VirtualMachine) -> (PyTypeRef, (PyTypeRef, PyTupleRef)) {
|
||||
fn reduce(zelf: &Py<Self>, vm: &VirtualMachine) -> (PyTypeRef, (PyTypeRef, PyTupleRef)) {
|
||||
(
|
||||
vm.ctx.types.generic_alias_type.to_owned(),
|
||||
(zelf.origin.clone(), zelf.args.clone()),
|
||||
|
||||
@@ -72,8 +72,8 @@ impl_into_pyobject_int!(isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 BigI
|
||||
|
||||
macro_rules! impl_try_from_object_int {
|
||||
($(($t:ty, $to_prim:ident),)*) => {$(
|
||||
impl TryFromBorrowedObject for $t {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult<Self> {
|
||||
impl<'a> TryFromBorrowedObject<'a> for $t {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult<Self> {
|
||||
obj.try_value_with(|int: &PyInt| {
|
||||
int.try_to_primitive(vm)
|
||||
}, vm)
|
||||
|
||||
+419
-412
@@ -68,16 +68,6 @@ impl Constructor for PyMemoryView {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(
|
||||
Hashable,
|
||||
Comparable,
|
||||
AsBuffer,
|
||||
AsMapping,
|
||||
AsSequence,
|
||||
Constructor,
|
||||
Iterable,
|
||||
Representable
|
||||
))]
|
||||
impl PyMemoryView {
|
||||
fn parse_format(format: &str, vm: &VirtualMachine) -> PyResult<FormatSpec> {
|
||||
FormatSpec::parse(format.as_bytes(), vm)
|
||||
@@ -143,13 +133,6 @@ impl PyMemoryView {
|
||||
zelf
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
pub fn release(&self) {
|
||||
if self.released.compare_exchange(false, true).is_ok() {
|
||||
self.buffer.release();
|
||||
}
|
||||
}
|
||||
|
||||
fn try_not_released(&self, vm: &VirtualMachine) -> PyResult<()> {
|
||||
if self.released.load() {
|
||||
Err(vm.new_value_error("operation forbidden on released memoryview object".to_owned()))
|
||||
@@ -158,100 +141,6 @@ impl PyMemoryView {
|
||||
}
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn obj(&self, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
|
||||
self.try_not_released(vm).map(|_| self.buffer.obj.clone())
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn nbytes(&self, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
self.try_not_released(vm).map(|_| self.desc.len)
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn readonly(&self, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
self.try_not_released(vm).map(|_| self.desc.readonly)
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn itemsize(&self, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
self.try_not_released(vm).map(|_| self.desc.itemsize)
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn ndim(&self, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
self.try_not_released(vm).map(|_| self.desc.ndim())
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn shape(&self, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
|
||||
self.try_not_released(vm)?;
|
||||
Ok(vm.ctx.new_tuple(
|
||||
self.desc
|
||||
.dim_desc
|
||||
.iter()
|
||||
.map(|(shape, _, _)| shape.to_pyobject(vm))
|
||||
.collect(),
|
||||
))
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn strides(&self, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
|
||||
self.try_not_released(vm)?;
|
||||
Ok(vm.ctx.new_tuple(
|
||||
self.desc
|
||||
.dim_desc
|
||||
.iter()
|
||||
.map(|(_, stride, _)| stride.to_pyobject(vm))
|
||||
.collect(),
|
||||
))
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn suboffsets(&self, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
|
||||
self.try_not_released(vm)?;
|
||||
Ok(vm.ctx.new_tuple(
|
||||
self.desc
|
||||
.dim_desc
|
||||
.iter()
|
||||
.map(|(_, _, suboffset)| suboffset.to_pyobject(vm))
|
||||
.collect(),
|
||||
))
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn format(&self, vm: &VirtualMachine) -> PyResult<PyStr> {
|
||||
self.try_not_released(vm)
|
||||
.map(|_| PyStr::from(self.desc.format.clone()))
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn contiguous(&self, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
self.try_not_released(vm).map(|_| self.desc.is_contiguous())
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn c_contiguous(&self, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
self.try_not_released(vm).map(|_| self.desc.is_contiguous())
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn f_contiguous(&self, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
// TODO: fortain order
|
||||
self.try_not_released(vm)
|
||||
.map(|_| self.desc.ndim() <= 1 && self.desc.is_contiguous())
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn enter(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
zelf.try_not_released(vm).map(|_| zelf)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn exit(&self, _args: FuncArgs) {
|
||||
self.release();
|
||||
}
|
||||
|
||||
fn getitem_by_idx(&self, i: isize, vm: &VirtualMachine) -> PyResult {
|
||||
if self.desc.ndim() != 1 {
|
||||
return Err(vm.new_not_implemented_error(
|
||||
@@ -281,29 +170,6 @@ impl PyMemoryView {
|
||||
format_unpack(&self.format_spec, &bytes[pos..pos + self.desc.itemsize], vm)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn getitem(zelf: PyRef<Self>, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
zelf.try_not_released(vm)?;
|
||||
if zelf.desc.ndim() == 0 {
|
||||
// 0-d memoryview can be referenced using mv[...] or mv[()] only
|
||||
if needle.is(&vm.ctx.ellipsis) {
|
||||
return Ok(zelf.into());
|
||||
}
|
||||
if let Some(tuple) = needle.payload::<PyTuple>() {
|
||||
if tuple.is_empty() {
|
||||
return zelf.unpack_single(0, vm);
|
||||
}
|
||||
}
|
||||
return Err(vm.new_type_error("invalid indexing of 0-dim memory".to_owned()));
|
||||
}
|
||||
|
||||
match SubscriptNeedle::try_from_object(vm, needle)? {
|
||||
SubscriptNeedle::Index(i) => zelf.getitem_by_idx(i, vm),
|
||||
SubscriptNeedle::Slice(slice) => zelf.getitem_by_slice(&slice, vm),
|
||||
SubscriptNeedle::MultiIndex(indices) => zelf.getitem_by_multi_idx(&indices, vm),
|
||||
}
|
||||
}
|
||||
|
||||
fn setitem_by_idx(&self, i: isize, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
if self.desc.ndim() != 1 {
|
||||
return Err(vm.new_not_implemented_error("sub-views are not implemented".to_owned()));
|
||||
@@ -317,60 +183,6 @@ impl PyMemoryView {
|
||||
self.pack_single(pos, value, vm)
|
||||
}
|
||||
|
||||
fn setitem_by_slice(
|
||||
zelf: PyRef<Self>,
|
||||
slice: &PySlice,
|
||||
src: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
if zelf.desc.ndim() != 1 {
|
||||
return Err(vm.new_not_implemented_error("sub-view are not implemented".to_owned()));
|
||||
}
|
||||
|
||||
let mut dest = zelf.new_view();
|
||||
dest.init_slice(slice, 0, vm)?;
|
||||
dest.init_len();
|
||||
|
||||
if zelf.is(&src) {
|
||||
return if !is_equiv_structure(&zelf.desc, &dest.desc) {
|
||||
Err(vm.new_value_error(
|
||||
"memoryview assignment: lvalue and rvalue have different structures".to_owned(),
|
||||
))
|
||||
} else {
|
||||
// assign self[:] to self
|
||||
Ok(())
|
||||
};
|
||||
};
|
||||
|
||||
let src = if let Some(src) = src.downcast_ref::<PyMemoryView>() {
|
||||
if zelf.buffer.obj.is(&src.buffer.obj) {
|
||||
src.to_contiguous(vm)
|
||||
} else {
|
||||
AsBuffer::as_buffer(src, vm)?
|
||||
}
|
||||
} else {
|
||||
PyBuffer::try_from_object(vm, src)?
|
||||
};
|
||||
|
||||
if !is_equiv_structure(&src.desc, &dest.desc) {
|
||||
return Err(vm.new_value_error(
|
||||
"memoryview assignment: lvalue and rvalue have different structures".to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
let mut bytes_mut = dest.buffer.obj_bytes_mut();
|
||||
let src_bytes = src.obj_bytes();
|
||||
dest.desc.zip_eq(&src.desc, true, |a_range, b_range| {
|
||||
let a_range = (a_range.start + dest.start as isize) as usize
|
||||
..(a_range.end + dest.start as isize) as usize;
|
||||
let b_range = b_range.start as usize..b_range.end as usize;
|
||||
bytes_mut[a_range].copy_from_slice(&src_bytes[b_range]);
|
||||
false
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn setitem_by_multi_idx(
|
||||
&self,
|
||||
indexes: &[isize],
|
||||
@@ -381,47 +193,6 @@ impl PyMemoryView {
|
||||
self.pack_single(pos, value, vm)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn delitem(&self, _needle: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
if self.desc.readonly {
|
||||
return Err(vm.new_type_error("cannot modify read-only memory".to_owned()));
|
||||
}
|
||||
Err(vm.new_type_error("cannot delete memory".to_owned()))
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn setitem(
|
||||
zelf: PyRef<Self>,
|
||||
needle: PyObjectRef,
|
||||
value: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
zelf.try_not_released(vm)?;
|
||||
if zelf.desc.readonly {
|
||||
return Err(vm.new_type_error("cannot modify read-only memory".to_owned()));
|
||||
}
|
||||
if value.is(&vm.ctx.none) {
|
||||
return Err(vm.new_type_error("cannot delete memory".to_owned()));
|
||||
}
|
||||
|
||||
if zelf.desc.ndim() == 0 {
|
||||
// TODO: merge branches when we got conditional if let
|
||||
if needle.is(&vm.ctx.ellipsis) {
|
||||
return zelf.pack_single(0, value, vm);
|
||||
} else if let Some(tuple) = needle.payload::<PyTuple>() {
|
||||
if tuple.is_empty() {
|
||||
return zelf.pack_single(0, value, vm);
|
||||
}
|
||||
}
|
||||
return Err(vm.new_type_error("invalid indexing of 0-dim memory".to_owned()));
|
||||
}
|
||||
match SubscriptNeedle::try_from_object(vm, needle)? {
|
||||
SubscriptNeedle::Index(i) => zelf.setitem_by_idx(i, value, vm),
|
||||
SubscriptNeedle::Slice(slice) => Self::setitem_by_slice(zelf, &slice, value, vm),
|
||||
SubscriptNeedle::MultiIndex(indices) => zelf.setitem_by_multi_idx(&indices, value, vm),
|
||||
}
|
||||
}
|
||||
|
||||
fn pack_single(&self, pos: usize, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let mut bytes = self.buffer.obj_bytes_mut();
|
||||
// TODO: Optimize
|
||||
@@ -522,26 +293,6 @@ impl PyMemoryView {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// return the length of the first dimension
|
||||
#[pymethod(magic)]
|
||||
fn len(&self, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
self.try_not_released(vm)?;
|
||||
Ok(if self.desc.ndim() == 0 {
|
||||
1
|
||||
} else {
|
||||
// shape for dim[0]
|
||||
self.desc.dim_desc[0].0
|
||||
})
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn tobytes(&self, vm: &VirtualMachine) -> PyResult<PyBytesRef> {
|
||||
self.try_not_released(vm)?;
|
||||
let mut v = vec![];
|
||||
self.append_to(&mut v);
|
||||
Ok(PyBytes::from(v).into_ref(vm))
|
||||
}
|
||||
|
||||
fn _to_list(
|
||||
&self,
|
||||
bytes: &[u8],
|
||||
@@ -572,6 +323,389 @@ impl PyMemoryView {
|
||||
Ok(vm.ctx.new_list(v))
|
||||
}
|
||||
|
||||
fn eq(zelf: &Py<Self>, other: &PyObject, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
if zelf.is(other) {
|
||||
return Ok(true);
|
||||
}
|
||||
if zelf.released.load() {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
if let Some(other) = other.payload::<Self>() {
|
||||
if other.released.load() {
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
|
||||
let other = match PyBuffer::try_from_borrowed_object(vm, other) {
|
||||
Ok(buf) => buf,
|
||||
Err(_) => return Ok(false),
|
||||
};
|
||||
|
||||
if !is_equiv_shape(&zelf.desc, &other.desc) {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let a_itemsize = zelf.desc.itemsize;
|
||||
let b_itemsize = other.desc.itemsize;
|
||||
let a_format_spec = &zelf.format_spec;
|
||||
let b_format_spec = &Self::parse_format(&other.desc.format, vm)?;
|
||||
|
||||
if zelf.desc.ndim() == 0 {
|
||||
let a_val = format_unpack(a_format_spec, &zelf.buffer.obj_bytes()[..a_itemsize], vm)?;
|
||||
let b_val = format_unpack(b_format_spec, &other.obj_bytes()[..b_itemsize], vm)?;
|
||||
return vm.bool_eq(&a_val, &b_val);
|
||||
}
|
||||
|
||||
// TODO: optimize cmp by format
|
||||
let mut ret = Ok(true);
|
||||
let a_bytes = zelf.buffer.obj_bytes();
|
||||
let b_bytes = other.obj_bytes();
|
||||
zelf.desc.zip_eq(&other.desc, false, |a_range, b_range| {
|
||||
let a_range = (a_range.start + zelf.start as isize) as usize
|
||||
..(a_range.end + zelf.start as isize) as usize;
|
||||
let b_range = b_range.start as usize..b_range.end as usize;
|
||||
let a_val = match format_unpack(a_format_spec, &a_bytes[a_range], vm) {
|
||||
Ok(val) => val,
|
||||
Err(e) => {
|
||||
ret = Err(e);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
let b_val = match format_unpack(b_format_spec, &b_bytes[b_range], vm) {
|
||||
Ok(val) => val,
|
||||
Err(e) => {
|
||||
ret = Err(e);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
ret = vm.bool_eq(&a_val, &b_val);
|
||||
if let Ok(b) = ret {
|
||||
!b
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
ret
|
||||
}
|
||||
|
||||
fn obj_bytes(&self) -> BorrowedValue<[u8]> {
|
||||
if self.desc.is_contiguous() {
|
||||
BorrowedValue::map(self.buffer.obj_bytes(), |x| {
|
||||
&x[self.start..self.start + self.desc.len]
|
||||
})
|
||||
} else {
|
||||
BorrowedValue::map(self.buffer.obj_bytes(), |x| &x[self.start..])
|
||||
}
|
||||
}
|
||||
|
||||
fn obj_bytes_mut(&self) -> BorrowedValueMut<[u8]> {
|
||||
if self.desc.is_contiguous() {
|
||||
BorrowedValueMut::map(self.buffer.obj_bytes_mut(), |x| {
|
||||
&mut x[self.start..self.start + self.desc.len]
|
||||
})
|
||||
} else {
|
||||
BorrowedValueMut::map(self.buffer.obj_bytes_mut(), |x| &mut x[self.start..])
|
||||
}
|
||||
}
|
||||
|
||||
fn as_contiguous(&self) -> Option<BorrowedValue<[u8]>> {
|
||||
self.desc.is_contiguous().then(|| {
|
||||
BorrowedValue::map(self.buffer.obj_bytes(), |x| {
|
||||
&x[self.start..self.start + self.desc.len]
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn _as_contiguous_mut(&self) -> Option<BorrowedValueMut<[u8]>> {
|
||||
self.desc.is_contiguous().then(|| {
|
||||
BorrowedValueMut::map(self.buffer.obj_bytes_mut(), |x| {
|
||||
&mut x[self.start..self.start + self.desc.len]
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn append_to(&self, buf: &mut Vec<u8>) {
|
||||
if let Some(bytes) = self.as_contiguous() {
|
||||
buf.extend_from_slice(&bytes);
|
||||
} else {
|
||||
buf.reserve(self.desc.len);
|
||||
let bytes = &*self.buffer.obj_bytes();
|
||||
self.desc.for_each_segment(true, |range| {
|
||||
let start = (range.start + self.start as isize) as usize;
|
||||
let end = (range.end + self.start as isize) as usize;
|
||||
buf.extend_from_slice(&bytes[start..end]);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn contiguous_or_collect<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
|
||||
let borrowed;
|
||||
let mut collected;
|
||||
let v = if let Some(bytes) = self.as_contiguous() {
|
||||
borrowed = bytes;
|
||||
&*borrowed
|
||||
} else {
|
||||
collected = vec![];
|
||||
self.append_to(&mut collected);
|
||||
&collected
|
||||
};
|
||||
f(v)
|
||||
}
|
||||
|
||||
/// clone data from memoryview
|
||||
/// keep the shape, convert to contiguous
|
||||
pub fn to_contiguous(&self, vm: &VirtualMachine) -> PyBuffer {
|
||||
let mut data = vec![];
|
||||
self.append_to(&mut data);
|
||||
|
||||
if self.desc.ndim() == 0 {
|
||||
return VecBuffer::from(data)
|
||||
.into_ref(vm)
|
||||
.into_pybuffer_with_descriptor(self.desc.clone());
|
||||
}
|
||||
|
||||
let mut dim_desc = self.desc.dim_desc.clone();
|
||||
dim_desc.last_mut().unwrap().1 = self.desc.itemsize as isize;
|
||||
dim_desc.last_mut().unwrap().2 = 0;
|
||||
for i in (0..dim_desc.len() - 1).rev() {
|
||||
dim_desc[i].1 = dim_desc[i + 1].1 * dim_desc[i + 1].0 as isize;
|
||||
dim_desc[i].2 = 0;
|
||||
}
|
||||
|
||||
let desc = BufferDescriptor {
|
||||
len: self.desc.len,
|
||||
readonly: self.desc.readonly,
|
||||
itemsize: self.desc.itemsize,
|
||||
format: self.desc.format.clone(),
|
||||
dim_desc,
|
||||
};
|
||||
|
||||
VecBuffer::from(data)
|
||||
.into_ref(vm)
|
||||
.into_pybuffer_with_descriptor(desc)
|
||||
}
|
||||
}
|
||||
|
||||
impl Py<PyMemoryView> {
|
||||
fn setitem_by_slice(
|
||||
&self,
|
||||
slice: &PySlice,
|
||||
src: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
if self.desc.ndim() != 1 {
|
||||
return Err(vm.new_not_implemented_error("sub-view are not implemented".to_owned()));
|
||||
}
|
||||
|
||||
let mut dest = self.new_view();
|
||||
dest.init_slice(slice, 0, vm)?;
|
||||
dest.init_len();
|
||||
|
||||
if self.is(&src) {
|
||||
return if !is_equiv_structure(&self.desc, &dest.desc) {
|
||||
Err(vm.new_value_error(
|
||||
"memoryview assignment: lvalue and rvalue have different structures".to_owned(),
|
||||
))
|
||||
} else {
|
||||
// assign self[:] to self
|
||||
Ok(())
|
||||
};
|
||||
};
|
||||
|
||||
let src = if let Some(src) = src.downcast_ref::<PyMemoryView>() {
|
||||
if self.buffer.obj.is(&src.buffer.obj) {
|
||||
src.to_contiguous(vm)
|
||||
} else {
|
||||
AsBuffer::as_buffer(src, vm)?
|
||||
}
|
||||
} else {
|
||||
PyBuffer::try_from_object(vm, src)?
|
||||
};
|
||||
|
||||
if !is_equiv_structure(&src.desc, &dest.desc) {
|
||||
return Err(vm.new_value_error(
|
||||
"memoryview assignment: lvalue and rvalue have different structures".to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
let mut bytes_mut = dest.buffer.obj_bytes_mut();
|
||||
let src_bytes = src.obj_bytes();
|
||||
dest.desc.zip_eq(&src.desc, true, |a_range, b_range| {
|
||||
let a_range = (a_range.start + dest.start as isize) as usize
|
||||
..(a_range.end + dest.start as isize) as usize;
|
||||
let b_range = b_range.start as usize..b_range.end as usize;
|
||||
bytes_mut[a_range].copy_from_slice(&src_bytes[b_range]);
|
||||
false
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(
|
||||
Py,
|
||||
Hashable,
|
||||
Comparable,
|
||||
AsBuffer,
|
||||
AsMapping,
|
||||
AsSequence,
|
||||
Constructor,
|
||||
Iterable,
|
||||
Representable
|
||||
))]
|
||||
impl PyMemoryView {
|
||||
#[pymethod]
|
||||
pub fn release(&self) {
|
||||
if self.released.compare_exchange(false, true).is_ok() {
|
||||
self.buffer.release();
|
||||
}
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn obj(&self, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
|
||||
self.try_not_released(vm).map(|_| self.buffer.obj.clone())
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn nbytes(&self, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
self.try_not_released(vm).map(|_| self.desc.len)
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn readonly(&self, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
self.try_not_released(vm).map(|_| self.desc.readonly)
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn itemsize(&self, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
self.try_not_released(vm).map(|_| self.desc.itemsize)
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn ndim(&self, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
self.try_not_released(vm).map(|_| self.desc.ndim())
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn shape(&self, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
|
||||
self.try_not_released(vm)?;
|
||||
Ok(vm.ctx.new_tuple(
|
||||
self.desc
|
||||
.dim_desc
|
||||
.iter()
|
||||
.map(|(shape, _, _)| shape.to_pyobject(vm))
|
||||
.collect(),
|
||||
))
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn strides(&self, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
|
||||
self.try_not_released(vm)?;
|
||||
Ok(vm.ctx.new_tuple(
|
||||
self.desc
|
||||
.dim_desc
|
||||
.iter()
|
||||
.map(|(_, stride, _)| stride.to_pyobject(vm))
|
||||
.collect(),
|
||||
))
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn suboffsets(&self, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
|
||||
self.try_not_released(vm)?;
|
||||
Ok(vm.ctx.new_tuple(
|
||||
self.desc
|
||||
.dim_desc
|
||||
.iter()
|
||||
.map(|(_, _, suboffset)| suboffset.to_pyobject(vm))
|
||||
.collect(),
|
||||
))
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn format(&self, vm: &VirtualMachine) -> PyResult<PyStr> {
|
||||
self.try_not_released(vm)
|
||||
.map(|_| PyStr::from(self.desc.format.clone()))
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn contiguous(&self, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
self.try_not_released(vm).map(|_| self.desc.is_contiguous())
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn c_contiguous(&self, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
self.try_not_released(vm).map(|_| self.desc.is_contiguous())
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn f_contiguous(&self, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
// TODO: fortain order
|
||||
self.try_not_released(vm)
|
||||
.map(|_| self.desc.ndim() <= 1 && self.desc.is_contiguous())
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn enter(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
zelf.try_not_released(vm).map(|_| zelf)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn exit(&self, _args: FuncArgs) {
|
||||
self.release();
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn getitem(zelf: PyRef<Self>, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
zelf.try_not_released(vm)?;
|
||||
if zelf.desc.ndim() == 0 {
|
||||
// 0-d memoryview can be referenced using mv[...] or mv[()] only
|
||||
if needle.is(&vm.ctx.ellipsis) {
|
||||
return Ok(zelf.into());
|
||||
}
|
||||
if let Some(tuple) = needle.payload::<PyTuple>() {
|
||||
if tuple.is_empty() {
|
||||
return zelf.unpack_single(0, vm);
|
||||
}
|
||||
}
|
||||
return Err(vm.new_type_error("invalid indexing of 0-dim memory".to_owned()));
|
||||
}
|
||||
|
||||
match SubscriptNeedle::try_from_object(vm, needle)? {
|
||||
SubscriptNeedle::Index(i) => zelf.getitem_by_idx(i, vm),
|
||||
SubscriptNeedle::Slice(slice) => zelf.getitem_by_slice(&slice, vm),
|
||||
SubscriptNeedle::MultiIndex(indices) => zelf.getitem_by_multi_idx(&indices, vm),
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn delitem(&self, _needle: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
if self.desc.readonly {
|
||||
return Err(vm.new_type_error("cannot modify read-only memory".to_owned()));
|
||||
}
|
||||
Err(vm.new_type_error("cannot delete memory".to_owned()))
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn len(&self, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
self.try_not_released(vm)?;
|
||||
Ok(if self.desc.ndim() == 0 {
|
||||
1
|
||||
} else {
|
||||
// shape for dim[0]
|
||||
self.desc.dim_desc[0].0
|
||||
})
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn tobytes(&self, vm: &VirtualMachine) -> PyResult<PyBytesRef> {
|
||||
self.try_not_released(vm)?;
|
||||
let mut v = vec![];
|
||||
self.append_to(&mut v);
|
||||
Ok(PyBytes::from(v).into_ref(vm))
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn tolist(&self, vm: &VirtualMachine) -> PyResult<PyListRef> {
|
||||
self.try_not_released(vm)?;
|
||||
@@ -714,178 +848,51 @@ impl PyMemoryView {
|
||||
Ok(self.cast_to_1d(format, vm)?.into_ref(vm))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn eq(zelf: &Py<Self>, other: &PyObject, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
if zelf.is(other) {
|
||||
return Ok(true);
|
||||
}
|
||||
if zelf.released.load() {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
if let Some(other) = other.payload::<Self>() {
|
||||
if other.released.load() {
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
|
||||
let other = match PyBuffer::try_from_borrowed_object(vm, other) {
|
||||
Ok(buf) => buf,
|
||||
Err(_) => return Ok(false),
|
||||
};
|
||||
|
||||
if !is_equiv_shape(&zelf.desc, &other.desc) {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let a_itemsize = zelf.desc.itemsize;
|
||||
let b_itemsize = other.desc.itemsize;
|
||||
let a_format_spec = &zelf.format_spec;
|
||||
let b_format_spec = &Self::parse_format(&other.desc.format, vm)?;
|
||||
|
||||
if zelf.desc.ndim() == 0 {
|
||||
let a_val = format_unpack(a_format_spec, &zelf.buffer.obj_bytes()[..a_itemsize], vm)?;
|
||||
let b_val = format_unpack(b_format_spec, &other.obj_bytes()[..b_itemsize], vm)?;
|
||||
return vm.bool_eq(&a_val, &b_val);
|
||||
}
|
||||
|
||||
// TODO: optimize cmp by format
|
||||
let mut ret = Ok(true);
|
||||
let a_bytes = zelf.buffer.obj_bytes();
|
||||
let b_bytes = other.obj_bytes();
|
||||
zelf.desc.zip_eq(&other.desc, false, |a_range, b_range| {
|
||||
let a_range = (a_range.start + zelf.start as isize) as usize
|
||||
..(a_range.end + zelf.start as isize) as usize;
|
||||
let b_range = b_range.start as usize..b_range.end as usize;
|
||||
let a_val = match format_unpack(a_format_spec, &a_bytes[a_range], vm) {
|
||||
Ok(val) => val,
|
||||
Err(e) => {
|
||||
ret = Err(e);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
let b_val = match format_unpack(b_format_spec, &b_bytes[b_range], vm) {
|
||||
Ok(val) => val,
|
||||
Err(e) => {
|
||||
ret = Err(e);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
ret = vm.bool_eq(&a_val, &b_val);
|
||||
if let Ok(b) = ret {
|
||||
!b
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
ret
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
impl Py<PyMemoryView> {
|
||||
#[pymethod(magic)]
|
||||
fn reduce_ex(zelf: PyRef<Self>, _proto: usize, vm: &VirtualMachine) -> PyResult {
|
||||
Self::reduce(zelf, vm)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn reduce(_zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
Err(vm.new_type_error("cannot pickle 'memoryview' object".to_owned()))
|
||||
}
|
||||
|
||||
fn obj_bytes(&self) -> BorrowedValue<[u8]> {
|
||||
if self.desc.is_contiguous() {
|
||||
BorrowedValue::map(self.buffer.obj_bytes(), |x| {
|
||||
&x[self.start..self.start + self.desc.len]
|
||||
})
|
||||
} else {
|
||||
BorrowedValue::map(self.buffer.obj_bytes(), |x| &x[self.start..])
|
||||
fn setitem(
|
||||
&self,
|
||||
needle: PyObjectRef,
|
||||
value: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
self.try_not_released(vm)?;
|
||||
if self.desc.readonly {
|
||||
return Err(vm.new_type_error("cannot modify read-only memory".to_owned()));
|
||||
}
|
||||
}
|
||||
|
||||
fn obj_bytes_mut(&self) -> BorrowedValueMut<[u8]> {
|
||||
if self.desc.is_contiguous() {
|
||||
BorrowedValueMut::map(self.buffer.obj_bytes_mut(), |x| {
|
||||
&mut x[self.start..self.start + self.desc.len]
|
||||
})
|
||||
} else {
|
||||
BorrowedValueMut::map(self.buffer.obj_bytes_mut(), |x| &mut x[self.start..])
|
||||
if value.is(&vm.ctx.none) {
|
||||
return Err(vm.new_type_error("cannot delete memory".to_owned()));
|
||||
}
|
||||
}
|
||||
|
||||
fn as_contiguous(&self) -> Option<BorrowedValue<[u8]>> {
|
||||
self.desc.is_contiguous().then(|| {
|
||||
BorrowedValue::map(self.buffer.obj_bytes(), |x| {
|
||||
&x[self.start..self.start + self.desc.len]
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn _as_contiguous_mut(&self) -> Option<BorrowedValueMut<[u8]>> {
|
||||
self.desc.is_contiguous().then(|| {
|
||||
BorrowedValueMut::map(self.buffer.obj_bytes_mut(), |x| {
|
||||
&mut x[self.start..self.start + self.desc.len]
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn append_to(&self, buf: &mut Vec<u8>) {
|
||||
if let Some(bytes) = self.as_contiguous() {
|
||||
buf.extend_from_slice(&bytes);
|
||||
} else {
|
||||
buf.reserve(self.desc.len);
|
||||
let bytes = &*self.buffer.obj_bytes();
|
||||
self.desc.for_each_segment(true, |range| {
|
||||
let start = (range.start + self.start as isize) as usize;
|
||||
let end = (range.end + self.start as isize) as usize;
|
||||
buf.extend_from_slice(&bytes[start..end]);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn contiguous_or_collect<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
|
||||
let borrowed;
|
||||
let mut collected;
|
||||
let v = if let Some(bytes) = self.as_contiguous() {
|
||||
borrowed = bytes;
|
||||
&*borrowed
|
||||
} else {
|
||||
collected = vec![];
|
||||
self.append_to(&mut collected);
|
||||
&collected
|
||||
};
|
||||
f(v)
|
||||
}
|
||||
|
||||
/// clone data from memoryview
|
||||
/// keep the shape, convert to contiguous
|
||||
pub fn to_contiguous(&self, vm: &VirtualMachine) -> PyBuffer {
|
||||
let mut data = vec![];
|
||||
self.append_to(&mut data);
|
||||
|
||||
if self.desc.ndim() == 0 {
|
||||
return VecBuffer::from(data)
|
||||
.into_ref(vm)
|
||||
.into_pybuffer_with_descriptor(self.desc.clone());
|
||||
// TODO: merge branches when we got conditional if let
|
||||
if needle.is(&vm.ctx.ellipsis) {
|
||||
return self.pack_single(0, value, vm);
|
||||
} else if let Some(tuple) = needle.payload::<PyTuple>() {
|
||||
if tuple.is_empty() {
|
||||
return self.pack_single(0, value, vm);
|
||||
}
|
||||
}
|
||||
return Err(vm.new_type_error("invalid indexing of 0-dim memory".to_owned()));
|
||||
}
|
||||
|
||||
let mut dim_desc = self.desc.dim_desc.clone();
|
||||
dim_desc.last_mut().unwrap().1 = self.desc.itemsize as isize;
|
||||
dim_desc.last_mut().unwrap().2 = 0;
|
||||
for i in (0..dim_desc.len() - 1).rev() {
|
||||
dim_desc[i].1 = dim_desc[i + 1].1 * dim_desc[i + 1].0 as isize;
|
||||
dim_desc[i].2 = 0;
|
||||
match SubscriptNeedle::try_from_object(vm, needle)? {
|
||||
SubscriptNeedle::Index(i) => self.setitem_by_idx(i, value, vm),
|
||||
SubscriptNeedle::Slice(slice) => self.setitem_by_slice(&slice, value, vm),
|
||||
SubscriptNeedle::MultiIndex(indices) => self.setitem_by_multi_idx(&indices, value, vm),
|
||||
}
|
||||
}
|
||||
|
||||
let desc = BufferDescriptor {
|
||||
len: self.desc.len,
|
||||
readonly: self.desc.readonly,
|
||||
itemsize: self.desc.itemsize,
|
||||
format: self.desc.format.clone(),
|
||||
dim_desc,
|
||||
};
|
||||
#[pymethod(magic)]
|
||||
fn reduce_ex(&self, _proto: usize, vm: &VirtualMachine) -> PyResult {
|
||||
self.reduce(vm)
|
||||
}
|
||||
|
||||
VecBuffer::from(data)
|
||||
.into_ref(vm)
|
||||
.into_pybuffer_with_descriptor(desc)
|
||||
#[pymethod(magic)]
|
||||
fn reduce(&self, vm: &VirtualMachine) -> PyResult {
|
||||
Err(vm.new_type_error("cannot pickle 'memoryview' object".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -977,7 +984,7 @@ impl AsMapping for PyMemoryView {
|
||||
ass_subscript: atomic_func!(|mapping, needle, value, vm| {
|
||||
let zelf = PyMemoryView::mapping_downcast(mapping);
|
||||
if let Some(value) = value {
|
||||
PyMemoryView::setitem(zelf.to_owned(), needle.to_owned(), value, vm)
|
||||
zelf.setitem(needle.to_owned(), value, vm)
|
||||
} else {
|
||||
Err(vm.new_type_error("cannot delete memory".to_owned()))
|
||||
}
|
||||
|
||||
@@ -42,8 +42,8 @@ use unic_ucd_category::GeneralCategory;
|
||||
use unic_ucd_ident::{is_xid_continue, is_xid_start};
|
||||
use unicode_casing::CharExt;
|
||||
|
||||
impl TryFromBorrowedObject for String {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult<Self> {
|
||||
impl<'a> TryFromBorrowedObject<'a> for String {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult<Self> {
|
||||
obj.try_value_with(|pystr: &PyStr| Ok(pystr.as_str().to_owned()), vm)
|
||||
}
|
||||
}
|
||||
|
||||
+66
-63
@@ -355,6 +355,31 @@ impl PyType {
|
||||
|
||||
attributes
|
||||
}
|
||||
|
||||
// bound method for every type
|
||||
pub(crate) fn __new__(zelf: PyRef<PyType>, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
let (subtype, args): (PyRef<Self>, FuncArgs) = args.bind(vm)?;
|
||||
if !subtype.fast_issubclass(&zelf) {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"{zelf}.__new__({subtype}): {subtype} is not a subtype of {zelf}",
|
||||
zelf = zelf.name(),
|
||||
subtype = subtype.name(),
|
||||
)));
|
||||
}
|
||||
call_slot_new(zelf, subtype, args, vm)
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
impl Py<PyType> {
|
||||
@@ -375,30 +400,10 @@ impl Py<PyType> {
|
||||
}
|
||||
|
||||
#[pyclass(
|
||||
with(GetAttr, SetAttr, Callable, AsNumber, Representable),
|
||||
with(Py, GetAttr, SetAttr, Callable, AsNumber, Representable),
|
||||
flags(BASETYPE)
|
||||
)]
|
||||
impl PyType {
|
||||
// bound method for every type
|
||||
pub(crate) fn __new__(zelf: PyRef<Self>, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
let (subtype, args): (PyRef<Self>, FuncArgs) = args.bind(vm)?;
|
||||
if !subtype.fast_issubclass(&zelf) {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"{zelf}.__new__({subtype}): {subtype} is not a subtype of {zelf}",
|
||||
zelf = zelf.name(),
|
||||
subtype = subtype.name(),
|
||||
)));
|
||||
}
|
||||
call_slot_new(zelf, subtype, args, vm)
|
||||
}
|
||||
|
||||
#[pygetset(name = "__mro__")]
|
||||
fn get_mro(zelf: PyRef<Self>) -> PyTuple {
|
||||
let elements: Vec<PyObjectRef> =
|
||||
zelf.iter_mro().map(|x| x.as_object().to_owned()).collect();
|
||||
PyTuple::new_unchecked(elements.into_boxed_slice())
|
||||
}
|
||||
|
||||
#[pygetset(magic)]
|
||||
fn bases(&self, vm: &VirtualMachine) -> PyTupleRef {
|
||||
vm.ctx.new_tuple(
|
||||
@@ -419,48 +424,11 @@ impl PyType {
|
||||
self.slots.flags.bits()
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn dir(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyList {
|
||||
let attributes: Vec<PyObjectRef> = zelf
|
||||
.get_attributes()
|
||||
.into_iter()
|
||||
.map(|(k, _)| k.to_object())
|
||||
.collect();
|
||||
PyList::from(attributes)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn instancecheck(zelf: PyRef<Self>, obj: PyObjectRef) -> bool {
|
||||
obj.fast_isinstance(&zelf)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn subclasscheck(zelf: PyRef<Self>, subclass: PyTypeRef) -> bool {
|
||||
subclass.fast_issubclass(&zelf)
|
||||
}
|
||||
|
||||
#[pyclassmethod(magic)]
|
||||
fn subclasshook(_args: FuncArgs, vm: &VirtualMachine) -> PyObjectRef {
|
||||
vm.ctx.not_implemented()
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn __name__(&self) -> String {
|
||||
self.name().to_string()
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
#[pygetset(magic)]
|
||||
pub fn qualname(&self, vm: &VirtualMachine) -> PyObjectRef {
|
||||
self.attributes
|
||||
@@ -607,11 +575,6 @@ impl PyType {
|
||||
)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn mro(zelf: PyRef<Self>) -> Vec<PyObjectRef> {
|
||||
zelf.iter_mro().map(|cls| cls.to_owned().into()).collect()
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
pub fn ror(zelf: PyObjectRef, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
|
||||
or_(other, zelf, vm)
|
||||
@@ -906,6 +869,46 @@ impl PyType {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
impl Py<PyType> {
|
||||
#[pygetset(name = "__mro__")]
|
||||
fn get_mro(&self) -> PyTuple {
|
||||
let elements: Vec<PyObjectRef> =
|
||||
self.iter_mro().map(|x| x.as_object().to_owned()).collect();
|
||||
PyTuple::new_unchecked(elements.into_boxed_slice())
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn dir(&self) -> PyList {
|
||||
let attributes: Vec<PyObjectRef> = self
|
||||
.get_attributes()
|
||||
.into_iter()
|
||||
.map(|(k, _)| k.to_object())
|
||||
.collect();
|
||||
PyList::from(attributes)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn instancecheck(&self, obj: PyObjectRef) -> bool {
|
||||
obj.fast_isinstance(self)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn subclasscheck(&self, subclass: PyTypeRef) -> bool {
|
||||
subclass.fast_issubclass(self)
|
||||
}
|
||||
|
||||
#[pyclassmethod(magic)]
|
||||
fn subclasshook(_args: FuncArgs, vm: &VirtualMachine) -> PyObjectRef {
|
||||
vm.ctx.not_implemented()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn mro(&self) -> Vec<PyObjectRef> {
|
||||
self.iter_mro().map(|cls| cls.to_owned().into()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
const SIGNATURE_END_MARKER: &str = ")\n--\n\n";
|
||||
fn get_signature(doc: &str) -> Option<&str> {
|
||||
doc.find(SIGNATURE_END_MARKER).map(|index| &doc[..=index])
|
||||
|
||||
@@ -30,8 +30,8 @@ impl From<Vec<u8>> for PyBytesInner {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFromBorrowedObject for PyBytesInner {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult<Self> {
|
||||
impl<'a> TryFromBorrowedObject<'a> for PyBytesInner {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult<Self> {
|
||||
bytes_from_object(vm, obj).map(Self::from)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-13
@@ -3,7 +3,7 @@
|
||||
use crate::{
|
||||
builtins::{PyBaseObject, PyBoundMethod, PyType, PyTypeRef},
|
||||
identifier,
|
||||
object::{Py, PyObjectPayload, PyObjectRef, PyRef},
|
||||
object::{Py, PyObjectRef},
|
||||
types::{hash_not_implemented, PyTypeFlags, PyTypeSlots},
|
||||
vm::Context,
|
||||
};
|
||||
@@ -63,18 +63,6 @@ pub trait PyClassDef {
|
||||
const UNHASHABLE: bool = false;
|
||||
}
|
||||
|
||||
impl<T> PyClassDef for PyRef<T>
|
||||
where
|
||||
T: PyObjectPayload + PyClassDef,
|
||||
{
|
||||
const NAME: &'static str = T::NAME;
|
||||
const MODULE_NAME: Option<&'static str> = T::MODULE_NAME;
|
||||
const TP_NAME: &'static str = T::TP_NAME;
|
||||
const DOC: Option<&'static str> = T::DOC;
|
||||
const BASICSIZE: usize = T::BASICSIZE;
|
||||
const UNHASHABLE: bool = T::UNHASHABLE;
|
||||
}
|
||||
|
||||
pub trait PyClassImpl: PyClassDef {
|
||||
const TP_FLAGS: PyTypeFlags = PyTypeFlags::DEFAULT;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
builtins::PyFloat,
|
||||
object::{AsObject, PyObject, PyObjectRef, PyPayload, PyRef, PyResult},
|
||||
vm::VirtualMachine,
|
||||
Py, VirtualMachine,
|
||||
};
|
||||
use num_traits::ToPrimitive;
|
||||
|
||||
@@ -15,7 +15,7 @@ pub trait TryFromObject: Sized {
|
||||
}
|
||||
|
||||
/// Rust-side only version of TryFromObject to reduce unnecessary Rc::clone
|
||||
impl<T: TryFromBorrowedObject> TryFromObject for T {
|
||||
impl<T: for<'a> TryFromBorrowedObject<'a>> TryFromObject for T {
|
||||
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
|
||||
TryFromBorrowedObject::try_from_borrowed_object(vm, &obj)
|
||||
}
|
||||
@@ -31,9 +31,9 @@ impl PyObjectRef {
|
||||
}
|
||||
|
||||
impl PyObject {
|
||||
pub fn try_to_value<T>(&self, vm: &VirtualMachine) -> PyResult<T>
|
||||
pub fn try_to_value<'a, T: 'a>(&'a self, vm: &VirtualMachine) -> PyResult<T>
|
||||
where
|
||||
T: TryFromBorrowedObject,
|
||||
T: TryFromBorrowedObject<'a>,
|
||||
{
|
||||
T::try_from_borrowed_object(vm, self)
|
||||
}
|
||||
@@ -55,9 +55,12 @@ impl PyObject {
|
||||
}
|
||||
|
||||
/// Lower-cost variation of `TryFromObject`
|
||||
pub trait TryFromBorrowedObject: Sized {
|
||||
pub trait TryFromBorrowedObject<'a>: Sized
|
||||
where
|
||||
Self: 'a,
|
||||
{
|
||||
/// Attempt to convert a Python object to a value of this type.
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult<Self>;
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult<Self>;
|
||||
}
|
||||
|
||||
impl<T> TryFromObject for PyRef<T>
|
||||
@@ -93,12 +96,24 @@ impl<T: TryFromObject> TryFromObject for Option<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: TryFromObject> TryFromBorrowedObject for Vec<T> {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, value: &PyObject) -> PyResult<Self> {
|
||||
impl<'a, T: 'a + TryFromObject> TryFromBorrowedObject<'a> for Vec<T> {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, value: &'a PyObject) -> PyResult<Self> {
|
||||
vm.extract_elements_with(value, |obj| T::try_from_object(vm, obj))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: PyPayload> TryFromBorrowedObject<'a> for &'a Py<T> {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult<Self> {
|
||||
let class = T::class(vm);
|
||||
if obj.fast_isinstance(class) {
|
||||
obj.downcast_ref()
|
||||
.ok_or_else(|| vm.new_downcast_runtime_error(class, &obj))
|
||||
} else {
|
||||
Err(vm.new_downcast_type_error(class, &obj))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFromObject for std::time::Duration {
|
||||
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
|
||||
use std::time::Duration;
|
||||
|
||||
+41
-37
@@ -164,24 +164,20 @@ impl Frame {
|
||||
temporary_refs: PyMutex::new(vec![]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FrameRef {
|
||||
#[inline(always)]
|
||||
fn with_exec<R>(&self, f: impl FnOnce(ExecutingFrame) -> R) -> R {
|
||||
let mut state = self.state.lock();
|
||||
let exec = ExecutingFrame {
|
||||
code: &self.code,
|
||||
fastlocals: &self.fastlocals,
|
||||
cells_frees: &self.cells_frees,
|
||||
locals: &self.locals,
|
||||
globals: &self.globals,
|
||||
builtins: &self.builtins,
|
||||
lasti: &self.lasti,
|
||||
object: self,
|
||||
state: &mut state,
|
||||
};
|
||||
f(exec)
|
||||
pub fn current_location(&self) -> bytecode::Location {
|
||||
self.code.locations[self.lasti() as usize - 1]
|
||||
}
|
||||
|
||||
pub fn lasti(&self) -> u32 {
|
||||
#[cfg(feature = "threading")]
|
||||
{
|
||||
self.lasti.load(atomic::Ordering::Relaxed)
|
||||
}
|
||||
#[cfg(not(feature = "threading"))]
|
||||
{
|
||||
self.lasti.get()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn locals(&self, vm: &VirtualMachine) -> PyResult<ArgMapping> {
|
||||
@@ -221,6 +217,25 @@ impl FrameRef {
|
||||
}
|
||||
Ok(locals.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl Py<Frame> {
|
||||
#[inline(always)]
|
||||
fn with_exec<R>(&self, f: impl FnOnce(ExecutingFrame) -> R) -> R {
|
||||
let mut state = self.state.lock();
|
||||
let exec = ExecutingFrame {
|
||||
code: &self.code,
|
||||
fastlocals: &self.fastlocals,
|
||||
cells_frees: &self.cells_frees,
|
||||
locals: &self.locals,
|
||||
globals: &self.globals,
|
||||
builtins: &self.builtins,
|
||||
lasti: &self.lasti,
|
||||
object: self,
|
||||
state: &mut state,
|
||||
};
|
||||
f(exec)
|
||||
}
|
||||
|
||||
// #[cfg_attr(feature = "flame-it", flame("Frame"))]
|
||||
pub fn run(&self, vm: &VirtualMachine) -> PyResult<ExecutionResult> {
|
||||
@@ -250,34 +265,19 @@ impl FrameRef {
|
||||
self.with_exec(|mut exec| exec.gen_throw(vm, exc_type, exc_val, exc_tb))
|
||||
}
|
||||
|
||||
pub fn current_location(&self) -> bytecode::Location {
|
||||
self.code.locations[self.lasti() as usize - 1]
|
||||
}
|
||||
|
||||
pub fn yield_from_target(&self) -> Option<PyObjectRef> {
|
||||
self.with_exec(|exec| exec.yield_from_target().map(PyObject::to_owned))
|
||||
}
|
||||
|
||||
pub fn lasti(&self) -> u32 {
|
||||
#[cfg(feature = "threading")]
|
||||
{
|
||||
self.lasti.load(atomic::Ordering::Relaxed)
|
||||
}
|
||||
#[cfg(not(feature = "threading"))]
|
||||
{
|
||||
self.lasti.get()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_internal_frame(&self) -> bool {
|
||||
let code = self.clone().f_code();
|
||||
let code = self.f_code();
|
||||
let filename = code.co_filename();
|
||||
|
||||
filename.as_str().contains("importlib") && filename.as_str().contains("_bootstrap")
|
||||
}
|
||||
|
||||
pub fn next_external_frame(&self, vm: &VirtualMachine) -> Option<FrameRef> {
|
||||
self.clone().f_back(vm).map(|mut back| loop {
|
||||
self.f_back(vm).map(|mut back| loop {
|
||||
back = if let Some(back) = back.to_owned().f_back(vm) {
|
||||
back
|
||||
} else {
|
||||
@@ -300,7 +300,7 @@ struct ExecutingFrame<'a> {
|
||||
locals: &'a ArgMapping,
|
||||
globals: &'a PyDictRef,
|
||||
builtins: &'a PyDictRef,
|
||||
object: &'a FrameRef,
|
||||
object: &'a Py<Frame>,
|
||||
lasti: &'a Lasti,
|
||||
state: &'a mut FrameState,
|
||||
}
|
||||
@@ -376,8 +376,12 @@ impl ExecutingFrame<'_> {
|
||||
|
||||
let loc = frame.code.locations[idx];
|
||||
let next = exception.traceback();
|
||||
let new_traceback =
|
||||
PyTraceback::new(next, frame.object.clone(), frame.lasti(), loc.row());
|
||||
let new_traceback = PyTraceback::new(
|
||||
next,
|
||||
frame.object.to_owned(),
|
||||
frame.lasti(),
|
||||
loc.row(),
|
||||
);
|
||||
vm_trace!("Adding to traceback: {:?} {:?}", new_traceback, loc.row());
|
||||
exception.set_traceback(Some(new_traceback.into_ref(vm)));
|
||||
|
||||
|
||||
@@ -65,8 +65,8 @@ impl From<ArgBytesLike> for PyBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFromBorrowedObject for ArgBytesLike {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult<Self> {
|
||||
impl<'a> TryFromBorrowedObject<'a> for ArgBytesLike {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult<Self> {
|
||||
let buffer = PyBuffer::try_from_borrowed_object(vm, obj)?;
|
||||
if buffer.desc.is_contiguous() {
|
||||
Ok(Self(buffer))
|
||||
@@ -107,8 +107,8 @@ impl From<ArgMemoryBuffer> for PyBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFromBorrowedObject for ArgMemoryBuffer {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult<Self> {
|
||||
impl<'a> TryFromBorrowedObject<'a> for ArgMemoryBuffer {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult<Self> {
|
||||
let buffer = PyBuffer::try_from_borrowed_object(vm, obj)?;
|
||||
if !buffer.desc.is_contiguous() {
|
||||
Err(vm.new_type_error("non-contiguous buffer is not a bytes-like object".to_owned()))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use super::{FromArgs, FuncArgs};
|
||||
use crate::{
|
||||
convert::ToPyResult, object::PyThreadingConstraint, PyPayload, PyRef, PyResult, VirtualMachine,
|
||||
convert::ToPyResult, object::PyThreadingConstraint, Py, PyPayload, PyRef, PyResult,
|
||||
VirtualMachine,
|
||||
};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
@@ -59,6 +60,8 @@ use sealed::PyNativeFuncInternal;
|
||||
#[doc(hidden)]
|
||||
pub struct OwnedParam<T>(PhantomData<T>);
|
||||
#[doc(hidden)]
|
||||
pub struct BorrowedParam<T>(PhantomData<T>);
|
||||
#[doc(hidden)]
|
||||
pub struct RefParam<T>(PhantomData<T>);
|
||||
|
||||
// This is the "magic" that allows rust functions of varying signatures to
|
||||
@@ -80,6 +83,20 @@ macro_rules! into_py_native_func_tuple {
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, S, $($T,)* R> PyNativeFuncInternal<(BorrowedParam<S>, $(OwnedParam<$T>,)*), R, VirtualMachine> for F
|
||||
where
|
||||
F: Fn(&Py<S>, $($T,)* &VirtualMachine) -> R + PyThreadingConstraint + 'static,
|
||||
S: PyPayload,
|
||||
$($T: FromArgs,)*
|
||||
R: ToPyResult,
|
||||
{
|
||||
fn call_(&self, vm: &VirtualMachine, args: FuncArgs) -> PyResult {
|
||||
let (zelf, $($n,)*) = args.bind::<(PyRef<S>, $($T,)*)>(vm)?;
|
||||
|
||||
(self)(&zelf, $($n,)* vm).to_pyresult(vm)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, S, $($T,)* R> PyNativeFuncInternal<(RefParam<S>, $(OwnedParam<$T>,)*), R, VirtualMachine> for F
|
||||
where
|
||||
F: Fn(&S, $($T,)* &VirtualMachine) -> R + PyThreadingConstraint + 'static,
|
||||
@@ -107,6 +124,20 @@ macro_rules! into_py_native_func_tuple {
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, S, $($T,)* R> PyNativeFuncInternal<(BorrowedParam<S>, $(OwnedParam<$T>,)*), R, ()> for F
|
||||
where
|
||||
F: Fn(&Py<S>, $($T,)*) -> R + PyThreadingConstraint + 'static,
|
||||
S: PyPayload,
|
||||
$($T: FromArgs,)*
|
||||
R: ToPyResult,
|
||||
{
|
||||
fn call_(&self, vm: &VirtualMachine, args: FuncArgs) -> PyResult {
|
||||
let (zelf, $($n,)*) = args.bind::<(PyRef<S>, $($T,)*)>(vm)?;
|
||||
|
||||
(self)(&zelf, $($n,)*).to_pyresult(vm)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, S, $($T,)* R> PyNativeFuncInternal<(RefParam<S>, $(OwnedParam<$T>,)*), R, ()> for F
|
||||
where
|
||||
F: Fn(&S, $($T,)*) -> R + PyThreadingConstraint + 'static,
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
*/
|
||||
use crate::{
|
||||
convert::ToPyResult,
|
||||
function::{OwnedParam, RefParam},
|
||||
function::{BorrowedParam, OwnedParam, RefParam},
|
||||
object::PyThreadingConstraint,
|
||||
PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
|
||||
Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
|
||||
};
|
||||
|
||||
#[derive(result_like::OptionLike, is_macro::Is, Debug)]
|
||||
@@ -74,6 +74,18 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, S, R> IntoPyGetterFunc<(BorrowedParam<S>, R, VirtualMachine)> for F
|
||||
where
|
||||
F: Fn(&Py<S>, &VirtualMachine) -> R + 'static + Send + Sync,
|
||||
S: PyPayload,
|
||||
R: ToPyResult,
|
||||
{
|
||||
fn get(&self, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
let zelf = PyRef::<S>::try_from_object(vm, obj)?;
|
||||
(self)(&zelf, vm).to_pyresult(vm)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, S, R> IntoPyGetterFunc<(RefParam<S>, R, VirtualMachine)> for F
|
||||
where
|
||||
F: Fn(&S, &VirtualMachine) -> R + 'static + Send + Sync,
|
||||
@@ -98,6 +110,18 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, S, R> IntoPyGetterFunc<(BorrowedParam<S>, R)> for F
|
||||
where
|
||||
F: Fn(&Py<S>) -> R + 'static + Send + Sync,
|
||||
S: PyPayload,
|
||||
R: ToPyResult,
|
||||
{
|
||||
fn get(&self, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
let zelf = PyRef::<S>::try_from_object(vm, obj)?;
|
||||
(self)(&zelf).to_pyresult(vm)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, S, R> IntoPyGetterFunc<(RefParam<S>, R)> for F
|
||||
where
|
||||
F: Fn(&S) -> R + 'static + Send + Sync,
|
||||
@@ -149,6 +173,20 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, S, V, R> IntoPySetterFunc<(BorrowedParam<S>, V, R, VirtualMachine)> for F
|
||||
where
|
||||
F: Fn(&Py<S>, V, &VirtualMachine) -> R + 'static + Send + Sync,
|
||||
S: PyPayload,
|
||||
V: FromPySetterValue,
|
||||
R: IntoPyNoResult,
|
||||
{
|
||||
fn set(&self, obj: PyObjectRef, value: PySetterValue, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let zelf = PyRef::<S>::try_from_object(vm, obj)?;
|
||||
let value = V::from_setter_value(vm, value)?;
|
||||
(self)(&zelf, value, vm).into_noresult()
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, S, V, R> IntoPySetterFunc<(RefParam<S>, V, R, VirtualMachine)> for F
|
||||
where
|
||||
F: Fn(&S, V, &VirtualMachine) -> R + 'static + Send + Sync,
|
||||
@@ -177,6 +215,20 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, S, V, R> IntoPySetterFunc<(BorrowedParam<S>, V, R)> for F
|
||||
where
|
||||
F: Fn(&Py<S>, V) -> R + 'static + Send + Sync,
|
||||
S: PyPayload,
|
||||
V: FromPySetterValue,
|
||||
R: IntoPyNoResult,
|
||||
{
|
||||
fn set(&self, obj: PyObjectRef, value: PySetterValue, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let zelf = PyRef::<S>::try_from_object(vm, obj)?;
|
||||
let value = V::from_setter_value(vm, value)?;
|
||||
(self)(&zelf, value).into_noresult()
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, S, V, R> IntoPySetterFunc<(RefParam<S>, V, R)> for F
|
||||
where
|
||||
F: Fn(&S, V) -> R + 'static + Send + Sync,
|
||||
|
||||
@@ -13,7 +13,8 @@ pub use argument::{
|
||||
};
|
||||
pub use arithmetic::{PyArithmeticValue, PyComparisonValue};
|
||||
pub use buffer::{ArgAsciiBuffer, ArgBytesLike, ArgMemoryBuffer, ArgStrOrBytesLike};
|
||||
pub use builtin::{IntoPyNativeFunc, OwnedParam, PyNativeFunc, RefParam};
|
||||
pub(self) use builtin::{BorrowedParam, OwnedParam, RefParam};
|
||||
pub use builtin::{IntoPyNativeFunc, PyNativeFunc};
|
||||
pub use either::Either;
|
||||
pub use getset::PySetterValue;
|
||||
pub(super) use getset::{IntoPyGetterFunc, IntoPySetterFunc, PyGetterFunc, PySetterFunc};
|
||||
@@ -28,8 +29,8 @@ pub enum ArgByteOrder {
|
||||
Little,
|
||||
}
|
||||
|
||||
impl TryFromBorrowedObject for ArgByteOrder {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult<Self> {
|
||||
impl<'a> TryFromBorrowedObject<'a> for ArgByteOrder {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult<Self> {
|
||||
obj.try_value_with(
|
||||
|s: &PyStr| match s.as_str() {
|
||||
"big" => Ok(Self::Big),
|
||||
|
||||
@@ -385,7 +385,7 @@ impl Drop for PyWeak {
|
||||
}
|
||||
}
|
||||
|
||||
impl PyRef<PyWeak> {
|
||||
impl Py<PyWeak> {
|
||||
#[inline(always)]
|
||||
pub fn upgrade(&self) -> Option<PyObjectRef> {
|
||||
PyWeak::upgrade(self)
|
||||
|
||||
@@ -136,8 +136,8 @@ impl PyBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFromBorrowedObject for PyBuffer {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult<Self> {
|
||||
impl<'a> TryFromBorrowedObject<'a> for PyBuffer {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult<Self> {
|
||||
let cls = obj.class();
|
||||
let as_buffer = cls.mro_find_map(|cls| cls.slots.as_buffer);
|
||||
if let Some(f) = as_buffer {
|
||||
|
||||
+51
-67
@@ -3065,8 +3065,6 @@ mod _io {
|
||||
closed: AtomicCell<bool>,
|
||||
}
|
||||
|
||||
type StringIORef = PyRef<StringIO>;
|
||||
|
||||
#[derive(FromArgs)]
|
||||
struct StringIONewArgs {
|
||||
#[pyarg(positional, optional)]
|
||||
@@ -3100,7 +3098,6 @@ mod _io {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(flags(BASETYPE, HAS_DICT), with(PyRef, Constructor))]
|
||||
impl StringIO {
|
||||
fn buffer(&self, vm: &VirtualMachine) -> PyResult<PyRwLockWriteGuard<'_, BufferedIO>> {
|
||||
if !self.closed.load() {
|
||||
@@ -3109,7 +3106,10 @@ mod _io {
|
||||
Err(io_closed_error(vm))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(flags(BASETYPE, HAS_DICT), with(Constructor))]
|
||||
impl StringIO {
|
||||
#[pymethod]
|
||||
fn readable(&self) -> bool {
|
||||
true
|
||||
@@ -3132,34 +3132,28 @@ mod _io {
|
||||
fn close(&self) {
|
||||
self.closed.store(true);
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
impl StringIORef {
|
||||
//write string to underlying vector
|
||||
// write string to underlying vector
|
||||
#[pymethod]
|
||||
fn write(self, data: PyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn write(&self, data: PyStrRef, vm: &VirtualMachine) -> PyResult<u64> {
|
||||
let bytes = data.as_str().as_bytes();
|
||||
|
||||
match self.buffer(vm)?.write(bytes) {
|
||||
Some(value) => Ok(vm.ctx.new_int(value).into()),
|
||||
None => Err(vm.new_type_error("Error Writing String".to_owned())),
|
||||
}
|
||||
self.buffer(vm)?
|
||||
.write(bytes)
|
||||
.ok_or_else(|| vm.new_type_error("Error Writing String".to_owned()))
|
||||
}
|
||||
|
||||
//return the entire contents of the underlying
|
||||
// return the entire contents of the underlying
|
||||
#[pymethod]
|
||||
fn getvalue(self, vm: &VirtualMachine) -> PyResult {
|
||||
match String::from_utf8(self.buffer(vm)?.getvalue()) {
|
||||
Ok(result) => Ok(vm.ctx.new_str(result).into()),
|
||||
Err(_) => Err(vm.new_value_error("Error Retrieving Value".to_owned())),
|
||||
}
|
||||
fn getvalue(&self, vm: &VirtualMachine) -> PyResult<String> {
|
||||
let bytes = self.buffer(vm)?.getvalue();
|
||||
String::from_utf8(bytes)
|
||||
.map_err(|_| vm.new_value_error("Error Retrieving Value".to_owned()))
|
||||
}
|
||||
|
||||
//skip to the jth position
|
||||
// skip to the jth position
|
||||
#[pymethod]
|
||||
fn seek(
|
||||
self,
|
||||
&self,
|
||||
offset: PyObjectRef,
|
||||
how: OptionalArg<i32>,
|
||||
vm: &VirtualMachine,
|
||||
@@ -3169,38 +3163,34 @@ mod _io {
|
||||
.map_err(|err| os_err(vm, err))
|
||||
}
|
||||
|
||||
//Read k bytes from the object and return.
|
||||
//If k is undefined || k == -1, then we read all bytes until the end of the file.
|
||||
//This also increments the stream position by the value of k
|
||||
// Read k bytes from the object and return.
|
||||
// If k is undefined || k == -1, then we read all bytes until the end of the file.
|
||||
// This also increments the stream position by the value of k
|
||||
#[pymethod]
|
||||
fn read(self, size: OptionalSize, vm: &VirtualMachine) -> PyResult {
|
||||
let data = match self.buffer(vm)?.read(size.to_usize()) {
|
||||
Some(value) => value,
|
||||
None => Vec::new(),
|
||||
};
|
||||
fn read(&self, size: OptionalSize, vm: &VirtualMachine) -> PyResult<String> {
|
||||
let data = self.buffer(vm)?.read(size.to_usize()).unwrap_or_default();
|
||||
|
||||
let value = String::from_utf8(data)
|
||||
.map_err(|_| vm.new_value_error("Error Retrieving Value".to_owned()))?;
|
||||
Ok(vm.ctx.new_str(value).into())
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn tell(self, vm: &VirtualMachine) -> PyResult<u64> {
|
||||
fn tell(&self, vm: &VirtualMachine) -> PyResult<u64> {
|
||||
Ok(self.buffer(vm)?.tell())
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn readline(self, size: OptionalSize, vm: &VirtualMachine) -> PyResult<String> {
|
||||
fn readline(&self, size: OptionalSize, vm: &VirtualMachine) -> PyResult<String> {
|
||||
// TODO size should correspond to the number of characters, at the moments its the number of
|
||||
// bytes.
|
||||
match String::from_utf8(self.buffer(vm)?.readline(size.to_usize(), vm)?) {
|
||||
Ok(value) => Ok(value),
|
||||
Err(_) => Err(vm.new_value_error("Error Retrieving Value".to_owned())),
|
||||
}
|
||||
let input = self.buffer(vm)?.readline(size.to_usize(), vm)?;
|
||||
String::from_utf8(input)
|
||||
.map_err(|_| vm.new_value_error("Error Retrieving Value".to_owned()))
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn truncate(self, pos: OptionalSize, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
fn truncate(&self, pos: OptionalSize, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
let mut buffer = self.buffer(vm)?;
|
||||
let pos = pos.try_usize(vm)?;
|
||||
Ok(buffer.truncate(pos))
|
||||
@@ -3216,8 +3206,6 @@ mod _io {
|
||||
exports: AtomicCell<usize>,
|
||||
}
|
||||
|
||||
type BytesIORef = PyRef<BytesIO>;
|
||||
|
||||
impl Constructor for BytesIO {
|
||||
type Args = OptionalArg<Option<PyBytesRef>>;
|
||||
|
||||
@@ -3236,7 +3224,6 @@ mod _io {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(flags(BASETYPE, HAS_DICT), with(PyRef, Constructor))]
|
||||
impl BytesIO {
|
||||
fn buffer(&self, vm: &VirtualMachine) -> PyResult<PyRwLockWriteGuard<'_, BufferedIO>> {
|
||||
if !self.closed.load() {
|
||||
@@ -3245,7 +3232,10 @@ mod _io {
|
||||
Err(io_closed_error(vm))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(flags(BASETYPE, HAS_DICT), with(PyRef, Constructor))]
|
||||
impl BytesIO {
|
||||
#[pymethod]
|
||||
fn readable(&self) -> bool {
|
||||
true
|
||||
@@ -3258,37 +3248,33 @@ mod _io {
|
||||
fn seekable(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
impl BytesIORef {
|
||||
#[pymethod]
|
||||
fn write(self, data: ArgBytesLike, vm: &VirtualMachine) -> PyResult<u64> {
|
||||
fn write(&self, data: ArgBytesLike, vm: &VirtualMachine) -> PyResult<u64> {
|
||||
let mut buffer = self.try_resizable(vm)?;
|
||||
match data.with_ref(|b| buffer.write(b)) {
|
||||
Some(value) => Ok(value),
|
||||
None => Err(vm.new_type_error("Error Writing Bytes".to_owned())),
|
||||
}
|
||||
data.with_ref(|b| buffer.write(b))
|
||||
.ok_or_else(|| vm.new_type_error("Error Writing Bytes".to_owned()))
|
||||
}
|
||||
|
||||
//Retrieves the entire bytes object value from the underlying buffer
|
||||
// Retrieves the entire bytes object value from the underlying buffer
|
||||
#[pymethod]
|
||||
fn getvalue(self, vm: &VirtualMachine) -> PyResult<PyBytesRef> {
|
||||
Ok(vm.ctx.new_bytes(self.buffer(vm)?.getvalue()))
|
||||
fn getvalue(&self, vm: &VirtualMachine) -> PyResult<PyBytesRef> {
|
||||
let bytes = self.buffer(vm)?.getvalue();
|
||||
Ok(vm.ctx.new_bytes(bytes))
|
||||
}
|
||||
|
||||
//Takes an integer k (bytes) and returns them from the underlying buffer
|
||||
//If k is undefined || k == -1, then we read all bytes until the end of the file.
|
||||
//This also increments the stream position by the value of k
|
||||
// Takes an integer k (bytes) and returns them from the underlying buffer
|
||||
// If k is undefined || k == -1, then we read all bytes until the end of the file.
|
||||
// This also increments the stream position by the value of k
|
||||
#[pymethod]
|
||||
#[pymethod(name = "read1")]
|
||||
fn read(self, size: OptionalSize, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
|
||||
fn read(&self, size: OptionalSize, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
|
||||
let buf = self.buffer(vm)?.read(size.to_usize()).unwrap_or_default();
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn readinto(self, obj: ArgMemoryBuffer, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
fn readinto(&self, obj: ArgMemoryBuffer, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
let mut buf = self.buffer(vm)?;
|
||||
let ret = buf
|
||||
.cursor
|
||||
@@ -3301,7 +3287,7 @@ mod _io {
|
||||
//skip to the jth position
|
||||
#[pymethod]
|
||||
fn seek(
|
||||
self,
|
||||
&self,
|
||||
offset: PyObjectRef,
|
||||
how: OptionalArg<i32>,
|
||||
vm: &VirtualMachine,
|
||||
@@ -3312,22 +3298,17 @@ mod _io {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn seekable(self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn tell(self, vm: &VirtualMachine) -> PyResult<u64> {
|
||||
fn tell(&self, vm: &VirtualMachine) -> PyResult<u64> {
|
||||
Ok(self.buffer(vm)?.tell())
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn readline(self, size: OptionalSize, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
|
||||
fn readline(&self, size: OptionalSize, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
|
||||
self.buffer(vm)?.readline(size.to_usize(), vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn truncate(self, pos: OptionalSize, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
fn truncate(&self, pos: OptionalSize, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
if self.closed.load() {
|
||||
return Err(io_closed_error(vm));
|
||||
}
|
||||
@@ -3337,17 +3318,20 @@ mod _io {
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
fn closed(self) -> bool {
|
||||
fn closed(&self) -> bool {
|
||||
self.closed.load()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn close(self, vm: &VirtualMachine) -> PyResult<()> {
|
||||
fn close(&self, vm: &VirtualMachine) -> PyResult<()> {
|
||||
drop(self.try_resizable(vm)?);
|
||||
self.closed.store(true);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
impl PyRef<BytesIO> {
|
||||
#[pymethod]
|
||||
fn getbuffer(self, vm: &VirtualMachine) -> PyResult<PyMemoryView> {
|
||||
let len = self.buffer.read().cursor.get_ref().len();
|
||||
|
||||
@@ -435,8 +435,8 @@ mod unix {
|
||||
#[pyattr]
|
||||
use libc::{CLOCK_PROF, CLOCK_UPTIME};
|
||||
|
||||
impl TryFromBorrowedObject for ClockId {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult<Self> {
|
||||
impl<'a> TryFromBorrowedObject<'a> for ClockId {
|
||||
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult<Self> {
|
||||
obj.try_to_value(vm).map(ClockId::from_raw)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user