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