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
31 changes: 31 additions & 0 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -1485,6 +1485,37 @@ def _ensure_directory_equals(expected_dir: Path, actual_dir: Path):
)


@nox.session(name="test-introspection-backward-compatibility")
def test_introspection_backward_compatibility(session: nox.Session):
session.install("maturin")
session.install("ruff")
for crate in Path("pytests/backward-compatibility").iterdir():
if not crate.is_dir():
continue
with tempfile.TemporaryDirectory() as stub_dir:
cargo_toml_file = crate / "Cargo.toml"
_run(session, "maturin", "develop", "-m", str(cargo_toml_file))
package_name = toml.loads(cargo_toml_file.read_text())["lib"]["name"]
lib_file = session.run(
"python",
"-c",
f"import {package_name}; print({package_name}.{package_name}.__file__)",
silent=True,
).strip()
_run_cargo(
session,
"run",
"-p",
"pyo3-introspection",
"--",
lib_file,
package_name,
stub_dir,
)
_run(session, "ruff", "format", stub_dir)
_ensure_directory_equals(Path(stub_dir), crate / "stubs")


@lru_cache()
def _get_rust_info() -> Tuple[str, ...]:
output = _get_output("rustc", "-vV")
Expand Down
16 changes: 16 additions & 0 deletions pytests/backward-compatibility/0.28/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[workspace]

[package]
name = "pyo3-backward-compatibility-028"
version = "0.0.0"
description = "Backward compatibility tests for pyo3-introspection"
edition = "2021"
publish = false
rust-version = "1.83"

[dependencies]
pyo3 = { version = "0.28", features = ["experimental-inspect"] }

[lib]
name = "pyo3_backward_compatibility_028"
crate-type = ["cdylib"]
87 changes: 87 additions & 0 deletions pytests/backward-compatibility/0.28/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use pyo3::prelude::*;

