diff --git a/crates/ruff_linter/resources/test/fixtures/airflow/AIR302_names.py b/crates/ruff_linter/resources/test/fixtures/airflow/AIR302_names.py index 299c87b9feef1..63205874a8e2d 100644 --- a/crates/ruff_linter/resources/test/fixtures/airflow/AIR302_names.py +++ b/crates/ruff_linter/resources/test/fixtures/airflow/AIR302_names.py @@ -1,12 +1,52 @@ +from airflow.triggers.external_task import TaskStateTrigger +from airflow.www.auth import has_access +from airflow.api_connexion.security import requires_access +from airflow.metrics.validators import AllowListValidator +from airflow.metrics.validators import BlockListValidator from airflow.utils import dates -from airflow.utils.dates import date_range, datetime_to_nano, days_ago +from airflow.utils.dates import ( + date_range, + datetime_to_nano, + days_ago, + infer_time_unit, + parse_execution_date, + round_time, + scale_time_units, +) +from airflow.utils.file import TemporaryDirectory, mkdirs +from airflow.utils.state import SHUTDOWN, terminating_states +from airflow.utils.dag_cycle_tester import test_cycle + + +TaskStateTrigger -date_range -days_ago + +has_access +requires_access + +AllowListValidator +BlockListValidator dates.date_range dates.days_ago +date_range +days_ago +parse_execution_date +round_time +scale_time_units +infer_time_unit + + # This one was not deprecated. datetime_to_nano dates.datetime_to_nano + +TemporaryDirectory +mkdirs + +SHUTDOWN +terminating_states + + +test_cycle diff --git a/crates/ruff_linter/src/rules/airflow/rules/removal_in_3.rs b/crates/ruff_linter/src/rules/airflow/rules/removal_in_3.rs index 527b5cd402275..3f450a7978c81 100644 --- a/crates/ruff_linter/src/rules/airflow/rules/removal_in_3.rs +++ b/crates/ruff_linter/src/rules/airflow/rules/removal_in_3.rs @@ -51,7 +51,7 @@ impl Violation for Airflow3Removal { match replacement { Replacement::None => format!("`{deprecated}` is removed in Airflow 3.0"), Replacement::Name(name) => { - format!("`{deprecated}` is removed in Airflow 3.0; use {name} instead") + format!("`{deprecated}` is removed in Airflow 3.0; use `{name}` instead") } } } @@ -103,13 +103,75 @@ fn removed_name(checker: &mut Checker, expr: &Expr, ranged: impl Ranged) { .semantic() .resolve_qualified_name(expr) .and_then(|qualname| match qualname.segments() { - ["airflow", "utils", "dates", "date_range"] => { + ["airflow", "triggers", "external_task", "TaskStateTrigger"] => { Some((qualname.to_string(), Replacement::None)) } + ["airflow", "www", "auth", "has_access"] => Some(( + qualname.to_string(), + Replacement::Name("airflow.www.auth.has_access_*".to_string()), + )), + ["airflow", "api_connexion", "security", "requires_access"] => Some(( + qualname.to_string(), + Replacement::Name( + "airflow.api_connexion.security.requires_access_*".to_string(), + ), + )), + // airflow.metrics.validators + ["airflow", "metrics", "validators", "AllowListValidator"] => Some(( + qualname.to_string(), + Replacement::Name( + "airflow.metrics.validators.PatternAllowListValidator".to_string(), + ), + )), + ["airflow", "metrics", "validators", "BlockListValidator"] => Some(( + qualname.to_string(), + Replacement::Name( + "airflow.metrics.validators.PatternBlockListValidator".to_string(), + ), + )), + // airflow.utils.dates + ["airflow", "utils", "dates", "date_range"] => Some(( + qualname.to_string(), + Replacement::Name("airflow.timetables.".to_string()), + )), ["airflow", "utils", "dates", "days_ago"] => Some(( qualname.to_string(), - Replacement::Name("datetime.timedelta()".to_string()), + Replacement::Name("pendulum.today('UTC').add(days=-N, ...)".to_string()), + )), + ["airflow", "utils", "dates", "parse_execution_date"] => { + Some((qualname.to_string(), Replacement::None)) + } + ["airflow", "utils", "dates", "round_time"] => { + Some((qualname.to_string(), Replacement::None)) + } + ["airflow", "utils", "dates", "scale_time_units"] => { + Some((qualname.to_string(), Replacement::None)) + } + ["airflow", "utils", "dates", "infer_time_unit"] => { + Some((qualname.to_string(), Replacement::None)) + } + // airflow.utils.file + ["airflow", "utils", "file", "TemporaryDirectory"] => { + Some((qualname.to_string(), Replacement::None)) + } + ["airflow", "utils", "file", "mkdirs"] => Some(( + qualname.to_string(), + Replacement::Name("pendulum.today('UTC').add(days=-N, ...)".to_string()), )), + // airflow.utils.state + ["airflow", "utils", "state", "SHUTDOWN"] => { + Some((qualname.to_string(), Replacement::None)) + } + ["airflow", "utils", "state", "terminating_states"] => { + Some((qualname.to_string(), Replacement::None)) + } + // airflow.uilts + ["airflow", "utils", "dag_cycle_tester", "test_cycle"] => { + Some((qualname.to_string(), Replacement::None)) + } + ["airflow", "utils", "decorators", "apply_defaults"] => { + Some((qualname.to_string(), Replacement::None)) + } _ => None, }); if let Some((deprecated, replacement)) = result { diff --git a/crates/ruff_linter/src/rules/airflow/snapshots/ruff_linter__rules__airflow__tests__AIR302_AIR302_args.py.snap b/crates/ruff_linter/src/rules/airflow/snapshots/ruff_linter__rules__airflow__tests__AIR302_AIR302_args.py.snap index 23725fc463073..0f1114cc34181 100644 --- a/crates/ruff_linter/src/rules/airflow/snapshots/ruff_linter__rules__airflow__tests__AIR302_AIR302_args.py.snap +++ b/crates/ruff_linter/src/rules/airflow/snapshots/ruff_linter__rules__airflow__tests__AIR302_AIR302_args.py.snap @@ -1,7 +1,8 @@ --- source: crates/ruff_linter/src/rules/airflow/mod.rs +snapshot_kind: text --- -AIR302_args.py:6:39: AIR302 `schedule_interval` is removed in Airflow 3.0; use schedule instead +AIR302_args.py:6:39: AIR302 `schedule_interval` is removed in Airflow 3.0; use `schedule` instead | 4 | DAG(dag_id="class_schedule", schedule="@hourly") 5 | @@ -11,7 +12,7 @@ AIR302_args.py:6:39: AIR302 `schedule_interval` is removed in Airflow 3.0; use s 8 | DAG(dag_id="class_timetable", timetable=NullTimetable()) | -AIR302_args.py:8:31: AIR302 `timetable` is removed in Airflow 3.0; use schedule instead +AIR302_args.py:8:31: AIR302 `timetable` is removed in Airflow 3.0; use `schedule` instead | 6 | DAG(dag_id="class_schedule_interval", schedule_interval="@hourly") 7 | @@ -19,7 +20,7 @@ AIR302_args.py:8:31: AIR302 `timetable` is removed in Airflow 3.0; use schedule | ^^^^^^^^^ AIR302 | -AIR302_args.py:16:6: AIR302 `schedule_interval` is removed in Airflow 3.0; use schedule instead +AIR302_args.py:16:6: AIR302 `schedule_interval` is removed in Airflow 3.0; use `schedule` instead | 16 | @dag(schedule_interval="0 * * * *") | ^^^^^^^^^^^^^^^^^ AIR302 @@ -27,7 +28,7 @@ AIR302_args.py:16:6: AIR302 `schedule_interval` is removed in Airflow 3.0; use s 18 | pass | -AIR302_args.py:21:6: AIR302 `timetable` is removed in Airflow 3.0; use schedule instead +AIR302_args.py:21:6: AIR302 `timetable` is removed in Airflow 3.0; use `schedule` instead | 21 | @dag(timetable=NullTimetable()) | ^^^^^^^^^ AIR302 diff --git a/crates/ruff_linter/src/rules/airflow/snapshots/ruff_linter__rules__airflow__tests__AIR302_AIR302_names.py.snap b/crates/ruff_linter/src/rules/airflow/snapshots/ruff_linter__rules__airflow__tests__AIR302_AIR302_names.py.snap index f97e1dc4f110f..13ff8b0fd3f7c 100644 --- a/crates/ruff_linter/src/rules/airflow/snapshots/ruff_linter__rules__airflow__tests__AIR302_AIR302_names.py.snap +++ b/crates/ruff_linter/src/rules/airflow/snapshots/ruff_linter__rules__airflow__tests__AIR302_AIR302_names.py.snap @@ -1,38 +1,157 @@ --- source: crates/ruff_linter/src/rules/airflow/mod.rs +snapshot_kind: text --- -AIR302_names.py:4:1: AIR302 `airflow.utils.dates.date_range` is removed in Airflow 3.0 - | -2 | from airflow.utils.dates import date_range, datetime_to_nano, days_ago -3 | -4 | date_range - | ^^^^^^^^^^ AIR302 -5 | days_ago - | - -AIR302_names.py:5:1: AIR302 `airflow.utils.dates.days_ago` is removed in Airflow 3.0; use datetime.timedelta() instead - | -4 | date_range -5 | days_ago - | ^^^^^^^^ AIR302 -6 | -7 | dates.date_range - | - -AIR302_names.py:7:7: AIR302 `airflow.utils.dates.date_range` is removed in Airflow 3.0 - | -5 | days_ago -6 | -7 | dates.date_range - | ^^^^^^^^^^ AIR302 -8 | dates.days_ago - | - -AIR302_names.py:8:7: AIR302 `airflow.utils.dates.days_ago` is removed in Airflow 3.0; use datetime.timedelta() instead - | - 7 | dates.date_range - 8 | dates.days_ago +AIR302_names.py:21:1: AIR302 `airflow.triggers.external_task.TaskStateTrigger` is removed in Airflow 3.0 + | +21 | TaskStateTrigger + | ^^^^^^^^^^^^^^^^ AIR302 + | + +AIR302_names.py:24:1: AIR302 `airflow.www.auth.has_access` is removed in Airflow 3.0; use `airflow.www.auth.has_access_*` instead + | +24 | has_access + | ^^^^^^^^^^ AIR302 +25 | requires_access + | + +AIR302_names.py:25:1: AIR302 `airflow.api_connexion.security.requires_access` is removed in Airflow 3.0; use `airflow.api_connexion.security.requires_access_*` instead + | +24 | has_access +25 | requires_access + | ^^^^^^^^^^^^^^^ AIR302 +26 | +27 | AllowListValidator + | + +AIR302_names.py:27:1: AIR302 `airflow.metrics.validators.AllowListValidator` is removed in Airflow 3.0; use `airflow.metrics.validators.PatternAllowListValidator` instead + | +25 | requires_access +26 | +27 | AllowListValidator + | ^^^^^^^^^^^^^^^^^^ AIR302 +28 | BlockListValidator + | + +AIR302_names.py:28:1: AIR302 `airflow.metrics.validators.BlockListValidator` is removed in Airflow 3.0; use `airflow.metrics.validators.PatternBlockListValidator` instead + | +27 | AllowListValidator +28 | BlockListValidator + | ^^^^^^^^^^^^^^^^^^ AIR302 +29 | +30 | dates.date_range + | + +AIR302_names.py:30:7: AIR302 `airflow.utils.dates.date_range` is removed in Airflow 3.0; use `airflow.timetables.` instead + | +28 | BlockListValidator +29 | +30 | dates.date_range + | ^^^^^^^^^^ AIR302 +31 | dates.days_ago + | + +AIR302_names.py:31:7: AIR302 `airflow.utils.dates.days_ago` is removed in Airflow 3.0; use `pendulum.today('UTC').add(days=-N, ...)` instead + | +30 | dates.date_range +31 | dates.days_ago | ^^^^^^^^ AIR302 - 9 | -10 | # This one was not deprecated. +32 | +33 | date_range + | + +AIR302_names.py:33:1: AIR302 `airflow.utils.dates.date_range` is removed in Airflow 3.0; use `airflow.timetables.` instead + | +31 | dates.days_ago +32 | +33 | date_range + | ^^^^^^^^^^ AIR302 +34 | days_ago +35 | parse_execution_date + | + +AIR302_names.py:34:1: AIR302 `airflow.utils.dates.days_ago` is removed in Airflow 3.0; use `pendulum.today('UTC').add(days=-N, ...)` instead + | +33 | date_range +34 | days_ago + | ^^^^^^^^ AIR302 +35 | parse_execution_date +36 | round_time + | + +AIR302_names.py:35:1: AIR302 `airflow.utils.dates.parse_execution_date` is removed in Airflow 3.0 + | +33 | date_range +34 | days_ago +35 | parse_execution_date + | ^^^^^^^^^^^^^^^^^^^^ AIR302 +36 | round_time +37 | scale_time_units + | + +AIR302_names.py:36:1: AIR302 `airflow.utils.dates.round_time` is removed in Airflow 3.0 + | +34 | days_ago +35 | parse_execution_date +36 | round_time + | ^^^^^^^^^^ AIR302 +37 | scale_time_units +38 | infer_time_unit + | + +AIR302_names.py:37:1: AIR302 `airflow.utils.dates.scale_time_units` is removed in Airflow 3.0 + | +35 | parse_execution_date +36 | round_time +37 | scale_time_units + | ^^^^^^^^^^^^^^^^ AIR302 +38 | infer_time_unit + | + +AIR302_names.py:38:1: AIR302 `airflow.utils.dates.infer_time_unit` is removed in Airflow 3.0 + | +36 | round_time +37 | scale_time_units +38 | infer_time_unit + | ^^^^^^^^^^^^^^^ AIR302 + | + +AIR302_names.py:45:1: AIR302 `airflow.utils.file.TemporaryDirectory` is removed in Airflow 3.0 + | +43 | dates.datetime_to_nano +44 | +45 | TemporaryDirectory + | ^^^^^^^^^^^^^^^^^^ AIR302 +46 | mkdirs + | + +AIR302_names.py:46:1: AIR302 `airflow.utils.file.mkdirs` is removed in Airflow 3.0; use `pendulum.today('UTC').add(days=-N, ...)` instead + | +45 | TemporaryDirectory +46 | mkdirs + | ^^^^^^ AIR302 +47 | +48 | SHUTDOWN + | + +AIR302_names.py:48:1: AIR302 `airflow.utils.state.SHUTDOWN` is removed in Airflow 3.0 + | +46 | mkdirs +47 | +48 | SHUTDOWN + | ^^^^^^^^ AIR302 +49 | terminating_states + | + +AIR302_names.py:49:1: AIR302 `airflow.utils.state.terminating_states` is removed in Airflow 3.0 + | +48 | SHUTDOWN +49 | terminating_states + | ^^^^^^^^^^^^^^^^^^ AIR302 + | + +AIR302_names.py:52:1: AIR302 `airflow.utils.dag_cycle_tester.test_cycle` is removed in Airflow 3.0 + | +52 | test_cycle + | ^^^^^^^^^^ AIR302 |