Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions Lib/ctypes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,9 +299,7 @@ def create_unicode_buffer(init, size=None):
return buf
elif isinstance(init, int):
_sys.audit("ctypes.create_unicode_buffer", None, init)
# XXX: RUSTPYTHON
# buftype = c_wchar * init
buftype = c_wchar.__mul__(init)
buftype = c_wchar * init
buf = buftype()
return buf
raise TypeError(init)
Expand Down
197 changes: 110 additions & 87 deletions vm/src/protocol/number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,117 +443,140 @@ impl<'a> PyNumber<'a> {

// PyNumber_Check
pub fn check(obj: &PyObject) -> bool {
let methods = &obj.class().slots.as_number;
methods.int.load().is_some()
|| methods.index.load().is_some()
|| methods.float.load().is_some()
|| obj.downcastable::<PyComplex>()
let cls = &obj.class();
// TODO: when we finally have a proper slot inheritance, mro_find_map can be removed
// methods.int.load().is_some()
// || methods.index.load().is_some()
// || methods.float.load().is_some()
// || obj.downcastable::<PyComplex>()
let has_number = cls
.mro_find_map(|x| {
let methods = &x.slots.as_number;
if methods.int.load().is_some()
|| methods.index.load().is_some()
|| methods.float.load().is_some()
{
Some(())
} else {
None
}
})
.is_some();
has_number || obj.downcastable::<PyComplex>()
}
}

impl PyNumber<'_> {
// PyIndex_Check
pub fn is_index(self) -> bool {
self.class().slots.as_number.index.load().is_some()
self.class()
.mro_find_map(|x| x.slots.as_number.index.load())
.is_some()
}

#[inline]
pub fn int(self, vm: &VirtualMachine) -> Option<PyResult<PyIntRef>> {
self.class().slots.as_number.int.load().map(|f| {
let ret = f(self, vm)?;

if let Some(ret) = ret.downcast_ref_if_exact::<PyInt>(vm) {
return Ok(ret.to_owned());
}

let ret_class = ret.class().to_owned();
if let Some(ret) = ret.downcast_ref::<PyInt>() {
warnings::warn(
vm.ctx.exceptions.deprecation_warning,
format!(
"__int__ returned non-int (type {ret_class}). \
self.class()
.mro_find_map(|x| x.slots.as_number.int.load())
.map(|f| {
let ret = f(self, vm)?;

if let Some(ret) = ret.downcast_ref_if_exact::<PyInt>(vm) {
return Ok(ret.to_owned());
}

let ret_class = ret.class().to_owned();
if let Some(ret) = ret.downcast_ref::<PyInt>() {
warnings::warn(
vm.ctx.exceptions.deprecation_warning,
format!(
"__int__ returned non-int (type {ret_class}). \
The ability to return an instance of a strict subclass of int \
is deprecated, and may be removed in a future version of Python."
),
1,
vm,
)?;

Ok(ret.to_owned())
} else {
Err(vm.new_type_error(format!(
"{}.__int__ returned non-int(type {})",
self.class(),
ret_class
)))
}
})
),
1,
vm,
)?;

Ok(ret.to_owned())
} else {
Err(vm.new_type_error(format!(
"{}.__int__ returned non-int(type {})",
self.class(),
ret_class
)))
}
})
}

#[inline]
pub fn index(self, vm: &VirtualMachine) -> Option<PyResult<PyIntRef>> {
self.class().slots.as_number.index.load().map(|f| {
let ret = f(self, vm)?;

if let Some(ret) = ret.downcast_ref_if_exact::<PyInt>(vm) {
return Ok(ret.to_owned());
}

let ret_class = ret.class().to_owned();
if let Some(ret) = ret.downcast_ref::<PyInt>() {
warnings::warn(
vm.ctx.exceptions.deprecation_warning,
format!(
"__index__ returned non-int (type {ret_class}). \
self.class()
.mro_find_map(|x| x.slots.as_number.index.load())
.map(|f| {
let ret = f(self, vm)?;

if let Some(ret) = ret.downcast_ref_if_exact::<PyInt>(vm) {
return Ok(ret.to_owned());
}

let ret_class = ret.class().to_owned();
if let Some(ret) = ret.downcast_ref::<PyInt>() {
warnings::warn(
vm.ctx.exceptions.deprecation_warning,
format!(
"__index__ returned non-int (type {ret_class}). \
The ability to return an instance of a strict subclass of int \
is deprecated, and may be removed in a future version of Python."
),
1,
vm,
)?;

Ok(ret.to_owned())
} else {
Err(vm.new_type_error(format!(
"{}.__index__ returned non-int(type {})",
self.class(),
ret_class
)))
}
})
),
1,
vm,
)?;

Ok(ret.to_owned())
} else {
Err(vm.new_type_error(format!(
"{}.__index__ returned non-int(type {})",
self.class(),
ret_class
)))
}
})
}