/// Some module
#[pymodule]
mod pyo3_backward_compatibility_028 {
use pyo3::prelude::*;
use pyo3::types::{PyDict, PyTuple, PyType};
use std::collections::HashMap;
use std::path::PathBuf;

/// Some const
#[pymodule_export]
const CONST: usize = 0;

/// Some function
#[pyfunction]
#[pyo3(signature = (_arg1, /, _arg2: "int", *_args, _foo = None, **_kwargs))]
fn some_fn(
_arg1: (usize, Vec<PathBuf>, HashMap<String, usize>),
_arg2: Bound<'_, PyAny>,
_args: Bound<'_, PyTuple>,
_foo: Option<&str>,
_kwargs: Option<Bound<'_, PyDict>>,
) -> PyResult<()> {
Ok(())
}

/// Some class
#[pyclass(eq, ord, extends = PyDict)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
struct MyClass {
// TODO: parent class
value: usize,
}

#[pymethods]
impl MyClass {
#[expect(dead_code)]
const PI: Self = Self { value: 3 };

#[new]
fn new(value: usize) -> Self {
Self { value }
}

#[getter]
fn value(&self) -> usize {
self.value
}

#[setter]
fn set_value(&mut self, value: usize) {
self.value = value;
}

#[deleter]
fn delete_value(&self) {}

#[staticmethod]
fn static_method() -> bool {
true
}

#[classmethod]
fn class_method(_cls: Bound<'_, PyType>) -> &'static str {
"foo"
}

#[classattr]
fn class_attr() -> f32 {
0.
}
}

#[pymodule]
mod submodule {
use super::*;

#[pyclass(subclass)]
struct Class2 {}
}

#[pymodule_init]
fn init(_m: &Bound<'_, PyModule>) -> PyResult<()> {
Ok(())
}
}
39 changes: 39 additions & 0 deletions pytests/backward-compatibility/0.28/stubs/__init__.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from _typeshed import Incomplete
from collections.abc import Sequence
from os import PathLike
from typing import Final, final

CONST: Final = 0

@final
class MyClass(dict):
def __eq__(self, /, other: MyClass) -> bool: ...
def __ge__(self, /, other: MyClass) -> bool: ...
def __gt__(self, /, other: MyClass) -> bool: ...
def __le__(self, /, other: MyClass) -> bool: ...
def __lt__(self, /, other: MyClass) -> bool: ...
def __ne__(self, /, other: MyClass) -> bool: ...
def __new__(cls, /, value: int) -> MyClass: ...
@classmethod
@property
def class_attr(cls, /) -> float: ...
@classmethod
def class_method(cls, /) -> str: ...
@staticmethod
def static_method() -> bool: ...
@property
def value(self, /) -> int: ...
@value.deleter
def value(self, /) -> None: ...
@value.setter
def value(self, /, value: int) -> None: ...

def some_fn(
_arg1: tuple[int, Sequence[str | PathLike], dict[str, int]],
/,
_arg2: "int",
*_args,
_foo: str | None = None,
**_kwargs,
) -> None: ...
def __getattr__(name: str) -> Incomplete: ...
1 change: 1 addition & 0 deletions pytests/backward-compatibility/0.28/stubs/submodule.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
class Class2: ...
16 changes: 16 additions & 0 deletions pytests/backward-compatibility/0.29/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[workspace]

[package]
name = "pyo3-backward-compatibility-029"
version = "0.0.0"
description = "Backward compatibility tests for pyo3-introspection"
edition = "2021"
publish = false
rust-version = "1.83"

[dependencies]
pyo3 = { path = "../../..", features = ["experimental-inspect"] }

[lib]
name = "pyo3_backward_compatibility_029"
crate-type = ["cdylib"]
87 changes: 87 additions & 0 deletions pytests/backward-compatibility/0.29/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use pyo3::prelude::*;

/// Some module
#[pymodule]
mod pyo3_backward_compatibility_029 {
use pyo3::prelude::*;
use pyo3::types::{PyDict, PyTuple, PyType};
use std::collections::HashMap;
use std::path::PathBuf;

/// Some const
#[pymodule_export]
const CONST: usize = 0;

/// Some function
#[pyfunction]
#[pyo3(signature = (_arg1, /, _arg2: "int", *_args, _foo = None, **_kwargs))]
fn some_fn(
_arg1: (usize, Vec<PathBuf>, HashMap<String, usize>),
_arg2: Bound<'_, PyAny>,
_args: Bound<'_, PyTuple>,
_foo: Option<&str>,
_kwargs: Option<Bound<'_, PyDict>>,
) -> PyResult<()> {
Ok(())
}

/// Some class
#[pyclass(eq, ord, extends = PyDict)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
struct MyClass {
// TODO: parent class
value: usize,
}

#[pymethods]
impl MyClass {
#[expect(dead_code)]
const PI: Self = Self { value: 3 };

#[new]
fn new(value: usize) -> Self {
Self { value }
}

#[getter]
fn value(&self) -> usize {
self.value
}

#[setter]
fn set_value(&mut self, value: usize) {
self.value = value;
}

#[deleter]
fn delete_value(&self) {}

#[staticmethod]
fn static_method() -> bool {
true
}

#[classmethod]
fn class_method(_cls: Bound<'_, PyType>) -> &'static str {
"foo"
}

#[classattr]
fn class_attr() -> f32 {
0.
}
}

#[pymodule]
mod submodule {
use super::*;

#[pyclass(subclass)]
struct Class2 {}
}

#[pymodule_init]
fn init(_m: &Bound<'_, PyModule>) -> PyResult<()> {
Ok(())
}
}
52 changes: 52 additions & 0 deletions pytests/backward-compatibility/0.29/stubs/__init__.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""
Some module
"""

from _typeshed import Incomplete
from collections.abc import Sequence
from os import PathLike
from typing import Final, final

CONST: Final = 0
"""
Some const
"""

@final
class MyClass(dict):
"""
Some class
"""

class_attr: Final[float]
def __eq__(self, /, other: object) -> bool: ...
def __ge__(self, /, other: object) -> bool: ...
def __gt__(self, /, other: object) -> bool: ...
def __le__(self, /, other: object) -> bool: ...
def __lt__(self, /, other: object) -> bool: ...
def __ne__(self, /, other: object) -> bool: ...
def __new__(cls, /, value: int) -> MyClass: ...
@classmethod
def class_method(cls, /) -> str: ...
@staticmethod
def static_method() -> bool: ...
@property
def value(self, /) -> int: ...
@value.deleter
def value(self, /) -> None: ...
@value.setter
def value(self, /, value: int) -> None: ...

def some_fn(
_arg1: tuple[int, Sequence[str | PathLike[str]], dict[str, int]],
/,
_arg2: "int",
*_args,
_foo: str | None = None,
**_kwargs,
) -> None:
"""
Some function
"""

def __getattr__(name: str) -> Incomplete: ...
1 change: 1 addition & 0 deletions pytests/backward-compatibility/0.29/stubs/submodule.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
class Class2: ...
1 change: 1 addition & 0 deletions pytests/backward-compatibility/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
A set of crates to test `pyo3-introspection` backward compatibility support.
Loading