Skip to content

Commit

Permalink
Rename name to qualname and full_name to name to better match Python
Browse files Browse the repository at this point in the history
  • Loading branch information
adamreichold committed Dec 19, 2023
1 parent 59ba5b9 commit 93c70f1
Show file tree
Hide file tree
Showing 9 changed files with 43 additions and 19 deletions.
2 changes: 1 addition & 1 deletion guide/src/class/numeric.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ impl Number {

fn __repr__(slf: &PyCell<Self>) -> PyResult<String> {
// Get the class name dynamically in case `Number` is subclassed
let class_name: &str = slf.get_type().name()?;
let class_name: String = slf.get_type().qualname()?;
Ok(format!("{}({})", class_name, slf.borrow().0))
}

Expand Down
4 changes: 2 additions & 2 deletions guide/src/class/object.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ the subclass name. This is typically done in Python code by accessing
impl Number {
fn __repr__(slf: &PyCell<Self>) -> PyResult<String> {
// This is the equivalent of `self.__class__.__name__` in Python.
let class_name: &str = slf.get_type().name()?;
let class_name: String = slf.get_type().qualname()?;
// To access fields of the Rust struct, we need to borrow the `PyCell`.
Ok(format!("{}({})", class_name, slf.borrow().0))
}
Expand Down Expand Up @@ -263,7 +263,7 @@ impl Number {
}

fn __repr__(slf: &PyCell<Self>) -> PyResult<String> {
let class_name: &str = slf.get_type().name()?;
let class_name: String = slf.get_type().qualname()?;
Ok(format!("{}({})", class_name, slf.borrow().0))
}

Expand Down
3 changes: 3 additions & 0 deletions guide/src/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ Python::with_gil(|py| {
});
```

### `PyType::name` is now `PyType::qualname`

`PyType::name` has been renamed to `PyType::qualname` to indicate that it does indeed return the [qualified name](), matching the `__qualname__` attribute. The newly added `PyType::name` yields the full name including the module name now which corresponds to `__module__.__name__` on the level of attributes.

## from 0.19.* to 0.20

Expand Down
1 change: 0 additions & 1 deletion newsfragments/3660.added.md

This file was deleted.

1 change: 1 addition & 0 deletions newsfragments/3660.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`PyType::name` is now `PyType::qualname` whereas `PyType::name` efficiently accesses the full name which includes the module name.
2 changes: 1 addition & 1 deletion pytests/src/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ fn issue_219() {

#[pyfunction]
fn get_type_full_name(obj: &PyAny) -> PyResult<Cow<'_, str>> {
obj.get_type().full_name()
obj.get_type().name()
}

#[pymodule]
Expand Down
1 change: 1 addition & 0 deletions src/err/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,7 @@ impl PyErrArguments for PyDowncastErrorArguments {
self.from
.as_ref(py)
.name()
.as_deref()
.unwrap_or("<failed to extract type name>"),
self.to
)
Expand Down
40 changes: 30 additions & 10 deletions src/types/typeobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,28 @@ impl PyType {
py.from_borrowed_ptr(p as *mut ffi::PyObject)
}

/// Gets the name of the `PyType`.
pub fn name(&self) -> PyResult<&str> {
self.getattr(intern!(self.py(), "__qualname__"))?.extract()
/// Gets the [qualified name](https://docs.python.org/3/glossary.html#term-qualified-name) of the `PyType`.
pub fn qualname(&self) -> PyResult<String> {
#[cfg(any(Py_LIMITED_API, PyPy, not(Py_3_11)))]
let name = self.getattr(intern!(self.py(), "__qualname__"))?.extract();

#[cfg(not(any(Py_LIMITED_API, PyPy, not(Py_3_11))))]
let name = {
use crate::ffi_ptr_ext::FfiPtrExt;
use crate::types::any::PyAnyMethods;

let obj = unsafe {
ffi::PyType_GetQualName(self.as_type_ptr()).assume_owned_or_err(self.py())?
};

obj.extract()
};

name
}

/// Gets the full name, which includes the module, of the `PyType`.
pub fn full_name(&self) -> PyResult<Cow<'_, str>> {
pub fn name(&self) -> PyResult<Cow<'_, str>> {
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
{
let name = unsafe { CStr::from_ptr((*self.as_type_ptr()).tp_name) }.to_str()?;
Expand All @@ -49,13 +64,18 @@ impl PyType {

#[cfg(any(Py_LIMITED_API, PyPy))]
{
let module = self
.getattr(intern!(self.py(), "__module__"))?
.extract::<&str>()?;
let module = self.getattr(intern!(self.py(), "__module__"))?;

#[cfg(not(Py_3_11))]
let name = self.getattr(intern!(self.py(), "__name__"))?;

#[cfg(Py_3_11)]
let name = {
use crate::ffi_ptr_ext::FfiPtrExt;
use crate::types::any::PyAnyMethods;

let name = self
.getattr(intern!(self.py(), "__name__"))?
.extract::<&str>()?;
unsafe { ffi::PyType_GetName(self.as_type_ptr()).assume_owned_or_err(self.py())? }
};

Ok(Cow::Owned(format!("{}.{}", module, name)))
}
Expand Down
8 changes: 4 additions & 4 deletions tests/test_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,14 @@ impl ClassMethod {
#[classmethod]
/// Test class method.
fn method(cls: &PyType) -> PyResult<String> {
Ok(format!("{}.method()!", cls.name()?))
Ok(format!("{}.method()!", cls.qualname()?))
}

#[classmethod]
fn method_owned(cls: Py<PyType>) -> PyResult<String> {
Ok(format!(
"{}.method_owned()!",
Python::with_gil(|gil| cls.as_ref(gil).name().map(ToString::to_string))?
Python::with_gil(|gil| cls.as_ref(gil).qualname())?
))
}
}
Expand Down Expand Up @@ -109,7 +109,7 @@ struct ClassMethodWithArgs {}
impl ClassMethodWithArgs {
#[classmethod]
fn method(cls: &PyType, input: &PyString) -> PyResult<String> {
Ok(format!("{}.method({})", cls.name()?, input))
Ok(format!("{}.method({})", cls.qualname()?, input))
}
}

Expand Down Expand Up @@ -937,7 +937,7 @@ impl r#RawIdents {
fn test_raw_idents() {
Python::with_gil(|py| {
let raw_idents_type = py.get_type::<r#RawIdents>();
assert_eq!(raw_idents_type.name().unwrap(), "RawIdents");
assert_eq!(raw_idents_type.qualname().unwrap(), "RawIdents");
py_run!(
py,
raw_idents_type,
Expand Down

0 comments on commit 93c70f1

Please sign in to comment.