pyo3_stub_gen/
pyproject.rs1use anyhow::{bail, Result};
14use serde::{Deserialize, Serialize};
15use std::{fs, path::*};
16
17#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
18pub struct PyProject {
19 pub project: Project,
20 pub tool: Option<Tool>,
21
22 #[serde(skip)]
23 toml_path: PathBuf,
24}
25
26impl PyProject {
27 pub fn parse_toml(path: impl AsRef<Path>) -> Result<Self> {
28 let path = path.as_ref();
29 if path.file_name() != Some("pyproject.toml".as_ref()) {
30 bail!("{} is not a pyproject.toml", path.display())
31 }
32 let mut out: PyProject = toml::de::from_str(&fs::read_to_string(path)?)?;
33 out.toml_path = path.to_path_buf();
34 Ok(out)
35 }
36
37 pub fn module_name(&self) -> &str {
38 if let Some(tool) = &self.tool {
39 if let Some(maturin) = &tool.maturin {
40 if let Some(module_name) = &maturin.module_name {
41 return module_name;
42 }
43 }
44 }
45 &self.project.name
46 }
47
48 pub fn python_source(&self) -> Option<PathBuf> {
50 if let Some(tool) = &self.tool {
51 if let Some(maturin) = &tool.maturin {
52 if let Some(python_source) = &maturin.python_source {
53 if let Some(base) = self.toml_path.parent() {
54 return Some(base.join(python_source));
55 } else {
56 return Some(PathBuf::from(python_source));
57 }
58 }
59 }
60 }
61 None
62 }
63
64 pub fn stub_gen_config(&self) -> StubGenConfig {
67 self.tool
68 .as_ref()
69 .and_then(|t| t.pyo3_stub_gen.clone())
70 .unwrap_or_default()
71 }
72
73 pub fn doc_gen_config_resolved(&self) -> Option<crate::docgen::DocGenConfig> {
75 if let Some(mut config) = self.stub_gen_config().doc_gen {
76 if config.output_dir.is_relative() {
79 if let Some(base) = self.toml_path.parent() {
80 config.output_dir = base.join(&config.output_dir);
81 }
82 }
83 Some(config)
84 } else {
85 None
86 }
87 }
88}
89
90#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
91pub struct Project {
92 pub name: String,
93}
94
95#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
96pub struct Tool {
97 pub maturin: Option<Maturin>,
98 #[serde(rename = "pyo3-stub-gen")]
99 pub pyo3_stub_gen: Option<StubGenConfig>,
100}
101
102#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
103pub struct Maturin {
104 #[serde(rename = "python-source")]
105 pub python_source: Option<String>,
106 #[serde(rename = "module-name")]
107 pub module_name: Option<String>,
108}
109
110#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
115#[non_exhaustive]
116pub struct StubGenConfig {
117 #[serde(rename = "use-type-statement", default)]
120 pub use_type_statement: bool,
121 #[serde(rename = "doc-gen")]
123 pub doc_gen: Option<crate::docgen::DocGenConfig>,
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129
130 #[test]
131 fn test_stub_gen_config_true() {
132 let toml_str = r#"
133 [project]
134 name = "test"
135
136 [tool.pyo3-stub-gen]
137 use-type-statement = true
138 "#;
139 let pyproject: PyProject = toml::from_str(toml_str).unwrap();
140 assert!(pyproject.stub_gen_config().use_type_statement);
141 }
142
143 #[test]
144 fn test_stub_gen_config_false() {
145 let toml_str = r#"
146 [project]
147 name = "test"
148
149 [tool.pyo3-stub-gen]
150 use-type-statement = false
151 "#;
152 let pyproject: PyProject = toml::from_str(toml_str).unwrap();
153 assert!(!pyproject.stub_gen_config().use_type_statement);
154 }
155
156 #[test]
157 fn test_stub_gen_config_default() {
158 let toml_str = r#"
159 [project]
160 name = "test"
161 "#;
162 let pyproject: PyProject = toml::from_str(toml_str).unwrap();
163 assert!(!pyproject.stub_gen_config().use_type_statement);
164 }
165
166 #[test]
167 fn test_stub_gen_config_empty_section() {
168 let toml_str = r#"
169 [project]
170 name = "test"
171
172 [tool.pyo3-stub-gen]
173 "#;
174 let pyproject: PyProject = toml::from_str(toml_str).unwrap();
175 assert!(!pyproject.stub_gen_config().use_type_statement);
176 }
177}