Wtf8-compatible fixes (#5985)

* deprecate more payload_* functions

* loose trait bount for PyInterned

* Fix levenstein

* Fix genericalias

* Fix PyBoundMethod::repr

* fix repr

* Fix fromhex
This commit is contained in:
Jeong, YunWon authored and GitHub committed 2025-07-30 01:03:12 +09:00
1 parent 57029f6efa
commit 59a8a569dd
10 files changed
+35 -31

No files matched your search

+2 -2
View File
@@ -487,7 +487,7 @@ pub mod levenshtein {
if a == b { CASE_COST } else { MOVE_COST }
}
pub fn levenshtein_distance(a: &str, b: &str, max_cost: usize) -> usize {
pub fn levenshtein_distance(a: &[u8], b: &[u8], max_cost: usize) -> usize {
thread_local! {
#[allow(clippy::declare_interior_mutable_const)]
static BUFFER: RefCell<[usize; MAX_STRING_SIZE]> = const {
@@ -499,7 +499,7 @@ pub mod levenshtein {
return 0;
}
let (mut a_bytes, mut b_bytes) = (a.as_bytes(), b.as_bytes());
let (mut a_bytes, mut b_bytes) = (a, b);
let (mut a_begin, mut a_end) = (0usize, a.len());
let (mut b_begin, mut b_end) = (0usize, b.len());
+1 -1
View File
@@ -328,7 +328,7 @@ impl PyByteArray {
#[pyclassmethod]
fn fromhex(cls: PyTypeRef, string: PyStrRef, vm: &VirtualMachine) -> PyResult {
let bytes = PyBytesInner::fromhex(string.as_str(), vm)?;
let bytes = PyBytesInner::fromhex(string.as_bytes(), vm)?;
let bytes = vm.ctx.new_bytes(bytes);
let args = vec![bytes.into()].into();
PyType::call(&cls, args, vm)
+1 -1
View File
@@ -264,7 +264,7 @@ impl PyBytes {
#[pyclassmethod]
fn fromhex(cls: PyTypeRef, string: PyStrRef, vm: &VirtualMachine) -> PyResult {
let bytes = PyBytesInner::fromhex(string.as_str(), vm)?;
let bytes = PyBytesInner::fromhex(string.as_bytes(), vm)?;
let bytes = vm.ctx.new_bytes(bytes).into();
PyType::call(&cls, vec![bytes].into(), vm)
}
+6 -3
View File
@@ -859,10 +859,13 @@ impl Representable for PyBoundMethod {
vm.get_attribute_opt(zelf.function.clone(), "__name__")?
};
let func_name: Option<PyStrRef> = func_name.and_then(|o| o.downcast().ok());
let formatted_func_name = match func_name {
Some(name) => name.to_string(),
None => "?".to_string(),
};
let object_repr = zelf.object.repr(vm)?;
Ok(format!(
"<bound method {} of {}>",
func_name.as_ref().map_or("?", |s| s.as_str()),
&zelf.object.repr(vm)?.as_str(),
"<bound method {formatted_func_name} of {object_repr}>",
))
}
}
+4 -4
View File
@@ -122,16 +122,16 @@ impl PyGenericAlias {
.get_attribute_opt(obj.clone(), identifier!(vm, __args__))?
.is_some()
{
return Ok(obj.repr(vm)?.as_str().to_string());
return Ok(obj.repr(vm)?.to_string());
}
match (
vm.get_attribute_opt(obj.clone(), identifier!(vm, __qualname__))?
.and_then(|o| o.downcast_ref::<PyStr>().map(|n| n.as_str().to_string())),
.and_then(|o| o.downcast_ref::<PyStr>().map(|n| n.to_string())),
vm.get_attribute_opt(obj.clone(), identifier!(vm, __module__))?
.and_then(|o| o.downcast_ref::<PyStr>().map(|m| m.as_str().to_string())),
.and_then(|o| o.downcast_ref::<PyStr>().map(|m| m.to_string())),
) {
(None, _) | (_, None) => Ok(obj.repr(vm)?.as_str().to_string()),
(None, _) | (_, None) => Ok(obj.repr(vm)?.to_string()),
(Some(qualname), Some(module)) => Ok(if module == "builtins" {
qualname
} else {
+4 -4
View File
@@ -59,16 +59,16 @@ impl PyUnion {
.get_attribute_opt(obj.clone(), identifier!(vm, __args__))?
.is_some()
{
return Ok(obj.repr(vm)?.as_str().to_string());
return Ok(obj.repr(vm)?.to_string());
}
match (
vm.get_attribute_opt(obj.clone(), identifier!(vm, __qualname__))?
.and_then(|o| o.downcast_ref::<PyStr>().map(|n| n.as_str().to_string())),
.and_then(|o| o.downcast_ref::<PyStr>().map(|n| n.to_string())),
vm.get_attribute_opt(obj.clone(), identifier!(vm, __module__))?
.and_then(|o| o.downcast_ref::<PyStr>().map(|m| m.as_str().to_string())),
.and_then(|o| o.downcast_ref::<PyStr>().map(|m| m.to_string())),
) {
(None, _) | (_, None) => Ok(obj.repr(vm)?.as_str().to_string()),
(None, _) | (_, None) => Ok(obj.repr(vm)?.to_string()),
(Some(qualname), Some(module)) => Ok(if module == "builtins" {
qualname
} else {
+4 -4
View File
@@ -459,11 +459,11 @@ impl PyBytesInner {
bytes_to_hex(self.elements.as_slice(), sep, bytes_per_sep, vm)
}
pub fn fromhex(string: &str, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
let mut iter = string.bytes().enumerate();
let mut bytes: Vec<u8> = Vec::with_capacity(string.len() / 2);
pub fn fromhex(bytes: &[u8], vm: &VirtualMachine) -> PyResult<Vec<u8>> {
let mut iter = bytes.iter().enumerate();
let mut bytes: Vec<u8> = Vec::with_capacity(bytes.len() / 2);
let i = loop {
let (i, b) = match iter.next() {
let (i, &b) = match iter.next() {
Some(val) => val,
None => {
return Ok(bytes);
+4 -7
View File
@@ -128,10 +128,7 @@ impl CachedPyStrRef {
}
}
pub struct PyInterned<T>
where
T: PyPayload,
{
pub struct PyInterned<T> {
inner: Py<T>,
}
@@ -173,14 +170,14 @@ impl<T: PyPayload> std::hash::Hash for PyInterned<T> {
}
}
impl<T: PyPayload> AsRef<Py<T>> for PyInterned<T> {
impl<T> AsRef<Py<T>> for PyInterned<T> {
#[inline(always)]
fn as_ref(&self) -> &Py<T> {
&self.inner
}
}
impl<T: PyPayload> Deref for PyInterned<T> {
impl<T> Deref for PyInterned<T> {
type Target = Py<T>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
@@ -197,7 +194,7 @@ impl<T: PyPayload> PartialEq for PyInterned<T> {
impl<T: PyPayload> Eq for PyInterned<T> {}
impl<T: PyPayload + std::fmt::Debug> std::fmt::Debug for PyInterned<T> {
impl<T: std::fmt::Debug + PyPayload> std::fmt::Debug for PyInterned<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(&**self, f)?;
write!(f, "@{:p}", self.as_ptr())
+7 -3
View File
@@ -633,6 +633,7 @@ impl PyObject {
self.weak_ref_list().map(|wrl| wrl.get_weak_references())
}
#[deprecated(note = "use downcastable instead")]
#[inline(always)]
pub fn payload_is<T: PyObjectPayload>(&self) -> bool {
self.0.typeid == T::payload_type_id()
@@ -642,6 +643,7 @@ impl PyObject {
///
/// # Safety
/// The actual payload type must be T.
#[deprecated(note = "use downcast_unchecked_ref instead")]
#[inline(always)]
pub const unsafe fn payload_unchecked<T: PyObjectPayload>(&self) -> &T {
// we cast to a PyInner<T> first because we don't know T's exact offset because of
@@ -653,7 +655,9 @@ impl PyObject {
#[deprecated(note = "use downcast_ref instead")]
#[inline(always)]
pub fn payload<T: PyObjectPayload>(&self) -> Option<&T> {
#[allow(deprecated)]
if self.payload_is::<T>() {
#[allow(deprecated)]
Some(unsafe { self.payload_unchecked() })
} else {
None
@@ -719,7 +723,7 @@ impl PyObject {
/// Check if this object can be downcast to T.
#[inline(always)]
pub fn downcastable<T: PyObjectPayload>(&self) -> bool {
self.payload_is::<T>()
self.0.typeid == T::payload_type_id()
}
/// Attempt to downcast this reference to a subclass.
@@ -899,9 +903,9 @@ impl<T: PyObjectPayload> Py<T> {
})
}
#[inline]
pub fn payload(&self) -> &T {
// SAFETY: we know the payload is T because of the type parameter
unsafe { self.as_object().payload_unchecked() }
&self.0.payload
}
}
+2 -2
View File
@@ -26,7 +26,7 @@ pub fn calculate_suggestions<'a>(
for item in dir_iter {
let item_name = item.downcast_ref::<PyStr>()?;
if name.as_str() == item_name.as_str() {
if name.as_bytes() == item_name.as_bytes() {
continue;
}
// No more than 1/3 of the characters should need changed
@@ -35,7 +35,7 @@ pub fn calculate_suggestions<'a>(
suggestion_distance - 1,
);
let current_distance =
levenshtein_distance(name.as_str(), item_name.as_str(), max_distance);
levenshtein_distance(name.as_bytes(), item_name.as_bytes(), max_distance);
if current_distance > max_distance {
continue;
}