Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
58f6732
add a new code for rules check for deprecated imports in airflow 3.1
sjyangkevin Jan 4, 2026
1b0bd7c
update comment for airflow.utils.setup_teardown
sjyangkevin Jan 4, 2026
b5b9d99
group related imports and use SourceModuleMoved
sjyangkevin Jan 6, 2026
5a5afbf
move BaseOperator to airflow.sdk
sjyangkevin Jan 7, 2026
bf5da1e
udpate test case
sjyangkevin Jan 7, 2026
1521a97
refine rules and improve message for sdk change
sjyangkevin Jan 14, 2026
b40bbd9
refactor module moved task sdk to use SourceModuleMovedToSDK replacement
sjyangkevin Jan 14, 2026
8112c30
update comment for utils.log.secrets_masker
sjyangkevin Jan 14, 2026
417ed95
refactor to use Message for warning, be explicit on task sdk version,…
sjyangkevin Jan 15, 2026
378e4bc
update preview_since version to 0.14.12
sjyangkevin Jan 15, 2026
cfa2407
add a new item in enum for raising internal module warning message
sjyangkevin Jan 16, 2026
1dc05b0
add a blank line at end of file
sjyangkevin Jan 17, 2026
da80949
rename to which can be used to include custom message and optionall…
sjyangkevin Jan 19, 2026
5f8363f
update comment for
sjyangkevin Jan 19, 2026
250a248
update sdk version to 1.1.0 for AIR321, and version to 1.0.0 for AIR301
sjyangkevin Jan 20, 2026
2a3f6e6
clean up redundant match and improve message
sjyangkevin Jan 23, 2026
531cbca
rename the rule, and some updates to rule
sjyangkevin Jan 23, 2026
a513e55
refine message, refactor AIR311 sdk move to use SourceModuleMovedToSDK
sjyangkevin Jan 28, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from airflow.datasets import DatasetAliasEvent, DatasetEvent
from airflow.operators.postgres_operator import Mapping
from airflow.operators.subdag import SubDagOperator
from airflow.secrets.cache import SecretCache
from airflow.secrets.local_filesystem import LocalFilesystemBackend
from airflow.triggers.external_task import TaskStateTrigger
from airflow.utils import dates
Expand Down Expand Up @@ -61,9 +60,6 @@
# get_connection
LocalFilesystemBackend()

# airflow.secrets.cache
SecretCache()


# airflow.triggers.external_task
TaskStateTrigger()
Expand Down
102 changes: 102 additions & 0 deletions crates/ruff_linter/resources/test/fixtures/airflow/AIR321_names.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
from __future__ import annotations

# airflow.utils.setup_teardown
from airflow.utils.setup_teardown import (
BaseSetupTeardownContext,
SetupTeardownContext,
)

BaseSetupTeardownContext()
SetupTeardownContext()

# airflow.utils.xcom
from airflow.utils.xcom import XCOM_RETURN_KEY

XCOM_RETURN_KEY

# airflow.utils.task_group
from airflow.utils.task_group import TaskGroup

TaskGroup()

# airflow.utils.timezone
from datetime import datetime as dt
from airflow.utils.timezone import (
coerce_datetime,
convert_to_utc,
datetime,
make_naive,
parse,
utc,
utcnow,
)

current_time = dt.now()

coerce_datetime(v=current_time, tz=None)
convert_to_utc(current_time)
datetime(2026, 1, 1, 21, 30, 0)
make_naive(current_time, tz=None)
parse("2026-01-01 21:30:00")
utc
utcnow()

# airflow.utils.decorators
from airflow.utils.decorators import (
remove_task_decorator,
fixup_decorator_warning_stack,
)

remove_task_decorator()
fixup_decorator_warning_stack()

# airflow.models.abstractoperator
from airflow.models.abstractoperator import (
AbstractOperator,
NotMapped,
TaskStateChangeCallback,
)

AbstractOperator()
NotMapped()
TaskStateChangeCallback()

# airflow.models.baseoperator
from airflow.models.baseoperator import BaseOperator

BaseOperator()

# airflow.macros
from airflow.macros import (
ds_add,
ds_format,
datetime_diff_for_humans,
ds_format_locale,
)

ds_add("2026-01-01", 5)
ds_format("2026-01-01", "%Y-%m-%d", "%m-%d-%y")
datetime_diff_for_humans(
dt(2026, 1, 1, 21, 30, 0),
since=dt(2026, 1, 2, 21, 30, 0)
)
ds_format_locale("01/01/2026", "%d/%m/%Y", "EEEE dd MMMM yyyy", "en_US")

# airflow.io
from airflow.io import (
get_fs,
has_fs,
Properties,
)

get_fs()
has_fs()
Properties()

# airflow.secrets.cache
from airflow.secrets.cache import SecretCache
SecretCache()

