Skip to content

Commit

Permalink
document equality semantics for Bound<'_, PyString>
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhewitt committed Jun 16, 2024
1 parent 825aa84 commit dc113a3
Showing 1 changed file with 64 additions and 1 deletion.
65 changes: 64 additions & 1 deletion src/types/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,32 @@ impl<'a> PyStringData<'a> {

/// Represents a Python `string` (a Unicode string object).
///
/// This type is immutable.
/// This type is only seen inside PyO3's smart pointers as [`Py<PyString>`], [`Bound<'py, PyString>`],
/// and [`Borrowed<'a, 'py, PyString>`].
///
/// All functionality on this type is implemented through the [`PyStringMethods`] trait.
///
/// # Equality
///
/// For convenience, [`Bound<'py, PyString>`] implements [`PartialEq<str>`] to allow comparing the
/// data in the Python string to a Rust UTF-8 string slice.
///
/// This is not always the most appropriate way to compare Python strings, as Python string subclasses
/// may have different equality semantics. In these cases, using [`PyAnyMethods::eq`] is more
/// appropriate, at cost of the additional overhead of a Python method call.
///
/// ```rust
/// # use pyo3::prelude::*;
///
/// # Python::with_gil(|py| {
/// let py_string = PyString::new(py, "foo");
/// // via PartialEq<str>
/// assert_eq!(py_string, "foo");
///
/// // via Python equality
/// assert!(py_string.eq("foo").unwrap());
/// # });
/// ```
#[repr(transparent)]
pub struct PyString(PyAny);

Expand Down Expand Up @@ -490,48 +515,69 @@ impl IntoPy<Py<PyString>> for &'_ Py<PyString> {
}
}

/// Compares whether the data in the Python string is equal to the given UTF8.
///
/// In some cases Python equality might be more appropriate; see the note on [`PyString`].
impl PartialEq<str> for Bound<'_, PyString> {
#[inline]
fn eq(&self, other: &str) -> bool {
self.as_borrowed() == *other
}
}

/// Compares whether the data in the Python string is equal to the given UTF8.
///
/// In some cases Python equality might be more appropriate; see the note on [`PyString`].
impl PartialEq<&'_ str> for Bound<'_, PyString> {
#[inline]
fn eq(&self, other: &&str) -> bool {
self.as_borrowed() == **other
}
}

/// Compares whether the data in the Python string is equal to the given UTF8.
///
/// In some cases Python equality might be more appropriate; see the note on [`PyString`].
impl PartialEq<Bound<'_, PyString>> for str {
#[inline]
fn eq(&self, other: &Bound<'_, PyString>) -> bool {
*self == other.as_borrowed()
}
}

/// Compares whether the data in the Python string is equal to the given UTF8.
///
/// In some cases Python equality might be more appropriate; see the note on [`PyString`].
impl PartialEq<&'_ Bound<'_, PyString>> for str {
#[inline]
fn eq(&self, other: &&Bound<'_, PyString>) -> bool {
*self == other.as_borrowed()
}
}

/// Compares whether the data in the Python string is equal to the given UTF8.
///
/// In some cases Python equality might be more appropriate; see the note on [`PyString`].
impl PartialEq<Bound<'_, PyString>> for &'_ str {
#[inline]
fn eq(&self, other: &Bound<'_, PyString>) -> bool {
**self == other.as_borrowed()
}
}

/// Compares whether the data in the Python string is equal to the given UTF8.
///
/// In some cases Python equality might be more appropriate; see the note on [`PyString`].
impl PartialEq<str> for &'_ Bound<'_, PyString> {
#[inline]
fn eq(&self, other: &str) -> bool {
self.as_borrowed() == other
}
}

/// Compares whether the data in the Python string is equal to the given UTF8.
///
/// In some cases Python equality might be more appropriate; see the note on [`PyString`].
impl PartialEq<str> for Borrowed<'_, '_, PyString> {
#[inline]
fn eq(&self, other: &str) -> bool {
Expand All @@ -551,20 +597,29 @@ impl PartialEq<str> for Borrowed<'_, '_, PyString> {
}
}

/// Compares whether the data in the Python string is equal to the given UTF8.
///
/// In some cases Python equality might be more appropriate; see the note on [`PyString`].
impl PartialEq<&str> for Borrowed<'_, '_, PyString> {
#[inline]
fn eq(&self, other: &&str) -> bool {
*self == **other
}
}

/// Compares whether the data in the Python string is equal to the given UTF8.
///
/// In some cases Python equality might be more appropriate; see the note on [`PyString`].
impl PartialEq<Borrowed<'_, '_, PyString>> for str {
#[inline]
fn eq(&self, other: &Borrowed<'_, '_, PyString>) -> bool {
other == self
}
}

/// Compares whether the data in the Python string is equal to the given UTF8.
///
/// In some cases Python equality might be more appropriate; see the note on [`PyString`].
impl PartialEq<Borrowed<'_, '_, PyString>> for &'_ str {
#[inline]
fn eq(&self, other: &Borrowed<'_, '_, PyString>) -> bool {
Expand Down Expand Up @@ -858,12 +913,20 @@ mod tests {
assert_eq!(s, py_string);
assert_eq!(s, &py_string);

assert_eq!(py_string, *s);
assert_eq!(&py_string, *s);
assert_eq!(*s, py_string);
assert_eq!(*s, &py_string);

let py_string = py_string.as_borrowed();

assert_eq!(py_string, s);
assert_eq!(&py_string, s);
assert_eq!(s, py_string);
assert_eq!(s, &py_string);

assert_eq!(py_string, *s);
assert_eq!(*s, py_string);
})
}
}

0 comments on commit dc113a3

Please sign in to comment.