1#![allow(deprecated)]
2
3mod custom_exceptions;
4mod manual_overloading;
5mod manual_submit;
6mod overloading;
7mod overriding;
8mod rust_type_marker;
9mod skip_stub_type_test;
10
11use custom_exceptions::*;
12use manual_overloading::*;
13use manual_submit::*;
14use overloading::*;
15use overriding::*;
16use rust_type_marker::*;
17use skip_stub_type_test::*;
18
19#[cfg_attr(target_os = "macos", doc = include_str!("../../../README.md"))]
20mod readme {}
21
22use ahash::RandomState;
23use pyo3::{prelude::*, types::*};
24use pyo3_stub_gen::{define_stub_info_gatherer, derive::*, module_doc, module_variable};
25use rust_decimal::Decimal;
26use std::{collections::HashMap, path::PathBuf};
27
28#[gen_stub_pyfunction]
30#[pyfunction]
31fn sum(v: Vec<u32>) -> u32 {
32 v.iter().sum()
33}
34
35#[gen_stub_pyfunction]
36#[pyfunction]
37fn read_dict(dict: HashMap<usize, HashMap<usize, usize>>) {
38 for (k, v) in dict {
39 for (k2, v2) in v {
40 println!("{k} {k2} {v2}");
41 }
42 }
43}
44
45#[gen_stub_pyfunction]
46#[pyfunction]
47fn create_dict(n: usize) -> HashMap<usize, Vec<usize>> {
48 let mut dict = HashMap::new();
49 for i in 0..n {
50 dict.insert(i, (0..i).collect());
51 }
52 dict
53}
54
55#[gen_stub_pyfunction]
57#[pyfunction]
58fn add_decimals(a: Decimal, b: Decimal) -> Decimal {
59 a + b
60}
61
62#[gen_stub_pyclass]
63#[pyclass(extends=PyDate)]
64struct MyDate;
65
66#[gen_stub_pyclass]
67#[pyclass(subclass)]
68#[derive(Debug)]
69struct A {
70 #[gen_stub(default = A::default().x)]
71 #[pyo3(get, set)]
72 x: usize,
73
74 #[pyo3(get)]
75 y: usize,
76}
77
78impl Default for A {
79 fn default() -> Self {
80 Self { x: 2, y: 10 }
81 }
82}
83
84#[gen_stub_pymethods]
85#[pymethods]
86impl A {
87 #[new]
89 fn new(x: usize) -> Self {
90 Self { x, y: 10 }
91 }
92 #[classattr]
94 #[pyo3(name = "NUM")]
95 const NUM1: usize = 2;
96
97 #[deprecated(since = "1.0.0", note = "This constant is deprecated")]
99 #[classattr]
100 const NUM3: usize = 3;
101 #[expect(non_snake_case)]
103 #[classattr]
104 fn NUM2() -> usize {
105 2
106 }
107 #[classmethod]
108 fn classmethod_test1(cls: &Bound<'_, PyType>) {
109 _ = cls;
110 }
111
112 #[deprecated(since = "1.0.0", note = "This classmethod is deprecated")]
113 #[classmethod]
114 fn deprecated_classmethod(cls: &Bound<'_, PyType>) {
115 _ = cls;
116 }
117
118 #[classmethod]
119 fn classmethod_test2(_: &Bound<'_, PyType>) {}
120
121 fn show_x(&self) {
122 println!("x = {}", self.x);
123 }
124
125 fn ref_test<'a>(&self, x: Bound<'a, PyDict>) -> Bound<'a, PyDict> {
126 x
127 }
128
129 async fn async_get_x(&self) -> usize {
130 self.x
131 }
132
133 #[gen_stub(skip)]
134 fn need_skip(&self) {}
135
136 #[deprecated(since = "1.0.0", note = "This method is deprecated")]
137 fn deprecated_method(&self) {
138 println!("This method is deprecated");
139 }
140
141 #[deprecated(since = "1.0.0", note = "This method is deprecated")]
142 #[getter]
143 fn deprecated_getter(&self) -> usize {
144 self.x
145 }
146
147 #[deprecated(since = "1.0.0", note = "This setter is deprecated")]
148 #[setter]
149 fn set_y(&mut self, value: usize) {
150 self.y = value;
151 }
152
153 #[deprecated(since = "1.0.0", note = "This staticmethod is deprecated")]
154 #[staticmethod]
155 fn deprecated_staticmethod() -> usize {
156 42
157 }
158}
159
160#[gen_stub_pyfunction]
161#[pyfunction]
162#[pyo3(signature = (x = 2))]
163fn create_a(x: usize) -> A {
164 A { x, y: 10 }
165}
166
167#[gen_stub_pyclass]
168#[pyclass(extends=A)]
169#[derive(Debug)]
170struct B;
171
172#[derive(Debug)]
174struct C {
175 x: usize,
176}
177#[gen_stub_pyfunction]
178#[pyfunction(signature = (c=None))]
179fn print_c(c: Option<C>) {
180 if let Some(c) = c {
181 println!("{}", c.x);
182 } else {
183 println!("None");
184 }
185}
186impl FromPyObject<'_> for C {
187 fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult<Self> {
188 Ok(C { x: ob.extract()? })
189 }
190}
191impl pyo3_stub_gen::PyStubType for C {
192 fn type_output() -> pyo3_stub_gen::TypeInfo {
193 usize::type_output()
194 }
195}
196
197#[gen_stub_pyfunction]
199#[pyfunction]
200fn str_len(x: &str) -> PyResult<usize> {
201 Ok(x.len())
202}
203
204#[gen_stub_pyfunction]
205#[pyfunction]
206fn echo_path(path: PathBuf) -> PyResult<PathBuf> {
207 Ok(path)
208}
209
210#[gen_stub_pyfunction]
211#[pyfunction]
212fn ahash_dict() -> HashMap<String, i32, RandomState> {
213 let mut map: HashMap<String, i32, RandomState> = HashMap::with_hasher(RandomState::new());
214 map.insert("apple".to_string(), 3);
215 map.insert("banana".to_string(), 2);
216 map.insert("orange".to_string(), 5);
217 map
218}
219
220#[gen_stub_pyclass_enum]
221#[pyclass(eq, eq_int)]
222#[derive(Debug, Clone, PartialEq, Eq, Hash)]
223pub enum Number {
224 #[pyo3(name = "FLOAT")]
225 Float,
226 #[pyo3(name = "INTEGER")]
227 Integer,
228}
229
230#[gen_stub_pyclass_enum]
231#[pyclass(eq, eq_int)]
232#[pyo3(rename_all = "UPPERCASE")]
233#[derive(Debug, Clone, PartialEq, Eq, Hash)]
234pub enum NumberRenameAll {
235 Float,
237 Integer,
238}
239
240#[gen_stub_pyclass_complex_enum]
241#[pyclass]
242#[pyo3(rename_all = "UPPERCASE")]
243#[derive(Debug, Clone)]
244pub enum NumberComplex {
245 Float(f64),
247 #[pyo3(constructor = (int=2))]
249 Integer {
250 int: i32,
252 },
253}
254
255#[gen_stub_pyclass_complex_enum]
258#[pyclass]
259enum Shape1 {
260 Circle { radius: f64 },
261 Rectangle { width: f64, height: f64 },
262 RegularPolygon(u32, f64),
263 Nothing {},
264}
265
266#[gen_stub_pyclass_complex_enum]
269#[pyclass]
270enum Shape2 {
271 #[pyo3(constructor = (radius=1.0))]
272 Circle {
273 radius: f64,
274 },
275 #[pyo3(constructor = (*, width, height))]
276 Rectangle {
277 width: f64,
278 height: f64,
279 },
280 #[pyo3(constructor = (side_count, radius=1.0))]
281 RegularPolygon {
282 side_count: u32,
283 radius: f64,
284 },
285 Nothing {},
286}
287
288#[gen_stub_pymethods]
289#[pymethods]
290impl Number {
291 #[getter]
292 fn is_float(&self) -> bool {
294 matches!(self, Self::Float)
295 }
296
297 #[getter]
298 fn is_integer(&self) -> bool {
300 matches!(self, Self::Integer)
301 }
302}
303
304#[gen_stub_pyclass]
305#[pyclass]
306pub struct DecimalHolder {
307 #[pyo3(get)]
308 value: Decimal,
309}
310
311#[gen_stub_pymethods]
312#[pymethods]
313impl DecimalHolder {
314 #[new]
315 fn new(value: Decimal) -> Self {
316 Self { value }
317 }
318}
319
320module_variable!("pure", "MY_CONSTANT1", usize);
321module_variable!("pure", "MY_CONSTANT2", usize, 123);
322
323#[gen_stub_pyfunction]
324#[pyfunction]
325async fn async_num() -> i32 {
326 123
327}
328
329#[gen_stub_pyfunction]
330#[pyfunction]
331#[deprecated(since = "1.0.0", note = "This function is deprecated")]
332fn deprecated_function() {
333 println!("This function is deprecated");
334}
335
336#[gen_stub_pyfunction]
338#[pyfunction]
339#[pyo3(signature = (num = Number::Float))]
340fn default_value(num: Number) -> Number {
341 num
342}
343
344#[gen_stub_pyclass]
348#[pyclass(eq, ord)]
349#[derive(Debug, Clone, PartialEq, PartialOrd)]
350pub struct ComparableStruct {
351 #[pyo3(get)]
352 pub value: i32,
353}
354
355#[gen_stub_pymethods]
356#[pymethods]
357impl ComparableStruct {
358 #[new]
359 fn new(value: i32) -> Self {
360 Self { value }
361 }
362}
363
364#[gen_stub_pyclass]
366#[pyclass(eq, hash, frozen, str)]
367#[derive(Debug, Clone, Hash, PartialEq)]
368pub struct HashableStruct {
369 #[pyo3(get)]
370 pub name: String,
371}
372
373impl std::fmt::Display for HashableStruct {
374 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
375 write!(f, "HashableStruct({})", self.name)
376 }
377}
378
379#[gen_stub_pymethods]
380#[pymethods]
381impl HashableStruct {
382 #[new]
383 fn new(name: String) -> Self {
384 Self { name }
385 }
386}
387
388#[gen_stub_pyfunction]
390#[pyfunction]
391#[pyo3(signature = (*args))]
392fn func_with_star_arg_typed(
393 #[gen_stub(override_type(type_repr = "str"))] args: &Bound<PyTuple>,
394) -> String {
395 args.to_string()
396}
397
398#[gen_stub_pyfunction]
400#[pyfunction]
401#[pyo3(signature = (*args))]
402fn func_with_star_arg(args: &Bound<PyTuple>) -> String {
403 args.to_string()
404}
405
406#[gen_stub_pyfunction]
408#[pyfunction]
409#[pyo3(signature = (**kwargs))]
410fn func_with_kwargs(kwargs: Option<&Bound<PyDict>>) -> bool {
411 kwargs.is_some()
412}
413
414module_doc!("pure", "Document for {} ...", env!("CARGO_PKG_NAME"));
415
416#[pymodule]
418fn pure(m: &Bound<PyModule>) -> PyResult<()> {
419 m.add("MY_CONSTANT1", 19937)?;
420 m.add("MY_CONSTANT2", 123)?;
421 m.add_class::<A>()?;
422 m.add_class::<B>()?;
423 m.add_class::<MyDate>()?;
424 m.add_class::<Number>()?;
425 m.add_class::<NumberRenameAll>()?;
426 m.add_class::<NumberComplex>()?;
427 m.add_class::<Shape1>()?;
428 m.add_class::<Shape2>()?;
429 m.add_class::<ManualSubmit>()?;
430 m.add_class::<PartialManualSubmit>()?;
431 m.add_class::<OverrideType>()?;
432 m.add_class::<ComparableStruct>()?;
433 m.add_class::<HashableStruct>()?;
434 m.add_class::<DecimalHolder>()?;
435 m.add_class::<DataContainer>()?;
436 m.add_class::<Placeholder>()?;
437 m.add_class::<Calculator>()?;
438 m.add_class::<InstanceValue>()?;
439 m.add_class::<Problem>()?;
440 m.add_class::<CustomStubType>()?;
441 m.add_class::<NormalClass>()?;
442 m.add_class::<CustomEnum>()?;
443 m.add_class::<CustomComplexEnum>()?;
444 m.add_function(wrap_pyfunction!(sum, m)?)?;
445 m.add_function(wrap_pyfunction!(create_dict, m)?)?;
446 m.add_function(wrap_pyfunction!(read_dict, m)?)?;
447 m.add_function(wrap_pyfunction!(create_a, m)?)?;
448 m.add_function(wrap_pyfunction!(print_c, m)?)?;
449 m.add_function(wrap_pyfunction!(str_len, m)?)?;
450 m.add_function(wrap_pyfunction!(echo_path, m)?)?;
451 m.add_function(wrap_pyfunction!(ahash_dict, m)?)?;
452 m.add_function(wrap_pyfunction!(async_num, m)?)?;
453 m.add_function(wrap_pyfunction!(deprecated_function, m)?)?;
454 m.add_function(wrap_pyfunction!(default_value, m)?)?;
455 m.add_function(wrap_pyfunction!(fn_override_type, m)?)?;
456 m.add_function(wrap_pyfunction!(fn_with_python_param, m)?)?;
457 m.add_function(wrap_pyfunction!(fn_with_python_stub, m)?)?;
458 m.add_function(wrap_pyfunction!(overload_example_1, m)?)?;
459 m.add_function(wrap_pyfunction!(overload_example_2, m)?)?;
460 m.add_function(wrap_pyfunction!(as_tuple, m)?)?;
461 m.add_function(wrap_pyfunction!(manual_overload_example_1, m)?)?;
462 m.add_function(wrap_pyfunction!(manual_overload_example_2, m)?)?;
463 m.add_function(wrap_pyfunction!(manual_overload_as_tuple, m)?)?;
464 m.add_function(wrap_pyfunction!(add_decimals, m)?)?;
465 m.add_function(wrap_pyfunction!(process_container, m)?)?;
466 m.add_function(wrap_pyfunction!(sum_list, m)?)?;
467 m.add_function(wrap_pyfunction!(create_containers, m)?)?;
468 m.add_function(wrap_pyfunction!(func_with_star_arg, m)?)?;
470 m.add_function(wrap_pyfunction!(func_with_star_arg_typed, m)?)?;
471 m.add_function(wrap_pyfunction!(func_with_kwargs, m)?)?;
472
473 m.add_function(wrap_pyfunction!(test_type_ignore_specific, m)?)?;
475 m.add_function(wrap_pyfunction!(test_type_ignore_all, m)?)?;
476 m.add_function(wrap_pyfunction!(test_type_ignore_pyright, m)?)?;
477 m.add_function(wrap_pyfunction!(test_type_ignore_custom, m)?)?;
478 m.add_function(wrap_pyfunction!(test_type_ignore_no_comment_all, m)?)?;
479 m.add_function(wrap_pyfunction!(test_type_ignore_no_comment_specific, m)?)?;
480
481 m.add("MyError", m.py().get_type::<MyError>())?;
483 m.add_class::<NotIntError>()?;
484
485 m.add_class::<TypeIgnoreTest>()?;
487 Ok(())
488}
489
490#[gen_stub_pyfunction]
492#[gen_stub(type_ignore = ["arg-type", "return-value"])]
493#[pyfunction]
494fn test_type_ignore_specific() -> i32 {
495 42
496}
497
498#[gen_stub_pyfunction]
500#[gen_stub(type_ignore)]
501#[pyfunction]
502fn test_type_ignore_all() -> i32 {
503 42
504}
505
506#[gen_stub_pyfunction]
508#[gen_stub(type_ignore = ["reportGeneralTypeIssues", "reportReturnType"])]
509#[pyfunction]
510fn test_type_ignore_pyright() -> i32 {
511 42
512}
513
514#[gen_stub_pyfunction]
516#[gen_stub(type_ignore = ["custom-rule", "attr-defined"])]
517#[pyfunction]
518fn test_type_ignore_custom() -> i32 {
519 42
520}
521
522#[gen_stub_pyfunction]
527#[gen_stub(type_ignore)]
528#[pyfunction]
529fn test_type_ignore_no_comment_all() -> i32 {
530 42
531}
532
533#[gen_stub_pyfunction]
534#[gen_stub(type_ignore=["arg-type", "reportIncompatibleMethodOverride"])]
535#[pyfunction]
536fn test_type_ignore_no_comment_specific() -> i32 {
537 42
538}
539
540#[gen_stub_pyclass]
542#[pyclass]
543pub struct TypeIgnoreTest {}
544
545#[gen_stub_pymethods]
546#[pymethods]
547impl TypeIgnoreTest {
548 #[new]
549 fn new() -> Self {
550 Self {}
551 }
552
553 #[gen_stub(type_ignore = ["union-attr", "return-value"])]
555 fn test_method_ignore(&self, value: i32) -> i32 {
556 value * 2
557 }
558
559 #[gen_stub(type_ignore)]
561 fn test_method_all_ignore(&self) -> i32 {
562 42
563 }
564}
565
566define_stub_info_gatherer!(stub_info);
567
568#[cfg(test)]
570mod test {
571 #[test]
572 fn test() {
573 assert_eq!(2 + 2, 4);
574 }
575}