# airflow.hooks
from airflow.hooks.base import BaseHook
BaseHook()
6 changes: 6 additions & 0 deletions crates/ruff_linter/src/checkers/ast/analyze/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@ pub(crate) fn expression(expr: &Expr, checker: &Checker) {
if checker.is_rule_enabled(Rule::Airflow3Removal) {
airflow::rules::airflow_3_removal_expr(checker, expr);
}
if checker.is_rule_enabled(Rule::Airflow31Moved) {
airflow::rules::airflow_3_1_moved_expr(checker, expr);
}
if checker.is_rule_enabled(Rule::Airflow3SuggestedUpdate) {
airflow::rules::airflow_3_0_suggested_update_expr(checker, expr);
}
Expand Down Expand Up @@ -487,6 +490,9 @@ pub(crate) fn expression(expr: &Expr, checker: &Checker) {
if checker.is_rule_enabled(Rule::Airflow3Removal) {
airflow::rules::airflow_3_removal_expr(checker, expr);
}
if checker.is_rule_enabled(Rule::Airflow31Moved) {
airflow::rules::airflow_3_1_moved_expr(checker, expr);
}
if checker.is_rule_enabled(Rule::Airflow3SuggestedUpdate) {
airflow::rules::airflow_3_0_suggested_update_expr(checker, expr);
}
Expand Down
1 change: 1 addition & 0 deletions crates/ruff_linter/src/codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
(Airflow, "303") => rules::airflow::rules::Airflow3IncompatibleFunctionSignature,
(Airflow, "311") => rules::airflow::rules::Airflow3SuggestedUpdate,
(Airflow, "312") => rules::airflow::rules::Airflow3SuggestedToMoveToProvider,
(Airflow, "321") => rules::airflow::rules::Airflow31Moved,

// perflint
(Perflint, "101") => rules::perflint::rules::UnnecessaryListCast,
Expand Down
17 changes: 17 additions & 0 deletions crates/ruff_linter/src/rules/airflow/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ use ruff_python_semantic::{MemberNameImport, NameImport};
use ruff_text_size::Ranged;
use ruff_text_size::TextRange;

/// Warning message for internal modules that are not part of the public API.
pub(crate) const INTERNAL_MODULE_WARNING: &str = "This is an internal module which is not suggested to be used and is subject to change without notice.";

#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) enum Replacement {
// There's no replacement or suggestion other than removal
Expand All @@ -33,6 +36,20 @@ pub(crate) enum Replacement {
module: &'static str,
name: String,
},
// Symbols moved to Task SDK in Airflow 3. Used when we want to match multiple names.
// e.g., `airflow.io.get_fs | has_fs | Properties` to `airflow.sdk.io.get_fs | has_fs | Properties`
SourceModuleMovedToSDK {
module: &'static str,
name: String,
version: &'static str,
},
// Symbols updated in Airflow 3 with only module changed. Used when we want to include custom message and optionally report diagnostics.
SourceModuleMovedWithMessage {
module: &'static str,
name: String,
message: &'static str,
suggest_fix: bool,
},
Comment on lines +46 to +52
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create this new enum item which can be used as follow:

  1. The fix_title format is: "{name} has been moved to {module} since Airflow 3.1. {message}"; we can use the message parameter to include a static string as additional message that we want to show to users.
  2. The suggest_fix parameter is used to optionally report diagnostics. In some cases, we might want to just show a warning (e.g., internal module usage), but in some case, we might want to report diagnostic and suggest fix (e.g., BaseHook is moved from one module to another)

Why message is a static string. Use the following example to explain. Making message a String allow us to use format! to templating the string and render it at runtime. However, only rest or variables defined in the accessible scope can be used to render the string. As module and name will be handled in fix_title. It might not be necessary to use those values to render the message. So, here use static string.

[
            "airflow",
            "utils",
            "setup_teardown",
            rest @ ("BaseSetupTeardownContext" | "SetupTeardownContext"),
        ] => Replacement::SourceModuleMovedWithMessage {
            module: "airflow.sdk.definitions._internal.setup_teardown",
            name: rest.to_string(),
            message: "This is an internal module which is not suggested to be used and is subject to change without notice.",
            suggest_fix: false,
        },

}

#[derive(Clone, Debug, Eq, PartialEq)]
Expand Down
1 change: 1 addition & 0 deletions crates/ruff_linter/src/rules/airflow/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ mod tests {
#[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::Airflow31Moved, Path::new("AIR321_names.py"))]
#[test_case(Rule::Airflow3MovedToProvider, Path::new("AIR302_amazon.py"))]
#[test_case(Rule::Airflow3MovedToProvider, Path::new("AIR302_celery.py"))]
#[test_case(Rule::Airflow3MovedToProvider, Path::new("AIR302_common_sql.py"))]
Expand Down
2 changes: 2 additions & 0 deletions crates/ruff_linter/src/rules/airflow/rules/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub(crate) use dag_schedule_argument::*;
pub(crate) use function_signature_change_in_3::*;
pub(crate) use moved_in_3_1::*;
pub(crate) use moved_to_provider_in_3::*;
pub(crate) use removal_in_3::*;
pub(crate) use suggested_to_move_to_provider_in_3::*;
Expand All @@ -8,6 +9,7 @@ pub(crate) use task_variable_name::*;

mod dag_schedule_argument;
mod function_signature_change_in_3;
mod moved_in_3_1;
mod moved_to_provider_in_3;
mod removal_in_3;
mod suggested_to_move_to_provider_in_3;
Expand Down
Loading
Loading