mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
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:
1 parent
57029f6efa
commit
59a8a569dd
10 files changed
+35
-31
No files matched your search
+2
-2
@@ -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());
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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}>",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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())
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user