Skip to content

[airflow] Move AIR302 to AIR301 and AIR303 to AIR302 #17151

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/ruff_linter/src/codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1069,8 +1069,8 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
// airflow
(Airflow, "001") => (RuleGroup::Stable, rules::airflow::rules::AirflowVariableNameTaskIdMismatch),
(Airflow, "002") => (RuleGroup::Preview, rules::airflow::rules::AirflowDagNoScheduleArgument),
(Airflow, "302") => (RuleGroup::Preview, rules::airflow::rules::Airflow3Removal),
(Airflow, "303") => (RuleGroup::Preview, rules::airflow::rules::Airflow3MovedToProvider),
(Airflow, "301") => (RuleGroup::Preview, rules::airflow::rules::Airflow3Removal),
(Airflow, "302") => (RuleGroup::Preview, rules::airflow::rules::Airflow3MovedToProvider),

// perflint
(Perflint, "101") => (RuleGroup::Stable, rules::perflint::rules::UnnecessaryListCast),
Expand Down
14 changes: 7 additions & 7 deletions crates/ruff_linter/src/rules/airflow/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ mod tests {

#[test_case(Rule::AirflowVariableNameTaskIdMismatch, Path::new("AIR001.py"))]
#[test_case(Rule::AirflowDagNoScheduleArgument, Path::new("AIR002.py"))]
#[test_case(Rule::Airflow3Removal, Path::new("AIR302_args.py"))]
#[test_case(Rule::Airflow3Removal, Path::new("AIR302_names.py"))]
#[test_case(Rule::Airflow3Removal, Path::new("AIR302_names_try.py"))]
#[test_case(Rule::Airflow3Removal, Path::new("AIR302_class_attribute.py"))]
#[test_case(Rule::Airflow3Removal, Path::new("AIR302_airflow_plugin.py"))]
#[test_case(Rule::Airflow3Removal, Path::new("AIR302_context.py"))]
#[test_case(Rule::Airflow3MovedToProvider, Path::new("AIR303.py"))]
#[test_case(Rule::Airflow3Removal, Path::new("AIR301_args.py"))]
#[test_case(Rule::Airflow3Removal, Path::new("AIR301_names.py"))]
#[test_case(Rule::Airflow3Removal, Path::new("AIR301_names_try.py"))]
#[test_case(Rule::Airflow3Removal, Path::new("AIR301_class_attribute.py"))]
#[test_case(Rule::Airflow3Removal, Path::new("AIR301_airflow_plugin.py"))]
#[test_case(Rule::Airflow3Removal, Path::new("AIR301_context.py"))]
#[test_case(Rule::Airflow3MovedToProvider, Path::new("AIR302.py"))]
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy());
let diagnostics = test_path(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ pub(crate) fn dag_no_schedule_argument(checker: &Checker, expr: &Expr) {
// If there's a schedule keyword argument, we are good.
// This includes the canonical 'schedule', and the deprecated 'timetable'
// and 'schedule_interval'. Usages of deprecated schedule arguments are
// covered by AIR302.
// covered by AIR301.
if ["schedule", "schedule_interval", "timetable"]
.iter()
.any(|a| arguments.find_keyword(a).is_some())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ impl Violation for Airflow3MovedToProvider {
}
}

/// AIR303
/// AIR302
pub(crate) fn moved_to_provider_in_3(checker: &Checker, expr: &Expr) {
if !checker.semantic().seen_module(Modules::AIRFLOW) {
return;
Expand Down
4 changes: 2 additions & 2 deletions crates/ruff_linter/src/rules/airflow/rules/removal_in_3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ impl Violation for Airflow3Removal {
}
}

/// AIR302
/// AIR301
pub(crate) fn airflow_3_removal_expr(checker: &Checker, expr: &Expr) {
if !checker.semantic().seen_module(Modules::AIRFLOW) {
return;
Expand Down Expand Up @@ -114,7 +114,7 @@ pub(crate) fn airflow_3_removal_expr(checker: &Checker, expr: &Expr) {
}
}

/// AIR302
/// AIR301
pub(crate) fn airflow_3_removal_function_def(checker: &Checker, function_def: &StmtFunctionDef) {
if !checker.semantic().seen_module(Modules::AIRFLOW) {
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,43 +1,42 @@
---
source: crates/ruff_linter/src/rules/airflow/mod.rs
snapshot_kind: text
---
AIR302_airflow_plugin.py:7:5: AIR302 `operators` is removed in Airflow 3.0; This extension should just be imported as a regular python module.
AIR301_airflow_plugin.py:7:5: AIR301 `operators` is removed in Airflow 3.0; This extension should just be imported as a regular python module.
|
5 | name = "test_plugin"
6 | # --- Invalid extensions start
7 | operators = [PluginOperator]
| ^^^^^^^^^ AIR302
| ^^^^^^^^^ AIR301
8 | sensors = [PluginSensorOperator]
9 | hooks = [PluginHook]
|

AIR302_airflow_plugin.py:8:5: AIR302 `sensors` is removed in Airflow 3.0; This extension should just be imported as a regular python module.
AIR301_airflow_plugin.py:8:5: AIR301 `sensors` is removed in Airflow 3.0; This extension should just be imported as a regular python module.
|
6 | # --- Invalid extensions start
7 | operators = [PluginOperator]
8 | sensors = [PluginSensorOperator]
| ^^^^^^^ AIR302
| ^^^^^^^ AIR301
9 | hooks = [PluginHook]
10 | executors = [PluginExecutor]
|

AIR302_airflow_plugin.py:9:5: AIR302 `hooks` is removed in Airflow 3.0; This extension should just be imported as a regular python module.
AIR301_airflow_plugin.py:9:5: AIR301 `hooks` is removed in Airflow 3.0; This extension should just be imported as a regular python module.
|
7 | operators = [PluginOperator]
8 | sensors = [PluginSensorOperator]
9 | hooks = [PluginHook]
| ^^^^^ AIR302
| ^^^^^ AIR301
10 | executors = [PluginExecutor]
11 | # --- Invalid extensions end
|

AIR302_airflow_plugin.py:10:5: AIR302 `executors` is removed in Airflow 3.0; This extension should just be imported as a regular python module.
AIR301_airflow_plugin.py:10:5: AIR301 `executors` is removed in Airflow 3.0; This extension should just be imported as a regular python module.
|
8 | sensors = [PluginSensorOperator]
9 | hooks = [PluginHook]
10 | executors = [PluginExecutor]
| ^^^^^^^^^ AIR302
| ^^^^^^^^^ AIR301
11 | # --- Invalid extensions end
12 | macros = [plugin_macro]
|
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
---
source: crates/ruff_linter/src/rules/airflow/mod.rs
---
AIR302_args.py:20:39: AIR302 [*] `schedule_interval` is removed in Airflow 3.0
AIR301_args.py:20:39: AIR301 [*] `schedule_interval` is removed in Airflow 3.0
|
18 | DAG(dag_id="class_schedule", schedule="@hourly")
19 |
20 | DAG(dag_id="class_schedule_interval", schedule_interval="@hourly")
| ^^^^^^^^^^^^^^^^^ AIR302
| ^^^^^^^^^^^^^^^^^ AIR301
21 |
22 | DAG(dag_id="class_timetable", timetable=NullTimetable())
|
Expand All @@ -22,12 +22,12 @@ AIR302_args.py:20:39: AIR302 [*] `schedule_interval` is removed in Airflow 3.0
22 22 | DAG(dag_id="class_timetable", timetable=NullTimetable())
23 23 |

AIR302_args.py:22:31: AIR302 [*] `timetable` is removed in Airflow 3.0
AIR301_args.py:22:31: AIR301 [*] `timetable` is removed in Airflow 3.0
|
20 | DAG(dag_id="class_schedule_interval", schedule_interval="@hourly")
21 |
22 | DAG(dag_id="class_timetable", timetable=NullTimetable())
| ^^^^^^^^^ AIR302
| ^^^^^^^^^ AIR301
|
= help: Use `schedule` instead

Expand All @@ -41,20 +41,20 @@ AIR302_args.py:22:31: AIR302 [*] `timetable` is removed in Airflow 3.0
24 24 |
25 25 | def sla_callback(*arg, **kwargs):

AIR302_args.py:29:34: AIR302 `sla_miss_callback` is removed in Airflow 3.0
AIR301_args.py:29:34: AIR301 `sla_miss_callback` is removed in Airflow 3.0
|
29 | DAG(dag_id="class_sla_callback", sla_miss_callback=sla_callback)
| ^^^^^^^^^^^^^^^^^ AIR302
| ^^^^^^^^^^^^^^^^^ AIR301
30 |
31 | DAG(dag_id="class_fail_stop", fail_stop=True)
|

AIR302_args.py:31:31: AIR302 [*] `fail_stop` is removed in Airflow 3.0
AIR301_args.py:31:31: AIR301 [*] `fail_stop` is removed in Airflow 3.0
|
29 | DAG(dag_id="class_sla_callback", sla_miss_callback=sla_callback)
30 |
31 | DAG(dag_id="class_fail_stop", fail_stop=True)
| ^^^^^^^^^ AIR302
| ^^^^^^^^^ AIR301
32 |
33 | DAG(dag_id="class_default_view", default_view="dag_default_view")
|
Expand All @@ -70,30 +70,30 @@ AIR302_args.py:31:31: AIR302 [*] `fail_stop` is removed in Airflow 3.0
33 33 | DAG(dag_id="class_default_view", default_view="dag_default_view")
34 34 |

AIR302_args.py:33:34: AIR302 `default_view` is removed in Airflow 3.0
AIR301_args.py:33:34: AIR301 `default_view` is removed in Airflow 3.0
|
31 | DAG(dag_id="class_fail_stop", fail_stop=True)
32 |
33 | DAG(dag_id="class_default_view", default_view="dag_default_view")
| ^^^^^^^^^^^^ AIR302
| ^^^^^^^^^^^^ AIR301
34 |
35 | DAG(dag_id="class_orientation", orientation="BT")
|

AIR302_args.py:35:33: AIR302 `orientation` is removed in Airflow 3.0
AIR301_args.py:35:33: AIR301 `orientation` is removed in Airflow 3.0
|
33 | DAG(dag_id="class_default_view", default_view="dag_default_view")
34 |
35 | DAG(dag_id="class_orientation", orientation="BT")
| ^^^^^^^^^^^ AIR302
| ^^^^^^^^^^^ AIR301
36 |
37 | allow_future_exec_dates_dag = DAG(dag_id="class_allow_future_exec_dates")
|

AIR302_args.py:46:6: AIR302 [*] `schedule_interval` is removed in Airflow 3.0
AIR301_args.py:46:6: AIR301 [*] `schedule_interval` is removed in Airflow 3.0
|
46 | @dag(schedule_interval="0 * * * *")
| ^^^^^^^^^^^^^^^^^ AIR302
| ^^^^^^^^^^^^^^^^^ AIR301
47 | def decorator_schedule_interval():
48 | pass
|
Expand All @@ -109,10 +109,10 @@ AIR302_args.py:46:6: AIR302 [*] `schedule_interval` is removed in Airflow 3.0
48 48 | pass
49 49 |

AIR302_args.py:51:6: AIR302 [*] `timetable` is removed in Airflow 3.0
AIR301_args.py:51:6: AIR301 [*] `timetable` is removed in Airflow 3.0
|
51 | @dag(timetable=NullTimetable())
| ^^^^^^^^^ AIR302
| ^^^^^^^^^ AIR301
52 | def decorator_timetable():
53 | pass
|
Expand All @@ -128,20 +128,20 @@ AIR302_args.py:51:6: AIR302 [*] `timetable` is removed in Airflow 3.0
53 53 | pass
54 54 |

AIR302_args.py:56:6: AIR302 `sla_miss_callback` is removed in Airflow 3.0
AIR301_args.py:56:6: AIR301 `sla_miss_callback` is removed in Airflow 3.0
|
56 | @dag(sla_miss_callback=sla_callback)
| ^^^^^^^^^^^^^^^^^ AIR302
| ^^^^^^^^^^^^^^^^^ AIR301
57 | def decorator_sla_callback():
58 | pass
|

AIR302_args.py:64:39: AIR302 [*] `execution_date` is removed in Airflow 3.0
AIR301_args.py:64:39: AIR301 [*] `execution_date` is removed in Airflow 3.0
|
62 | def decorator_deprecated_operator_args():
63 | trigger_dagrun_op = trigger_dagrun.TriggerDagRunOperator(
64 | task_id="trigger_dagrun_op1", execution_date="2024-12-04"
| ^^^^^^^^^^^^^^ AIR302
| ^^^^^^^^^^^^^^ AIR301
65 | )
66 | trigger_dagrun_op2 = TriggerDagRunOperator(
|
Expand All @@ -157,12 +157,12 @@ AIR302_args.py:64:39: AIR302 [*] `execution_date` is removed in Airflow 3.0
66 66 | trigger_dagrun_op2 = TriggerDagRunOperator(
67 67 | task_id="trigger_dagrun_op2", execution_date="2024-12-04"

AIR302_args.py:67:39: AIR302 [*] `execution_date` is removed in Airflow 3.0
AIR301_args.py:67:39: AIR301 [*] `execution_date` is removed in Airflow 3.0
|
65 | )
66 | trigger_dagrun_op2 = TriggerDagRunOperator(
67 | task_id="trigger_dagrun_op2", execution_date="2024-12-04"
| ^^^^^^^^^^^^^^ AIR302
| ^^^^^^^^^^^^^^ AIR301
68 | )
|
= help: Use `logical_date` instead
Expand All @@ -177,11 +177,11 @@ AIR302_args.py:67:39: AIR302 [*] `execution_date` is removed in Airflow 3.0
69 69 |
70 70 | branch_dt_op = datetime.BranchDateTimeOperator(

AIR302_args.py:71:33: AIR302 [*] `use_task_execution_day` is removed in Airflow 3.0
AIR301_args.py:71:33: AIR301 [*] `use_task_execution_day` is removed in Airflow 3.0
|
70 | branch_dt_op = datetime.BranchDateTimeOperator(
71 | task_id="branch_dt_op", use_task_execution_day=True, task_concurrency=5
| ^^^^^^^^^^^^^^^^^^^^^^ AIR302
| ^^^^^^^^^^^^^^^^^^^^^^ AIR301
72 | )
73 | branch_dt_op2 = BranchDateTimeOperator(
|
Expand All @@ -197,11 +197,11 @@ AIR302_args.py:71:33: AIR302 [*] `use_task_execution_day` is removed in Airflow
73 73 | branch_dt_op2 = BranchDateTimeOperator(
74 74 | task_id="branch_dt_op2",

AIR302_args.py:71:62: AIR302 [*] `task_concurrency` is removed in Airflow 3.0
AIR301_args.py:71:62: AIR301 [*] `task_concurrency` is removed in Airflow 3.0
|
70 | branch_dt_op = datetime.BranchDateTimeOperator(
71 | task_id="branch_dt_op", use_task_execution_day=True, task_concurrency=5
| ^^^^^^^^^^^^^^^^ AIR302
| ^^^^^^^^^^^^^^^^ AIR301
72 | )
73 | branch_dt_op2 = BranchDateTimeOperator(
|
Expand All @@ -217,12 +217,12 @@ AIR302_args.py:71:62: AIR302 [*] `task_concurrency` is removed in Airflow 3.0
73 73 | branch_dt_op2 = BranchDateTimeOperator(
74 74 | task_id="branch_dt_op2",

AIR302_args.py:75:9: AIR302 [*] `use_task_execution_day` is removed in Airflow 3.0
AIR301_args.py:75:9: AIR301 [*] `use_task_execution_day` is removed in Airflow 3.0
|
73 | branch_dt_op2 = BranchDateTimeOperator(
74 | task_id="branch_dt_op2",
75 | use_task_execution_day=True,
| ^^^^^^^^^^^^^^^^^^^^^^ AIR302
| ^^^^^^^^^^^^^^^^^^^^^^ AIR301
76 | sla=timedelta(seconds=10),
77 | )
|
Expand All @@ -238,57 +238,57 @@ AIR302_args.py:75:9: AIR302 [*] `use_task_execution_day` is removed in Airflow 3
77 77 | )
78 78 |

AIR302_args.py:76:9: AIR302 `sla` is removed in Airflow 3.0
AIR301_args.py:76:9: AIR301 `sla` is removed in Airflow 3.0
|
74 | task_id="branch_dt_op2",
75 | use_task_execution_day=True,
76 | sla=timedelta(seconds=10),
| ^^^ AIR302
| ^^^ AIR301
77 | )
|

AIR302_args.py:98:15: AIR302 `filename_template` is removed in Airflow 3.0
AIR301_args.py:98:15: AIR301 `filename_template` is removed in Airflow 3.0
|
97 | # deprecated filename_template argument in FileTaskHandler
98 | S3TaskHandler(filename_template="/tmp/test")
| ^^^^^^^^^^^^^^^^^ AIR302
| ^^^^^^^^^^^^^^^^^ AIR301
99 | HdfsTaskHandler(filename_template="/tmp/test")
100 | ElasticsearchTaskHandler(filename_template="/tmp/test")
|

AIR302_args.py:99:17: AIR302 `filename_template` is removed in Airflow 3.0
AIR301_args.py:99:17: AIR301 `filename_template` is removed in Airflow 3.0
|
97 | # deprecated filename_template argument in FileTaskHandler
98 | S3TaskHandler(filename_template="/tmp/test")
99 | HdfsTaskHandler(filename_template="/tmp/test")
| ^^^^^^^^^^^^^^^^^ AIR302
| ^^^^^^^^^^^^^^^^^ AIR301
100 | ElasticsearchTaskHandler(filename_template="/tmp/test")
101 | GCSTaskHandler(filename_template="/tmp/test")
|

AIR302_args.py:100:26: AIR302 `filename_template` is removed in Airflow 3.0
AIR301_args.py:100:26: AIR301 `filename_template` is removed in Airflow 3.0
|
98 | S3TaskHandler(filename_template="/tmp/test")
99 | HdfsTaskHandler(filename_template="/tmp/test")
100 | ElasticsearchTaskHandler(filename_template="/tmp/test")
| ^^^^^^^^^^^^^^^^^ AIR302
| ^^^^^^^^^^^^^^^^^ AIR301
101 | GCSTaskHandler(filename_template="/tmp/test")
|

AIR302_args.py:101:16: AIR302 `filename_template` is removed in Airflow 3.0
AIR301_args.py:101:16: AIR301 `filename_template` is removed in Airflow 3.0
|
99 | HdfsTaskHandler(filename_template="/tmp/test")
100 | ElasticsearchTaskHandler(filename_template="/tmp/test")
101 | GCSTaskHandler(filename_template="/tmp/test")
| ^^^^^^^^^^^^^^^^^ AIR302
| ^^^^^^^^^^^^^^^^^ AIR301
102 |
103 | FabAuthManager(None)
|

AIR302_args.py:103:15: AIR302 `appbuilder` is removed in Airflow 3.0; The constructor takes no parameter now
AIR301_args.py:103:15: AIR301 `appbuilder` is removed in Airflow 3.0; The constructor takes no parameter now
|
101 | GCSTaskHandler(filename_template="/tmp/test")
102 |
103 | FabAuthManager(None)
| ^^^^^^ AIR302
| ^^^^^^ AIR301
|
Loading
Loading