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