Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions newsfragments/5555.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Introspection: fix `__new__` return type to be the built object type and not `None`
6 changes: 3 additions & 3 deletions pyo3-macros-backend/src/pyimpl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ use crate::{
};
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
#[cfg(feature = "experimental-inspect")]
use syn::Ident;
use syn::{
parse::{Parse, ParseStream},
spanned::Spanned,
ImplItemFn, Result,
};
#[cfg(feature = "experimental-inspect")]
use syn::{parse_quote, Ident};

/// The mechanism used to collect `#[pymethods]` into the type object
#[derive(Copy, Clone)]
Expand Down Expand Up @@ -411,7 +411,7 @@ fn method_introspection_code(spec: &FnSpec<'_>, parent: &syn::Type, ctx: &Ctx) -
}
FnType::FnNew | FnType::FnNewClass(_) => {
first_argument = Some("cls");
output = syn::ReturnType::Default; // The __new__ Python function return type is None
output = parse_quote!(-> #pyo3_path::PyRef<Self>); // Hack to return Self while implementing IntoPyObject
}
FnType::FnClass(_) => {
first_argument = Some("cls");
Expand Down
14 changes: 7 additions & 7 deletions pytests/stubs/comparisons.pyi
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
class Eq:
def __eq__(self, /, other: Eq) -> bool: ...
def __ne__(self, /, other: Eq) -> bool: ...
def __new__(cls, /, value: int) -> None: ...
def __new__(cls, /, value: int) -> Eq: ...

class EqDefaultNe:
def __eq__(self, /, other: EqDefaultNe) -> bool: ...
def __new__(cls, /, value: int) -> None: ...
def __new__(cls, /, value: int) -> EqDefaultNe: ...

class EqDerived:
def __eq__(self, /, other: EqDerived) -> bool: ...
def __ne__(self, /, other: EqDerived) -> bool: ...
def __new__(cls, /, value: int) -> None: ...
def __new__(cls, /, value: int) -> EqDerived: ...

class Ordered:
def __eq__(self, /, other: Ordered) -> bool: ...
Expand All @@ -19,15 +19,15 @@ class Ordered:
def __le__(self, /, other: Ordered) -> bool: ...
def __lt__(self, /, other: Ordered) -> bool: ...
def __ne__(self, /, other: Ordered) -> bool: ...
def __new__(cls, /, value: int) -> None: ...
def __new__(cls, /, value: int) -> Ordered: ...

class OrderedDefaultNe:
def __eq__(self, /, other: OrderedDefaultNe) -> bool: ...
def __ge__(self, /, other: OrderedDefaultNe) -> bool: ...
def __gt__(self, /, other: OrderedDefaultNe) -> bool: ...
def __le__(self, /, other: OrderedDefaultNe) -> bool: ...
def __lt__(self, /, other: OrderedDefaultNe) -> bool: ...
def __new__(cls, /, value: int) -> None: ...
def __new__(cls, /, value: int) -> OrderedDefaultNe: ...

class OrderedDerived:
def __eq__(self, /, other: OrderedDerived) -> bool: ...
Expand All @@ -37,7 +37,7 @@ class OrderedDerived:
def __le__(self, /, other: OrderedDerived) -> bool: ...
def __lt__(self, /, other: OrderedDerived) -> bool: ...
def __ne__(self, /, other: OrderedDerived) -> bool: ...
def __new__(cls, /, value: int) -> None: ...
def __new__(cls, /, value: int) -> OrderedDerived: ...
def __str__(self, /) -> str: ...

class OrderedRichCmp:
Expand All @@ -47,4 +47,4 @@ class OrderedRichCmp:
def __le__(self, /, other: OrderedRichCmp) -> bool: ...
def __lt__(self, /, other: OrderedRichCmp) -> bool: ...
def __ne__(self, /, other: OrderedRichCmp) -> bool: ...
def __new__(cls, /, value: int) -> None: ...
def __new__(cls, /, value: int) -> OrderedRichCmp: ...
12 changes: 6 additions & 6 deletions pytests/stubs/pyclasses.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ from _typeshed import Incomplete
from typing import Any

class AssertingBaseClass:
def __new__(cls, /, expected_type: Any) -> None: ...
def __new__(cls, /, expected_type: Any) -> AssertingBaseClass: ...

class ClassWithDecorators:
def __new__(cls, /) -> None: ...
def __new__(cls, /) -> ClassWithDecorators: ...
@property
def attr(self, /) -> int: ...
@attr.setter
Expand All @@ -19,13 +19,13 @@ class ClassWithDecorators:
def static_method() -> int: ...

class ClassWithDict:
def __new__(cls, /) -> None: ...
def __new__(cls, /) -> ClassWithDict: ...

class ClassWithoutConstructor: ...

class EmptyClass:
def __len__(self, /) -> int: ...
def __new__(cls, /) -> None: ...
def __new__(cls, /) -> EmptyClass: ...
def method(self, /) -> None: ...

class PlainObject:
Expand All @@ -39,11 +39,11 @@ class PlainObject:
def foo(self, /, value: str) -> None: ...

class PyClassIter:
def __new__(cls, /) -> None: ...
def __new__(cls, /) -> PyClassIter: ...
def __next__(self, /) -> int: ...

class PyClassThreadIter:
def __new__(cls, /) -> None: ...
def __new__(cls, /) -> PyClassThreadIter: ...
def __next__(self, /) -> int: ...

def map_a_class(
Expand Down
Loading