use super::{ConfigLoader, ConfigMatch};
use crate::config::Config;
use anyhow::{Context, Result};
use serde::Deserialize;
pub(crate) const PYPROJECT_CONFIG_FILE: &str = "pyproject.toml";
#[derive(Deserialize)]
struct PyprojectToml {
tool: Option<Tool>,
}
#[derive(Deserialize)]
struct Tool {
lychee: Option<Config>,
}
pub(crate) struct PyprojectTomlLoader;
impl ConfigLoader for PyprojectTomlLoader {
fn filename(&self) -> &str {
PYPROJECT_CONFIG_FILE
}
fn load(&self, contents: &str) -> Result<ConfigMatch> {
let pyproject = toml::from_str::<PyprojectToml>(contents)
.with_context(|| "Failed to parse [tool.lychee] from pyproject.toml")?;
match pyproject.tool.and_then(|t| t.lychee) {
Some(config) => Ok(ConfigMatch::Found(Box::new(config))),
None => Ok(ConfigMatch::NotFound),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_load_config() {
let toml = r#"
[tool.lychee]
exclude = ["foo"]
"#;
let result = PyprojectTomlLoader.load(toml).unwrap();
match result {
ConfigMatch::Found(config) => assert_eq!(config.exclude, vec!["foo".to_string()]),
ConfigMatch::NotFound => panic!("Expected config to be found"),
}
}
#[test]
fn test_load_no_lychee_config() {
let toml = r"
[tool.black]
line-length = 88
";
let result = PyprojectTomlLoader.load(toml).unwrap();
match result {
ConfigMatch::NotFound => (),
ConfigMatch::Found(_) => panic!("Expected no config to be found"),
}
}
#[test]
fn test_load_no_tool_section() {
let toml = r#"
[build-system]
requires = ["setuptools"]
"#;
let result = PyprojectTomlLoader.load(toml).unwrap();
match result {
ConfigMatch::NotFound => (),
ConfigMatch::Found(_) => panic!("Expected no config to be found"),
}
}
}