Skip to content

Commit f31d0b6

Browse files
committed
Address code review.
Move the main rule implementation to just below the `BlockingPathMethodInAsyncFunction` implementation.
1 parent fc6a4ec commit f31d0b6

File tree

1 file changed

+70
-71
lines changed

1 file changed

+70
-71
lines changed

crates/ruff_linter/src/rules/flake8_async/rules/blocking_path_methods.rs

Lines changed: 70 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,76 @@ impl Violation for BlockingPathMethodInAsyncFunction {
6161
}
6262
}
6363

64+
/// ASYNC240
65+
pub(crate) fn blocking_os_path(checker: &Checker, call: &ExprCall) {
66+
let semantic = checker.semantic();
67+
if !semantic.in_async_context() {
68+
return;
69+
}
70+
71+
// Check if an expression is calling I/O related os.path method.
72+
// Just initializing pathlib.Path object is OK, we can return
73+
// early in that scenario.
74+
if let Some(qualified_name) = semantic.resolve_qualified_name(call.func.as_ref()) {
75+
let segments = qualified_name.segments();
76+
if !matches!(segments, ["os", "path", _]) {
77+
return;
78+
}
79+
80+
let Some(os_path_method) = segments.last() else {
81+
return;
82+
};
83+
84+
if maybe_calling_io_operation(os_path_method) {
85+
checker.report_diagnostic(
86+
BlockingPathMethodInAsyncFunction {
87+
path_library: "os.path".to_string(),
88+
},
89+
call.func.range(),
90+
);
91+
}
92+
return;
93+
}
94+
95+
let Some(ast::ExprAttribute { value, attr, .. }) = call.func.as_attribute_expr() else {
96+
return;
97+
};
98+
99+
if !maybe_calling_io_operation(attr.id.as_str()) {
100+
return;
101+
}
102+
103+
// Check if an expression is a pathlib.Path constructor that directly
104+
// calls an I/O method.
105+
if PathlibPathChecker::match_initializer(value, semantic) {
106+
checker.report_diagnostic(
107+
BlockingPathMethodInAsyncFunction {
108+
path_library: "pathlib.Path".to_string(),
109+
},
110+
call.func.range(),
111+
);
112+
return;
113+
}
114+
115+
// Lastly, check if a variable is a pathlib.Path instance and it's
116+
// calling an I/O method.
117+
let Some(name) = value.as_name_expr() else {
118+
return;
119+
};
120+
121+
let Some(binding) = semantic.only_binding(name).map(|id| semantic.binding(id)) else {
122+
return;
123+
};
124+
125+
if check_type::<PathlibPathChecker>(binding, semantic) {
126+
checker.report_diagnostic(
127+
BlockingPathMethodInAsyncFunction {
128+
path_library: "pathlib.Path".to_string(),
129+
},
130+
call.func.range(),
131+
);
132+
}
133+
}
64134
struct PathlibPathChecker;
65135

66136
impl PathlibPathChecker {
@@ -174,74 +244,3 @@ fn maybe_calling_io_operation(attr: &str) -> bool {
174244
| "with_suffix"
175245
)
176246
}
177-
178-
/// ASYNC240
179-
pub(crate) fn blocking_os_path(checker: &Checker, call: &ExprCall) {
180-
let semantic = checker.semantic();
181-
if !semantic.in_async_context() {
182-
return;
183-
}
184-
185-
// Check if an expression is calling I/O related os.path method.
186-
// Just initializing pathlib.Path object is OK, we can return
187-
// early in that scenario.
188-
if let Some(qualified_name) = semantic.resolve_qualified_name(call.func.as_ref()) {
189-
let segments = qualified_name.segments();
190-
if !matches!(segments, ["os", "path", _]) {
191-
return;
192-
}
193-
194-
let Some(os_path_method) = segments.last() else {
195-
return;
196-
};
197-
198-
if maybe_calling_io_operation(os_path_method) {
199-
checker.report_diagnostic(
200-
BlockingPathMethodInAsyncFunction {
201-
path_library: "os.path".to_string(),
202-
},
203-
call.func.range(),
204-
);
205-
}
206-
return;
207-
}
208-
209-
let Some(ast::ExprAttribute { value, attr, .. }) = call.func.as_attribute_expr() else {
210-
return;
211-
};
212-
213-
if !maybe_calling_io_operation(attr.id.as_str()) {
214-
return;
215-
}
216-
217-
// Check if an expression is a pathlib.Path constructor that directly
218-
// calls an I/O method.
219-
if PathlibPathChecker::match_initializer(value, semantic) {
220-
checker.report_diagnostic(
221-
BlockingPathMethodInAsyncFunction {
222-
path_library: "pathlib.Path".to_string(),
223-
},
224-
call.func.range(),
225-
);
226-
return;
227-
}
228-
229-
// Lastly, check if a variable is a pathlib.Path instance and it's
230-
// calling an I/O method.
231-
let Some(name) = value.as_name_expr() else {
232-
return;
233-
};
234-
235-
let Some(binding) = semantic.only_binding(name).map(|id| semantic.binding(id)) else {
236-
return;
237-
};
238-
239-
if check_type::<PathlibPathChecker>(binding, semantic) {
240-
checker.report_diagnostic(
241-
BlockingPathMethodInAsyncFunction {
242-
path_library: "pathlib.Path".to_string(),
243-
},
244-
call.func.range(),
245-
);
246-
}
247-
}

0 commit comments

Comments
 (0)