Skip to content

Commit b69c767

Browse files
authored
Introspection: improve exception support (#5710)
- Fixes type hint of exception (do not swap module and name) - When an exception is included in a module, consider it as incomplete (we don't generate stubs for exceptions yet)
1 parent eb2bbbd commit b69c767

File tree

6 files changed

+68
-12
lines changed

6 files changed

+68
-12
lines changed

newsfragments/5710.fixed.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- Correct `PyTypeInfo::TYPE_HINT` on user exceptions that was swapping module and name
2+
- Stub generation: tag modules containing exception as incomplete (we do not generate stubs for exceptions yet)

pyo3-introspection/src/introspection.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,18 +72,25 @@ fn convert_module(
7272
id: &str,
7373
name: &str,
7474
members: &[String],
75-
incomplete: bool,
75+
mut incomplete: bool,
7676
chunks_by_id: &HashMap<&str, &Chunk>,
7777
chunks_by_parent: &HashMap<&str, Vec<&Chunk>>,
7878
) -> Result<Module> {
79-
let (modules, classes, functions, attributes) = convert_members(
80-
members
81-
.iter()
82-
.filter_map(|id| chunks_by_id.get(id.as_str()).copied())
83-
.chain(chunks_by_parent.get(&id).into_iter().flatten().copied()),
84-
chunks_by_id,
85-
chunks_by_parent,
86-
)?;
79+
let mut member_chunks = chunks_by_parent
80+
.get(&id)
81+
.into_iter()
82+
.flatten()
83+
.copied()
84+
.collect::<Vec<_>>();
85+
for member in members {
86+
if let Some(c) = chunks_by_id.get(member.as_str()) {
87+
member_chunks.push(*c);
88+
} else {
89+
incomplete = true; // We don't find an element
90+
}
91+
}
92+
let (modules, classes, functions, attributes) =
93+
convert_members(member_chunks, chunks_by_id, chunks_by_parent)?;
8794

8895
Ok(Module {
8996
name: name.into(),

pytests/src/exception.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
use pyo3::create_exception;
2+
use pyo3::exceptions::PyValueError;
3+
use pyo3::prelude::*;
4+
5+
create_exception!(pytests.exception, MyValueError, PyValueError);
6+
7+
#[pymodule(gil_used = false)]
8+
pub mod exception {
9+
use pyo3::exceptions::PyValueError;
10+
use pyo3::prelude::*;
11+
12+
#[pymodule_export]
13+
use super::MyValueError;
14+
15+
#[pyfunction]
16+
fn raise_my_value_error() -> PyResult<()> {
17+
Err(MyValueError::new_err("error"))
18+
}
19+
20+
#[pyfunction]
21+
fn return_value_error<'py>(py: Python<'py>) -> PyResult<Bound<'py, PyValueError>> {
22+
Ok(PyValueError::new_err("error")
23+
.into_pyobject(py)?
24+
.cast_into()?)
25+
}
26+
27+
#[pyfunction]
28+
fn return_my_value_error<'py>(py: Python<'py>) -> PyResult<Bound<'py, MyValueError>> {
29+
Ok(MyValueError::new_err("error")
30+
.into_pyobject(py)?
31+
.cast_into()?)
32+
}
33+
34+
#[pyfunction]
35+
fn return_pyerr() -> PyErr {
36+
MyValueError::new_err("error")
37+
}
38+
}

pytests/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ mod consts;
99
pub mod datetime;
1010
pub mod dict_iter;
1111
pub mod enums;
12+
mod exception;
1213
pub mod misc;
1314
pub mod objstore;
1415
pub mod othermod;
@@ -27,8 +28,8 @@ mod pyo3_pytests {
2728
use buf_and_str::buf_and_str;
2829
#[pymodule_export]
2930
use {
30-
comparisons::comparisons, consts::consts, enums::enums, pyclasses::pyclasses,
31-
pyfunctions::pyfunctions, subclassing::subclassing,
31+
comparisons::comparisons, consts::consts, enums::enums, exception::exception,
32+
pyclasses::pyclasses, pyfunctions::pyfunctions, subclassing::subclassing,
3233
};
3334

3435
// Inserting to sys.modules allows importing submodules nicely from Python

pytests/stubs/exception.pyi

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from _typeshed import Incomplete
2+
from pytests.exception import MyValueError
3+
4+
def raise_my_value_error() -> None: ...
5+
def return_my_value_error() -> MyValueError: ...
6+
def return_pyerr() -> BaseException: ...
7+
def return_value_error() -> ValueError: ...
8+
def __getattr__(name: str) -> Incomplete: ...

src/exceptions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,8 @@ macro_rules! create_exception_type_object {
207207
$crate::pyobject_native_type_core!(
208208
$name,
209209
$name::type_object_raw,
210-
stringify!($name),
211210
stringify!($module),
211+
stringify!($name),
212212
#module=::std::option::Option::Some(stringify!($module))
213213
);
214214

0 commit comments

Comments
 (0)