-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathsettings.rs
125 lines (113 loc) · 3.68 KB
/
settings.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use std::collections::BTreeSet;
use std::hash::{Hash, Hasher};
use std::path::{Path, PathBuf};
use glob::Pattern;
use once_cell::sync::Lazy;
use crate::checks::{CheckCode, ALL_CHECK_CODES};
use crate::fs;
use crate::pyproject::load_config;
#[derive(Debug, Clone)]
pub enum FilePattern {
Simple(&'static str),
Complex(Pattern, Option<Pattern>),
}
impl FilePattern {
pub fn from_user(pattern: &str, project_root: &Option<PathBuf>) -> Self {
let path = Path::new(pattern);
let absolute_path = match project_root {
Some(project_root) => fs::normalize_path_to(path, project_root),
None => fs::normalize_path(path),
};
let absolute = Pattern::new(&absolute_path.to_string_lossy()).expect("Invalid pattern.");
let basename = if !pattern.contains(std::path::MAIN_SEPARATOR) {
Some(Pattern::new(pattern).expect("Invalid pattern."))
} else {
None
};
FilePattern::Complex(absolute, basename)
}
}
#[derive(Debug)]
pub struct Settings {
pub line_length: usize,
pub exclude: Vec<FilePattern>,
pub extend_exclude: Vec<FilePattern>,
pub select: BTreeSet<CheckCode>,
}
impl Hash for Settings {
fn hash<H: Hasher>(&self, state: &mut H) {
self.line_length.hash(state);
for value in self.select.iter() {
value.hash(state);
}
}
}
static DEFAULT_EXCLUDE: Lazy<Vec<FilePattern>> = Lazy::new(|| {
vec![
FilePattern::Simple(".bzr"),
FilePattern::Simple(".direnv"),
FilePattern::Simple(".eggs"),
FilePattern::Simple(".git"),
FilePattern::Simple(".hg"),
FilePattern::Simple(".mypy_cache"),
FilePattern::Simple(".nox"),
FilePattern::Simple(".pants.d"),
FilePattern::Simple(".ruff_cache"),
FilePattern::Simple(".svn"),
FilePattern::Simple(".tox"),
FilePattern::Simple(".venv"),
FilePattern::Simple("__pypackages__"),
FilePattern::Simple("_build"),
FilePattern::Simple("buck-out"),
FilePattern::Simple("build"),
FilePattern::Simple("dist"),
FilePattern::Simple("node_modules"),
FilePattern::Simple("venv"),
]
});
impl Settings {
pub fn from_pyproject(path: &Option<PathBuf>, project_root: &Option<PathBuf>) -> Self {
let config = load_config(path);
let mut settings = Settings {
line_length: config.line_length.unwrap_or(88),
exclude: config
.exclude
.map(|paths| {
paths
.iter()
.map(|path| FilePattern::from_user(path, project_root))
.collect()
})
.unwrap_or_else(|| DEFAULT_EXCLUDE.clone()),
extend_exclude: config
.extend_exclude
.map(|paths| {
paths
.iter()
.map(|path| FilePattern::from_user(path, project_root))
.collect()
})
.unwrap_or_default(),
select: if let Some(select) = config.select {
BTreeSet::from_iter(select)
} else {
BTreeSet::from_iter(ALL_CHECK_CODES)
},
};
if let Some(ignore) = &config.ignore {
settings.ignore(ignore);
}
settings
}
pub fn select(&mut self, codes: Vec<CheckCode>) {
self.select.clear();
for code in codes {
self.select.insert(code);
}
}
pub fn ignore(&mut self, codes: &[CheckCode]) {
for code in codes {
self.select.remove(code);
}
}
}