pyo3_stub_gen/generate/
function.rs1use crate::{generate::*, rule_name::RuleName, type_info::*, TypeInfo};
2use itertools::Itertools;
3use std::fmt;
4
5#[derive(Debug, Clone, PartialEq)]
7pub struct FunctionDef {
8 pub name: &'static str,
9 pub args: Vec<Arg>,
10 pub r#return: TypeInfo,
11 pub doc: &'static str,
12 pub is_async: bool,
13 pub deprecated: Option<DeprecatedInfo>,
14 pub type_ignored: Option<IgnoreTarget>,
15}
16
17impl Import for FunctionDef {
18 fn import(&self) -> HashSet<ModuleRef> {
19 let mut import = self.r#return.import.clone();
20 for arg in &self.args {
21 import.extend(arg.import().into_iter());
22 }
23 if self.deprecated.is_some() {
25 import.insert("typing_extensions".into());
26 }
27 import
28 }
29}
30
31impl From<&PyFunctionInfo> for FunctionDef {
32 fn from(info: &PyFunctionInfo) -> Self {
33 Self {
34 name: info.name,
35 args: info.args.iter().map(Arg::from).collect(),
36 r#return: (info.r#return)(),
37 doc: info.doc,
38 is_async: info.is_async,
39 deprecated: info.deprecated.clone(),
40 type_ignored: info.type_ignored,
41 }
42 }
43}
44
45impl fmt::Display for FunctionDef {
46 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
47 if let Some(deprecated) = &self.deprecated {
49 writeln!(f, "{deprecated}")?;
50 }
51
52 let async_ = if self.is_async { "async " } else { "" };
53 write!(f, "{async_}def {}(", self.name)?;
54 for (i, arg) in self.args.iter().enumerate() {
55 write!(f, "{arg}")?;
56 if i != self.args.len() - 1 {
57 write!(f, ", ")?;
58 }
59 }
60 write!(f, ") -> {}:", self.r#return)?;
61
62 let type_ignore_comment = if let Some(target) = &self.type_ignored {
64 match target {
65 IgnoreTarget::All => Some(" # type: ignore".to_string()),
66 IgnoreTarget::Specified(rules) => {
67 let rules_str = rules
68 .iter()
69 .map(|r| {
70 let result = r.parse::<RuleName>().unwrap();
71 if let RuleName::Custom(custom) = &result {
72 log::warn!("Unknown custom rule name '{custom}' used in type ignore. Ensure this is intended.");
73 }
74 result
75 })
76 .join(",");
77 Some(format!(" # type: ignore[{}]", rules_str))
78 }
79 }
80 } else {
81 None
82 };
83
84 let doc = self.doc;
85 if !doc.is_empty() {
86 if let Some(comment) = &type_ignore_comment {
88 write!(f, "{}", comment)?;
89 }
90 writeln!(f)?;
91 docstring::write_docstring(f, self.doc, indent())?;
92 } else {
93 write!(f, " ...")?;
94 if let Some(comment) = &type_ignore_comment {
96 write!(f, "{}", comment)?;
97 }
98 writeln!(f)?;
99 }
100 writeln!(f)?;
101 Ok(())
102 }
103}