#[inline]
pub fn float(self, vm: &VirtualMachine) -> Option<PyResult<PyRef<PyFloat>>> {
self.class().slots.as_number.float.load().map(|f| {
let ret = f(self, vm)?;

if let Some(ret) = ret.downcast_ref_if_exact::<PyFloat>(vm) {
return Ok(ret.to_owned());
}

let ret_class = ret.class().to_owned();
if let Some(ret) = ret.downcast_ref::<PyFloat>() {
warnings::warn(
vm.ctx.exceptions.deprecation_warning,
format!(
"__float__ returned non-float (type {ret_class}). \
self.class()
.mro_find_map(|x| x.slots.as_number.float.load())
.map(|f| {
let ret = f(self, vm)?;

if let Some(ret) = ret.downcast_ref_if_exact::<PyFloat>(vm) {
return Ok(ret.to_owned());
}

let ret_class = ret.class().to_owned();
if let Some(ret) = ret.downcast_ref::<PyFloat>() {
warnings::warn(
vm.ctx.exceptions.deprecation_warning,
format!(
"__float__ returned non-float (type {ret_class}). \
The ability to return an instance of a strict subclass of float \
is deprecated, and may be removed in a future version of Python."
),
1,
vm,
)?;

Ok(ret.to_owned())
} else {
Err(vm.new_type_error(format!(
"{}.__float__ returned non-float(type {})",
self.class(),
ret_class
)))
}
})
),
1,
vm,
)?;

Ok(ret.to_owned())
} else {
Err(vm.new_type_error(format!(
"{}.__float__ returned non-float(type {})",
self.class(),
ret_class
)))
}
})
}
}

Expand Down
22 changes: 15 additions & 7 deletions vm/src/vm/vm_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,12 @@ impl VirtualMachine {
let class_a = a.class();
let class_b = b.class();

let slot_a = class_a.slots.as_number.left_binary_op(op_slot);
// Look up number slots across MRO for inheritance
let slot_a = class_a.mro_find_map(|x| x.slots.as_number.left_binary_op(op_slot));
let mut slot_b = None;

if !class_a.is(class_b) {
let slot_bb = class_b.slots.as_number.right_binary_op(op_slot);
let slot_bb = class_b.mro_find_map(|x| x.slots.as_number.right_binary_op(op_slot));
if slot_bb.map(|x| x as usize) != slot_a.map(|x| x as usize) {
slot_b = slot_bb;
}
Expand Down Expand Up @@ -230,7 +231,10 @@ impl VirtualMachine {
iop_slot: PyNumberBinaryOp,
op_slot: PyNumberBinaryOp,
) -> PyResult {
if let Some(slot) = a.class().slots.as_number.left_binary_op(iop_slot) {
if let Some(slot) = a
.class()
.mro_find_map(|x| x.slots.as_number.left_binary_op(iop_slot))
{
let x = slot(a, b, self)?;
if !x.is(&self.ctx.not_implemented) {
return Ok(x);
Expand Down Expand Up @@ -266,11 +270,12 @@ impl VirtualMachine {
let class_b = b.class();
let class_c = c.class();

let slot_a = class_a.slots.as_number.left_ternary_op(op_slot);
// Look up number slots across MRO for inheritance
let slot_a = class_a.mro_find_map(|x| x.slots.as_number.left_ternary_op(op_slot));
let mut slot_b = None;

if !class_a.is(class_b) {
let slot_bb = class_b.slots.as_number.right_ternary_op(op_slot);
let slot_bb = class_b.mro_find_map(|x| x.slots.as_number.right_ternary_op(op_slot));
if slot_bb.map(|x| x as usize) != slot_a.map(|x| x as usize) {
slot_b = slot_bb;
}
Expand Down Expand Up @@ -299,7 +304,7 @@ impl VirtualMachine {
}
}

if let Some(slot_c) = class_c.slots.as_number.left_ternary_op(op_slot)
if let Some(slot_c) = class_c.mro_find_map(|x| x.slots.as_number.left_ternary_op(op_slot))
&& slot_a.is_some_and(|slot_a| !std::ptr::fn_addr_eq(slot_a, slot_c))
&& slot_b.is_some_and(|slot_b| !std::ptr::fn_addr_eq(slot_b, slot_c))
{
Expand Down Expand Up @@ -338,7 +343,10 @@ impl VirtualMachine {
op_slot: PyNumberTernaryOp,
op_str: &str,
) -> PyResult {
if let Some(slot) = a.class().slots.as_number.left_ternary_op(iop_slot) {
if let Some(slot) = a
.class()
.mro_find_map(|x| x.slots.as_number.left_ternary_op(iop_slot))
{
let x = slot(a, b, c, self)?;
if !x.is(&self.ctx.not_implemented) {
return Ok(x);
Expand Down
Loading