1use crate::{generate::*, type_info::*};
2use std::fmt;
3
4/// Definition of a Python class.
5#[derive(Debug, Clone, PartialEq)]
6pub struct ClassDef {
7 pub name: &'static str,
8 pub doc: &'static str,
9 pub new: Option<NewDef>,
10 pub members: Vec<MemberDef>,
11 pub methods: Vec<MethodDef>,
12}
13
14impl Import for ClassDef {
15 fn import(&self) -> HashSet<ModuleRef> {
16 let mut import: HashSet = HashSet::new();
17 if let Some(new: &NewDef) = &self.new {
18 import.extend(iter:new.import());
19 }
20 for member: &MemberDef in &self.members {
21 import.extend(iter:member.import());
22 }
23 for method: &MethodDef in &self.methods {
24 import.extend(iter:method.import());
25 }
26 import
27 }
28}
29
30impl From<&PyClassInfo> for ClassDef {
31 fn from(info: &PyClassInfo) -> Self {
32 // Since there are multiple `#[pymethods]` for a single class, we need to merge them.
33 // This is only an initializer. See `StubInfo::gather` for the actual merging.
34 Self {
35 name: info.pyclass_name,
36 new: None,
37 doc: info.doc,
38 members: info.members.iter().map(MemberDef::from).collect(),
39 methods: Vec::new(),
40 }
41 }
42}
43
44impl fmt::Display for ClassDef {
45 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46 writeln!(f, "class {}:", self.name)?;
47 let indent = indent();
48 let doc = self.doc.trim();
49 if !doc.is_empty() {
50 writeln!(f, r#"{indent}r""""#)?;
51 for line in doc.lines() {
52 writeln!(f, "{indent}{}", line)?;
53 }
54 writeln!(f, r#"{indent}""""#)?;
55 }
56 for member in &self.members {
57 member.fmt(f)?;
58 }
59 if let Some(new) = &self.new {
60 new.fmt(f)?;
61 }
62 for method in &self.methods {
63 method.fmt(f)?;
64 }
65 if self.members.is_empty() && self.methods.is_empty() {
66 writeln!(f, "{indent}...")?;
67 }
68 writeln!(f)?;
69 Ok(())
70 }
71}
72