diff --git a/crates/ruff_linter/resources/test/fixtures/airflow/AIR301_names.py b/crates/ruff_linter/resources/test/fixtures/airflow/AIR301_names.py index 3d5018719c..73884a5ae6 100644 --- a/crates/ruff_linter/resources/test/fixtures/airflow/AIR301_names.py +++ b/crates/ruff_linter/resources/test/fixtures/airflow/AIR301_names.py @@ -24,9 +24,6 @@ from airflow.contrib.aws_athena_hook import AWSAthenaHook from airflow.datasets import DatasetAliasEvent from airflow.hooks.base_hook import BaseHook from airflow.operators.subdag import SubDagOperator -from airflow.providers.mysql.datasets import mysql -from airflow.providers.postgres.datasets import postgres -from airflow.providers.trino.datasets import trino from airflow.secrets.local_filesystem import LocalFilesystemBackend from airflow.sensors.base_sensor_operator import BaseSensorOperator from airflow.triggers.external_task import TaskStateTrigger @@ -78,14 +75,6 @@ BaseHook() # airflow.operators.subdag.* SubDagOperator() -# airflow.providers.mysql -mysql.sanitize_uri - -# airflow.providers.postgres -postgres.sanitize_uri - -# airflow.providers.trino -trino.sanitize_uri # airflow.secrets # get_connection @@ -155,3 +144,18 @@ should_hide_value_for_key from airflow.operators.python import get_current_context get_current_context() + +# airflow.providers.mysql +from airflow.providers.mysql.datasets.mysql import sanitize_uri + +sanitize_uri + +# airflow.providers.postgres +from airflow.providers.postgres.datasets.postgres import sanitize_uri + +sanitize_uri + +# airflow.providers.trino +from airflow.providers.trino.datasets.trino import sanitize_uri + +sanitize_uri diff --git a/crates/ruff_linter/src/rules/airflow/helpers.rs b/crates/ruff_linter/src/rules/airflow/helpers.rs index fb6f3b9ff5..54a4d2bda5 100644 --- a/crates/ruff_linter/src/rules/airflow/helpers.rs +++ b/crates/ruff_linter/src/rules/airflow/helpers.rs @@ -8,13 +8,20 @@ use ruff_python_semantic::SemanticModel; #[derive(Clone, Debug, Eq, PartialEq)] pub(crate) enum Replacement { + // There's no replacement or suggestion other than removal None, - Name(&'static str), + // The attribute name of a class has been changed. + AttrName(&'static str), + // Additional information. Used when there's replacement but they're not direct mapping. Message(&'static str), + // Symbols updated in Airflow 3 with replacement + // e.g., `airflow.datasets.Dataset` to `airflow.sdk.Asset` AutoImport { module: &'static str, name: &'static str, }, + // Symbols updated in Airflow 3 with only module changed. Used when we want to match multiple names. + // e.g., `airflow.configuration.as_dict | get` to `airflow.configuration.conf.as_dict | get` SourceModuleMoved { module: &'static str, name: String, 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 66b88c0f40..b6cc71f5a2 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 @@ -57,28 +57,27 @@ impl Violation for Airflow3Removal { } = self; match replacement { Replacement::None - | Replacement::Name(_) + | Replacement::AttrName(_) + | Replacement::Message(_) | Replacement::AutoImport { module: _, name: _ } | Replacement::SourceModuleMoved { module: _, name: _ } => { format!("`{deprecated}` is removed in Airflow 3.0") } - Replacement::Message(message) => { - format!("`{deprecated}` is removed in Airflow 3.0; {message}") - } } } fn fix_title(&self) -> Option { let Airflow3Removal { replacement, .. } = self; match replacement { - Replacement::Name(name) => Some(format!("Use `{name}` instead")), + Replacement::None => None, + Replacement::AttrName(name) => Some(format!("Use `{name}` instead")), + Replacement::Message(message) => Some((*message).to_string()), Replacement::AutoImport { module, name } => { Some(format!("Use `{module}.{name}` instead")) } Replacement::SourceModuleMoved { module, name } => { Some(format!("Use `{module}.{name}` instead")) } - _ => None, } } } @@ -278,22 +277,22 @@ fn check_class_attribute(checker: &Checker, attribute_expr: &ExprAttribute) { let replacement = match *qualname.segments() { ["airflow", "providers_manager", "ProvidersManager"] => match attr.as_str() { - "dataset_factories" => Replacement::Name("asset_factories"), - "dataset_uri_handlers" => Replacement::Name("asset_uri_handlers"), + "dataset_factories" => Replacement::AttrName("asset_factories"), + "dataset_uri_handlers" => Replacement::AttrName("asset_uri_handlers"), "dataset_to_openlineage_converters" => { - Replacement::Name("asset_to_openlineage_converters") + Replacement::AttrName("asset_to_openlineage_converters") } _ => return, }, ["airflow", "lineage", "hook", "DatasetLineageInfo"] => match attr.as_str() { - "dataset" => Replacement::Name("asset"), + "dataset" => Replacement::AttrName("asset"), _ => return, }, _ => return, }; // Create the `Fix` first to avoid cloning `Replacement`. - let fix = if let Replacement::Name(name) = replacement { + let fix = if let Replacement::AttrName(name) = replacement { Some(Fix::safe_edit(Edit::range_replacement( name.to_string(), attr.range(), @@ -466,52 +465,52 @@ fn check_method(checker: &Checker, call_expr: &ExprCall) { let replacement = match qualname.segments() { ["airflow", "datasets", "manager", "DatasetManager"] => match attr.as_str() { - "register_dataset_change" => Replacement::Name("register_asset_change"), - "create_datasets" => Replacement::Name("create_assets"), - "notify_dataset_created" => Replacement::Name("notify_asset_created"), - "notify_dataset_changed" => Replacement::Name("notify_asset_changed"), - "notify_dataset_alias_created" => Replacement::Name("notify_asset_alias_created"), + "register_dataset_change" => Replacement::AttrName("register_asset_change"), + "create_datasets" => Replacement::AttrName("create_assets"), + "notify_dataset_created" => Replacement::AttrName("notify_asset_created"), + "notify_dataset_changed" => Replacement::AttrName("notify_asset_changed"), + "notify_dataset_alias_created" => Replacement::AttrName("notify_asset_alias_created"), _ => return, }, ["airflow", "lineage", "hook", "HookLineageCollector"] => match attr.as_str() { - "create_dataset" => Replacement::Name("create_asset"), - "add_input_dataset" => Replacement::Name("add_input_asset"), - "add_output_dataset" => Replacement::Name("add_output_asset"), - "collected_datasets" => Replacement::Name("collected_assets"), + "create_dataset" => Replacement::AttrName("create_asset"), + "add_input_dataset" => Replacement::AttrName("add_input_asset"), + "add_output_dataset" => Replacement::AttrName("add_output_asset"), + "collected_datasets" => Replacement::AttrName("collected_assets"), _ => return, }, ["airflow", "providers", "amazon", "auth_manager", "aws_auth_manager", "AwsAuthManager"] => { match attr.as_str() { - "is_authorized_dataset" => Replacement::Name("is_authorized_asset"), + "is_authorized_dataset" => Replacement::AttrName("is_authorized_asset"), _ => return, } } ["airflow", "providers_manager", "ProvidersManager"] => match attr.as_str() { "initialize_providers_dataset_uri_resources" => { - Replacement::Name("initialize_providers_asset_uri_resources") + Replacement::AttrName("initialize_providers_asset_uri_resources") } _ => return, }, ["airflow", "secrets", "local_filesystem", "LocalFilesystemBackend"] => match attr.as_str() { - "get_connections" => Replacement::Name("get_connection"), + "get_connections" => Replacement::AttrName("get_connection"), _ => return, }, ["airflow", "datasets", ..] | ["airflow", "Dataset"] => match attr.as_str() { - "iter_datasets" => Replacement::Name("iter_assets"), - "iter_dataset_aliases" => Replacement::Name("iter_asset_aliases"), + "iter_datasets" => Replacement::AttrName("iter_assets"), + "iter_dataset_aliases" => Replacement::AttrName("iter_asset_aliases"), _ => return, }, segments => { if is_airflow_secret_backend(segments) { match attr.as_str() { - "get_conn_uri" => Replacement::Name("get_conn_value"), - "get_connections" => Replacement::Name("get_connection"), + "get_conn_uri" => Replacement::AttrName("get_conn_value"), + "get_connections" => Replacement::AttrName("get_connection"), _ => return, } } else if is_airflow_hook(segments) { match attr.as_str() { - "get_connections" => Replacement::Name("get_connection"), + "get_connections" => Replacement::AttrName("get_connection"), _ => return, } } else { @@ -520,7 +519,7 @@ fn check_method(checker: &Checker, call_expr: &ExprCall) { } }; // Create the `Fix` first to avoid cloning `Replacement`. - let fix = if let Replacement::Name(name) = replacement { + let fix = if let Replacement::AttrName(name) = replacement { Some(Fix::safe_edit(Edit::range_replacement( name.to_string(), attr.range(), @@ -566,12 +565,12 @@ fn check_name(checker: &Checker, expr: &Expr, range: TextRange) { let replacement = match qualified_name.segments() { // airflow.PY\d{1,2} ["airflow", "PY36" | "PY37" | "PY38" | "PY39" | "PY310" | "PY311" | "PY312"] => { - Replacement::Name("sys.version_info") + Replacement::Message("Use `sys.version_info` instead") } // airflow.api_connexion.security ["airflow", "api_connexion", "security", "requires_access"] => { - Replacement::Name("airflow.api_connexion.security.requires_access_*") + Replacement::Message("Use `airflow.api_connexion.security.requires_access_*` instead") } ["airflow", "api_connexion", "security", "requires_access_dataset"] => { Replacement::AutoImport { @@ -626,9 +625,10 @@ fn check_name(checker: &Checker, expr: &Expr, range: TextRange) { ["airflow", "datasets", "DatasetAliasEvent"] => Replacement::None, // airflow.hooks - ["airflow", "hooks", "base_hook", "BaseHook"] => { - Replacement::Name("airflow.hooks.base.BaseHook") - } + ["airflow", "hooks", "base_hook", "BaseHook"] => Replacement::AutoImport { + module: "airflow.hooks.base", + name: "BaseHook", + }, // airflow.lineage.hook ["airflow", "lineage", "hook", "DatasetLineageInfo"] => Replacement::AutoImport { @@ -664,9 +664,10 @@ fn check_name(checker: &Checker, expr: &Expr, range: TextRange) { }, // airflow.notifications - ["airflow", "notifications", "basenotifier", "BaseNotifier"] => { - Replacement::Name("airflow.sdk.BaseNotifier") - } + ["airflow", "notifications", "basenotifier", "BaseNotifier"] => Replacement::AutoImport { + module: "airflow.sdk", + name: "BaseNotifier", + }, // airflow.operators ["airflow", "operators", "subdag", ..] => { @@ -691,7 +692,10 @@ fn check_name(checker: &Checker, expr: &Expr, range: TextRange) { // airflow.sensors ["airflow", "sensors", "base_sensor_operator", "BaseSensorOperator"] => { - Replacement::Name("airflow.sdk.bases.sensor.BaseSensorOperator") + Replacement::AutoImport { + module: "airflow.sdk.bases.sensor", + name: "BaseSensorOperator", + } } // airflow.timetables @@ -720,23 +724,36 @@ fn check_name(checker: &Checker, expr: &Expr, range: TextRange) { // airflow.utils.dates ["dates", "date_range"] => Replacement::None, - ["dates", "days_ago"] => Replacement::Name("pendulum.today('UTC').add(days=-N, ...)"), + ["dates", "days_ago"] => { + Replacement::Message("Use `pendulum.today('UTC').add(days=-N, ...)` instead") + } ["dates", "parse_execution_date" | "round_time" | "scale_time_units" | "infer_time_unit"] => { Replacement::None } // airflow.utils.file - ["file", "TemporaryDirectory"] => Replacement::Name("tempfile.TemporaryDirectory"), - ["file", "mkdirs"] => Replacement::Name("pathlib.Path({path}).mkdir"), + ["file", "TemporaryDirectory"] => Replacement::AutoImport { + module: "tempfile", + name: "TemporaryDirectory", + }, + ["file", "mkdirs"] => Replacement::Message("Use `pathlib.Path({path}).mkdir` instead"), // airflow.utils.helpers - ["helpers", "chain"] => Replacement::Name("airflow.sdk.chain"), - ["helpers", "cross_downstream"] => Replacement::Name("airflow.sdk.cross_downstream"), + ["helpers", "chain"] => Replacement::AutoImport { + module: "airflow.sdk", + name: "chain", + }, + ["helpers", "cross_downstream"] => Replacement::AutoImport { + module: "airflow.sdk", + name: "cross_downstream", + }, + // TODO: update it as SourceModuleMoved // airflow.utils.log.secrets_masker - ["log", "secrets_masker"] => { - Replacement::Name("airflow.sdk.execution_time.secrets_masker") - } + ["log", "secrets_masker"] => Replacement::AutoImport { + module: "airflow.sdk.execution_time", + name: "secrets_masker", + }, // airflow.utils.state ["state", "SHUTDOWN" | "terminating_states"] => Replacement::None, @@ -751,18 +768,20 @@ fn check_name(checker: &Checker, expr: &Expr, range: TextRange) { // airflow.www // TODO: www has been removed ["airflow", "www", "auth", "has_access"] => { - Replacement::Name("airflow.www.auth.has_access_*") + Replacement::Message("Use `airflow.www.auth.has_access_*` instead") } ["airflow", "www", "auth", "has_access_dataset"] => Replacement::AutoImport { module: "airflow.www.auth", name: "has_access_asset", }, - ["airflow", "www", "utils", "get_sensitive_variables_fields"] => { - Replacement::Name("airflow.utils.log.secrets_masker.get_sensitive_variables_fields") - } - ["airflow", "www", "utils", "should_hide_value_for_key"] => { - Replacement::Name("airflow.utils.log.secrets_masker.should_hide_value_for_key") - } + ["airflow", "www", "utils", "get_sensitive_variables_fields"] => Replacement::AutoImport { + module: "airflow.utils.log.secrets_masker", + name: "get_sensitive_variables_fields", + }, + ["airflow", "www", "utils", "should_hide_value_for_key"] => Replacement::AutoImport { + module: "airflow.utils.log.secrets_masker", + name: "should_hide_value_for_key", + }, // airflow.providers.amazon ["airflow", "providers", "amazon", "aws", "datasets", "s3", rest] => match *rest { @@ -774,9 +793,10 @@ fn check_name(checker: &Checker, expr: &Expr, range: TextRange) { module: "airflow.providers.amazon.aws.assets.s3", name: "convert_asset_to_openlineage", }, - "sanitize_uri" => { - Replacement::Name("airflow.providers.amazon.aws.assets.s3.sanitize_uri") - } + "sanitize_uri" => Replacement::AutoImport { + module: "airflow.providers.amazon.aws.assets.s3", + name: "sanitize_uri", + }, _ => return, }, ["airflow", "providers", "amazon", "aws", "auth_manager", "avp", "entities", "AvpEntities", "DATASET"] => { @@ -797,9 +817,10 @@ fn check_name(checker: &Checker, expr: &Expr, range: TextRange) { module: "airflow.providers.common.io.assets.file", name: "convert_asset_to_openlineage", }, - "sanitize_uri" => { - Replacement::Name("airflow.providers.common.io.assets.file.sanitize_uri") - } + "sanitize_uri" => Replacement::AutoImport { + module: "airflow.providers.common.io.assets.file", + name: "sanitize_uri", + }, _ => return, }, @@ -826,20 +847,28 @@ fn check_name(checker: &Checker, expr: &Expr, range: TextRange) { module: "airflow.providers.google.assets.gcs", name: "convert_asset_to_openlineage", }, - ["gcs", "sanitize_uri"] => { - Replacement::Name("airflow.providers.google.assets.gcs.sanitize_uri") - } + ["gcs", "sanitize_uri"] => Replacement::AutoImport { + module: "airflow.providers.google.assets.gcs", + name: "sanitize_uri", + }, + _ => return, }, // airflow.providers.mysql ["airflow", "providers", "mysql", "datasets", "mysql", "sanitize_uri"] => { - Replacement::Name("airflow.providers.mysql.assets.mysql.sanitize_uri") + Replacement::AutoImport { + module: "airflow.providers.mysql.assets.mysql", + name: "sanitize_uri", + } } // airflow.providers.postgres ["airflow", "providers", "postgres", "datasets", "postgres", "sanitize_uri"] => { - Replacement::Name("airflow.providers.postgres.assets.postgres.sanitize_uri") + Replacement::AutoImport { + module: "airflow.providers.postgres.assets.postgres", + name: "sanitize_uri", + } } // airflow.providers.openlineage @@ -859,7 +888,10 @@ fn check_name(checker: &Checker, expr: &Expr, range: TextRange) { // airflow.providers.trino ["airflow", "providers", "trino", "datasets", "trino", "sanitize_uri"] => { - Replacement::Name("airflow.providers.trino.assets.trino.sanitize_uri") + Replacement::AutoImport { + module: "airflow.providers.trino.assets.trino", + name: "sanitize_uri", + } } _ => return, @@ -949,7 +981,7 @@ fn diagnostic_for_argument( Airflow3Removal { deprecated: deprecated.to_string(), replacement: match replacement { - Some(name) => Replacement::Name(name), + Some(name) => Replacement::AttrName(name), None => Replacement::None, }, }, diff --git a/crates/ruff_linter/src/rules/airflow/rules/suggested_to_update_3_0.rs b/crates/ruff_linter/src/rules/airflow/rules/suggested_to_update_3_0.rs index 05b68911b1..09cd9422cc 100644 --- a/crates/ruff_linter/src/rules/airflow/rules/suggested_to_update_3_0.rs +++ b/crates/ruff_linter/src/rules/airflow/rules/suggested_to_update_3_0.rs @@ -53,7 +53,8 @@ impl Violation for Airflow3SuggestedUpdate { } = self; match replacement { Replacement::None - | Replacement::Name(_) + | Replacement::AttrName(_) + | Replacement::Message(_) | Replacement::AutoImport { module: _, name: _ } | Replacement::SourceModuleMoved { module: _, name: _ } => { format!( @@ -61,27 +62,21 @@ impl Violation for Airflow3SuggestedUpdate { It still works in Airflow 3.0 but is expected to be removed in a future version." ) } - Replacement::Message(message) => { - format!( - "`{deprecated}` is removed in Airflow 3.0; \ - It still works in Airflow 3.0 but is expected to be removed in a future version.; \ - {message}" - ) - } } } fn fix_title(&self) -> Option { let Airflow3SuggestedUpdate { replacement, .. } = self; match replacement { - Replacement::Name(name) => Some(format!("Use `{name}` instead")), + Replacement::None => None, + Replacement::AttrName(name) => Some(format!("Use `{name}` instead")), + Replacement::Message(message) => Some((*message).to_string()), Replacement::AutoImport { module, name } => { Some(format!("Use `{module}.{name}` instead")) } Replacement::SourceModuleMoved { module, name } => { Some(format!("Use `{module}.{name}` instead")) } - _ => None, } } } @@ -126,7 +121,7 @@ fn diagnostic_for_argument( Airflow3SuggestedUpdate { deprecated: deprecated.to_string(), replacement: match replacement { - Some(name) => Replacement::Name(name), + Some(name) => Replacement::AttrName(name), None => Replacement::None, }, }, diff --git a/crates/ruff_linter/src/rules/airflow/snapshots/ruff_linter__rules__airflow__tests__AIR301_AIR301_airflow_plugin.py.snap b/crates/ruff_linter/src/rules/airflow/snapshots/ruff_linter__rules__airflow__tests__AIR301_AIR301_airflow_plugin.py.snap index dc16e1812b..173877e2d8 100644 --- a/crates/ruff_linter/src/rules/airflow/snapshots/ruff_linter__rules__airflow__tests__AIR301_AIR301_airflow_plugin.py.snap +++ b/crates/ruff_linter/src/rules/airflow/snapshots/ruff_linter__rules__airflow__tests__AIR301_AIR301_airflow_plugin.py.snap @@ -1,7 +1,7 @@ --- source: crates/ruff_linter/src/rules/airflow/mod.rs --- -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. +AIR301_airflow_plugin.py:7:5: AIR301 `operators` is removed in Airflow 3.0 | 5 | name = "test_plugin" 6 | # --- Invalid extensions start @@ -10,8 +10,9 @@ AIR301_airflow_plugin.py:7:5: AIR301 `operators` is removed in Airflow 3.0; This 8 | sensors = [PluginSensorOperator] 9 | hooks = [PluginHook] | + = help: 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. +AIR301_airflow_plugin.py:8:5: AIR301 `sensors` is removed in Airflow 3.0 | 6 | # --- Invalid extensions start 7 | operators = [PluginOperator] @@ -20,8 +21,9 @@ AIR301_airflow_plugin.py:8:5: AIR301 `sensors` is removed in Airflow 3.0; This e 9 | hooks = [PluginHook] 10 | executors = [PluginExecutor] | + = help: 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. +AIR301_airflow_plugin.py:9:5: AIR301 `hooks` is removed in Airflow 3.0 | 7 | operators = [PluginOperator] 8 | sensors = [PluginSensorOperator] @@ -30,8 +32,9 @@ AIR301_airflow_plugin.py:9:5: AIR301 `hooks` is removed in Airflow 3.0; This ext 10 | executors = [PluginExecutor] 11 | # --- Invalid extensions end | + = help: 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. +AIR301_airflow_plugin.py:10:5: AIR301 `executors` is removed in Airflow 3.0 | 8 | sensors = [PluginSensorOperator] 9 | hooks = [PluginHook] @@ -40,3 +43,4 @@ AIR301_airflow_plugin.py:10:5: AIR301 `executors` is removed in Airflow 3.0; Thi 11 | # --- Invalid extensions end 12 | macros = [plugin_macro] | + = help: This extension should just be imported as a regular python module. diff --git a/crates/ruff_linter/src/rules/airflow/snapshots/ruff_linter__rules__airflow__tests__AIR301_AIR301_args.py.snap b/crates/ruff_linter/src/rules/airflow/snapshots/ruff_linter__rules__airflow__tests__AIR301_AIR301_args.py.snap index 4731893731..17ca7e2196 100644 --- a/crates/ruff_linter/src/rules/airflow/snapshots/ruff_linter__rules__airflow__tests__AIR301_AIR301_args.py.snap +++ b/crates/ruff_linter/src/rules/airflow/snapshots/ruff_linter__rules__airflow__tests__AIR301_AIR301_args.py.snap @@ -258,10 +258,11 @@ AIR301_args.py:90:16: AIR301 `filename_template` is removed in Airflow 3.0 92 | FabAuthManager(None) | -AIR301_args.py:92:15: AIR301 `appbuilder` is removed in Airflow 3.0; The constructor takes no parameter now +AIR301_args.py:92:15: AIR301 `appbuilder` is removed in Airflow 3.0 | 90 | GCSTaskHandler(filename_template="/tmp/test") 91 | 92 | FabAuthManager(None) | ^^^^^^ AIR301 | + = help: The constructor takes no parameter now diff --git a/crates/ruff_linter/src/rules/airflow/snapshots/ruff_linter__rules__airflow__tests__AIR301_AIR301_names.py.snap b/crates/ruff_linter/src/rules/airflow/snapshots/ruff_linter__rules__airflow__tests__AIR301_AIR301_names.py.snap index a45ba0bce2..f64e07f815 100644 --- a/crates/ruff_linter/src/rules/airflow/snapshots/ruff_linter__rules__airflow__tests__AIR301_AIR301_names.py.snap +++ b/crates/ruff_linter/src/rules/airflow/snapshots/ruff_linter__rules__airflow__tests__AIR301_AIR301_names.py.snap @@ -1,448 +1,488 @@ --- source: crates/ruff_linter/src/rules/airflow/mod.rs --- -AIR301_names.py:56:1: AIR301 `airflow.PY36` is removed in Airflow 3.0 +AIR301_names.py:53:1: AIR301 `airflow.PY36` is removed in Airflow 3.0 | -55 | # airflow root -56 | PY36, PY37, PY38, PY39, PY310, PY311, PY312 +52 | # airflow root +53 | PY36, PY37, PY38, PY39, PY310, PY311, PY312 | ^^^^ AIR301 -57 | -58 | # airflow.api_connexion.security +54 | +55 | # airflow.api_connexion.security | = help: Use `sys.version_info` instead -AIR301_names.py:56:7: AIR301 `airflow.PY37` is removed in Airflow 3.0 +AIR301_names.py:53:7: AIR301 `airflow.PY37` is removed in Airflow 3.0 | -55 | # airflow root -56 | PY36, PY37, PY38, PY39, PY310, PY311, PY312 +52 | # airflow root +53 | PY36, PY37, PY38, PY39, PY310, PY311, PY312 | ^^^^ AIR301 -57 | -58 | # airflow.api_connexion.security +54 | +55 | # airflow.api_connexion.security | = help: Use `sys.version_info` instead -AIR301_names.py:56:13: AIR301 `airflow.PY38` is removed in Airflow 3.0 +AIR301_names.py:53:13: AIR301 `airflow.PY38` is removed in Airflow 3.0 | -55 | # airflow root -56 | PY36, PY37, PY38, PY39, PY310, PY311, PY312 +52 | # airflow root +53 | PY36, PY37, PY38, PY39, PY310, PY311, PY312 | ^^^^ AIR301 -57 | -58 | # airflow.api_connexion.security +54 | +55 | # airflow.api_connexion.security | = help: Use `sys.version_info` instead -AIR301_names.py:56:19: AIR301 `airflow.PY39` is removed in Airflow 3.0 +AIR301_names.py:53:19: AIR301 `airflow.PY39` is removed in Airflow 3.0 | -55 | # airflow root -56 | PY36, PY37, PY38, PY39, PY310, PY311, PY312 +52 | # airflow root +53 | PY36, PY37, PY38, PY39, PY310, PY311, PY312 | ^^^^ AIR301 -57 | -58 | # airflow.api_connexion.security +54 | +55 | # airflow.api_connexion.security | = help: Use `sys.version_info` instead -AIR301_names.py:56:25: AIR301 `airflow.PY310` is removed in Airflow 3.0 +AIR301_names.py:53:25: AIR301 `airflow.PY310` is removed in Airflow 3.0 | -55 | # airflow root -56 | PY36, PY37, PY38, PY39, PY310, PY311, PY312 +52 | # airflow root +53 | PY36, PY37, PY38, PY39, PY310, PY311, PY312 | ^^^^^ AIR301 -57 | -58 | # airflow.api_connexion.security +54 | +55 | # airflow.api_connexion.security | = help: Use `sys.version_info` instead -AIR301_names.py:56:32: AIR301 `airflow.PY311` is removed in Airflow 3.0 +AIR301_names.py:53:32: AIR301 `airflow.PY311` is removed in Airflow 3.0 | -55 | # airflow root -56 | PY36, PY37, PY38, PY39, PY310, PY311, PY312 +52 | # airflow root +53 | PY36, PY37, PY38, PY39, PY310, PY311, PY312 | ^^^^^ AIR301 -57 | -58 | # airflow.api_connexion.security +54 | +55 | # airflow.api_connexion.security | = help: Use `sys.version_info` instead -AIR301_names.py:56:39: AIR301 `airflow.PY312` is removed in Airflow 3.0 +AIR301_names.py:53:39: AIR301 `airflow.PY312` is removed in Airflow 3.0 | -55 | # airflow root -56 | PY36, PY37, PY38, PY39, PY310, PY311, PY312 +52 | # airflow root +53 | PY36, PY37, PY38, PY39, PY310, PY311, PY312 | ^^^^^ AIR301 -57 | -58 | # airflow.api_connexion.security +54 | +55 | # airflow.api_connexion.security | = help: Use `sys.version_info` instead -AIR301_names.py:59:1: AIR301 `airflow.api_connexion.security.requires_access` is removed in Airflow 3.0 +AIR301_names.py:56:1: AIR301 `airflow.api_connexion.security.requires_access` is removed in Airflow 3.0 | -58 | # airflow.api_connexion.security -59 | requires_access +55 | # airflow.api_connexion.security +56 | requires_access | ^^^^^^^^^^^^^^^ AIR301 | = help: Use `airflow.api_connexion.security.requires_access_*` instead -AIR301_names.py:63:1: AIR301 `airflow.configuration.get` is removed in Airflow 3.0 +AIR301_names.py:60:1: AIR301 `airflow.configuration.get` is removed in Airflow 3.0 | -62 | # airflow.configuration -63 | get, getboolean, getfloat, getint, has_option, remove_option, as_dict, set +59 | # airflow.configuration +60 | get, getboolean, getfloat, getint, has_option, remove_option, as_dict, set | ^^^ AIR301 | = help: Use `airflow.configuration.conf.get` instead -AIR301_names.py:63:6: AIR301 `airflow.configuration.getboolean` is removed in Airflow 3.0 +AIR301_names.py:60:6: AIR301 `airflow.configuration.getboolean` is removed in Airflow 3.0 | -62 | # airflow.configuration -63 | get, getboolean, getfloat, getint, has_option, remove_option, as_dict, set +59 | # airflow.configuration +60 | get, getboolean, getfloat, getint, has_option, remove_option, as_dict, set | ^^^^^^^^^^ AIR301 | = help: Use `airflow.configuration.conf.getboolean` instead -AIR301_names.py:63:18: AIR301 `airflow.configuration.getfloat` is removed in Airflow 3.0 +AIR301_names.py:60:18: AIR301 `airflow.configuration.getfloat` is removed in Airflow 3.0 | -62 | # airflow.configuration -63 | get, getboolean, getfloat, getint, has_option, remove_option, as_dict, set +59 | # airflow.configuration +60 | get, getboolean, getfloat, getint, has_option, remove_option, as_dict, set | ^^^^^^^^ AIR301 | = help: Use `airflow.configuration.conf.getfloat` instead -AIR301_names.py:63:28: AIR301 `airflow.configuration.getint` is removed in Airflow 3.0 +AIR301_names.py:60:28: AIR301 `airflow.configuration.getint` is removed in Airflow 3.0 | -62 | # airflow.configuration -63 | get, getboolean, getfloat, getint, has_option, remove_option, as_dict, set +59 | # airflow.configuration +60 | get, getboolean, getfloat, getint, has_option, remove_option, as_dict, set | ^^^^^^ AIR301 | = help: Use `airflow.configuration.conf.getint` instead -AIR301_names.py:63:36: AIR301 `airflow.configuration.has_option` is removed in Airflow 3.0 +AIR301_names.py:60:36: AIR301 `airflow.configuration.has_option` is removed in Airflow 3.0 | -62 | # airflow.configuration -63 | get, getboolean, getfloat, getint, has_option, remove_option, as_dict, set +59 | # airflow.configuration +60 | get, getboolean, getfloat, getint, has_option, remove_option, as_dict, set | ^^^^^^^^^^ AIR301 | = help: Use `airflow.configuration.conf.has_option` instead -AIR301_names.py:63:48: AIR301 `airflow.configuration.remove_option` is removed in Airflow 3.0 +AIR301_names.py:60:48: AIR301 `airflow.configuration.remove_option` is removed in Airflow 3.0 | -62 | # airflow.configuration -63 | get, getboolean, getfloat, getint, has_option, remove_option, as_dict, set +59 | # airflow.configuration +60 | get, getboolean, getfloat, getint, has_option, remove_option, as_dict, set | ^^^^^^^^^^^^^ AIR301 | = help: Use `airflow.configuration.conf.remove_option` instead -AIR301_names.py:63:63: AIR301 `airflow.configuration.as_dict` is removed in Airflow 3.0 +AIR301_names.py:60:63: AIR301 `airflow.configuration.as_dict` is removed in Airflow 3.0 | -62 | # airflow.configuration -63 | get, getboolean, getfloat, getint, has_option, remove_option, as_dict, set +59 | # airflow.configuration +60 | get, getboolean, getfloat, getint, has_option, remove_option, as_dict, set | ^^^^^^^ AIR301 | = help: Use `airflow.configuration.conf.as_dict` instead -AIR301_names.py:63:72: AIR301 `airflow.configuration.set` is removed in Airflow 3.0 +AIR301_names.py:60:72: AIR301 `airflow.configuration.set` is removed in Airflow 3.0 | -62 | # airflow.configuration -63 | get, getboolean, getfloat, getint, has_option, remove_option, as_dict, set +59 | # airflow.configuration +60 | get, getboolean, getfloat, getint, has_option, remove_option, as_dict, set | ^^^ AIR301 | = help: Use `airflow.configuration.conf.set` instead -AIR301_names.py:67:1: AIR301 `airflow.contrib.aws_athena_hook.AWSAthenaHook` is removed in Airflow 3.0; The whole `airflow.contrib` module has been removed. +AIR301_names.py:64:1: AIR301 `airflow.contrib.aws_athena_hook.AWSAthenaHook` is removed in Airflow 3.0 | -66 | # airflow.contrib.* -67 | AWSAthenaHook() +63 | # airflow.contrib.* +64 | AWSAthenaHook() | ^^^^^^^^^^^^^ AIR301 | + = help: The whole `airflow.contrib` module has been removed. -AIR301_names.py:71:1: AIR301 `airflow.datasets.DatasetAliasEvent` is removed in Airflow 3.0 +AIR301_names.py:68:1: AIR301 `airflow.datasets.DatasetAliasEvent` is removed in Airflow 3.0 | -70 | # airflow.datasets -71 | DatasetAliasEvent() +67 | # airflow.datasets +68 | DatasetAliasEvent() | ^^^^^^^^^^^^^^^^^ AIR301 | -AIR301_names.py:75:1: AIR301 `airflow.hooks.base_hook.BaseHook` is removed in Airflow 3.0 +AIR301_names.py:72:1: AIR301 `airflow.hooks.base_hook.BaseHook` is removed in Airflow 3.0 | -74 | # airflow.hooks -75 | BaseHook() +71 | # airflow.hooks +72 | BaseHook() | ^^^^^^^^ AIR301 | = help: Use `airflow.hooks.base.BaseHook` instead -AIR301_names.py:79:1: AIR301 `airflow.operators.subdag.SubDagOperator` is removed in Airflow 3.0; The whole `airflow.subdag` module has been removed. +AIR301_names.py:76:1: AIR301 `airflow.operators.subdag.SubDagOperator` is removed in Airflow 3.0 | -78 | # airflow.operators.subdag.* -79 | SubDagOperator() +75 | # airflow.operators.subdag.* +76 | SubDagOperator() | ^^^^^^^^^^^^^^ AIR301 -80 | -81 | # airflow.providers.mysql | + = help: The whole `airflow.subdag` module has been removed. -AIR301_names.py:82:7: AIR301 `airflow.providers.mysql.datasets.mysql.sanitize_uri` is removed in Airflow 3.0 +AIR301_names.py:85:1: AIR301 `airflow.sensors.base_sensor_operator.BaseSensorOperator` is removed in Airflow 3.0 | -81 | # airflow.providers.mysql -82 | mysql.sanitize_uri - | ^^^^^^^^^^^^ AIR301 -83 | -84 | # airflow.providers.postgres - | - = help: Use `airflow.providers.mysql.assets.mysql.sanitize_uri` instead - -AIR301_names.py:85:10: AIR301 `airflow.providers.postgres.datasets.postgres.sanitize_uri` is removed in Airflow 3.0 - | -84 | # airflow.providers.postgres -85 | postgres.sanitize_uri - | ^^^^^^^^^^^^ AIR301 -86 | -87 | # airflow.providers.trino - | - = help: Use `airflow.providers.postgres.assets.postgres.sanitize_uri` instead - -AIR301_names.py:88:7: AIR301 `airflow.providers.trino.datasets.trino.sanitize_uri` is removed in Airflow 3.0 - | -87 | # airflow.providers.trino -88 | trino.sanitize_uri - | ^^^^^^^^^^^^ AIR301 -89 | -90 | # airflow.secrets - | - = help: Use `airflow.providers.trino.assets.trino.sanitize_uri` instead - -AIR301_names.py:96:1: AIR301 `airflow.sensors.base_sensor_operator.BaseSensorOperator` is removed in Airflow 3.0 - | -95 | # airflow.sensors.base_sensor_operator -96 | BaseSensorOperator() +84 | # airflow.sensors.base_sensor_operator +85 | BaseSensorOperator() | ^^^^^^^^^^^^^^^^^^ AIR301 | = help: Use `airflow.sdk.bases.sensor.BaseSensorOperator` instead -AIR301_names.py:100:1: AIR301 `airflow.triggers.external_task.TaskStateTrigger` is removed in Airflow 3.0 +AIR301_names.py:89:1: AIR301 `airflow.triggers.external_task.TaskStateTrigger` is removed in Airflow 3.0 + | +88 | # airflow.triggers.external_task +89 | TaskStateTrigger() + | ^^^^^^^^^^^^^^^^ AIR301 +90 | +91 | # airflow.utils.date + | + +AIR301_names.py:92:7: AIR301 `airflow.utils.dates.date_range` is removed in Airflow 3.0 + | +91 | # airflow.utils.date +92 | dates.date_range + | ^^^^^^^^^^ AIR301 +93 | dates.days_ago + | + +AIR301_names.py:93:7: AIR301 `airflow.utils.dates.days_ago` is removed in Airflow 3.0 + | +91 | # airflow.utils.date +92 | dates.date_range +93 | dates.days_ago + | ^^^^^^^^ AIR301 +94 | +95 | date_range + | + = help: Use `pendulum.today('UTC').add(days=-N, ...)` instead + +AIR301_names.py:95:1: AIR301 `airflow.utils.dates.date_range` is removed in Airflow 3.0 + | +93 | dates.days_ago +94 | +95 | date_range + | ^^^^^^^^^^ AIR301 +96 | days_ago +97 | infer_time_unit + | + +AIR301_names.py:96:1: AIR301 `airflow.utils.dates.days_ago` is removed in Airflow 3.0 + | +95 | date_range +96 | days_ago + | ^^^^^^^^ AIR301 +97 | infer_time_unit +98 | parse_execution_date + | + = help: Use `pendulum.today('UTC').add(days=-N, ...)` instead + +AIR301_names.py:97:1: AIR301 `airflow.utils.dates.infer_time_unit` is removed in Airflow 3.0 + | +95 | date_range +96 | days_ago +97 | infer_time_unit + | ^^^^^^^^^^^^^^^ AIR301 +98 | parse_execution_date +99 | round_time + | + +AIR301_names.py:98:1: AIR301 `airflow.utils.dates.parse_execution_date` is removed in Airflow 3.0 | - 99 | # airflow.triggers.external_task -100 | TaskStateTrigger() + 96 | days_ago + 97 | infer_time_unit + 98 | parse_execution_date + | ^^^^^^^^^^^^^^^^^^^^ AIR301 + 99 | round_time +100 | scale_time_units + | + +AIR301_names.py:99:1: AIR301 `airflow.utils.dates.round_time` is removed in Airflow 3.0 + | + 97 | infer_time_unit + 98 | parse_execution_date + 99 | round_time + | ^^^^^^^^^^ AIR301 +100 | scale_time_units + | + +AIR301_names.py:100:1: AIR301 `airflow.utils.dates.scale_time_units` is removed in Airflow 3.0 + | + 98 | parse_execution_date + 99 | round_time +100 | scale_time_units | ^^^^^^^^^^^^^^^^ AIR301 101 | -102 | # airflow.utils.date +102 | # This one was not deprecated. | -AIR301_names.py:103:7: AIR301 `airflow.utils.dates.date_range` is removed in Airflow 3.0 +AIR301_names.py:107:1: AIR301 `airflow.utils.dag_cycle_tester.test_cycle` is removed in Airflow 3.0 | -102 | # airflow.utils.date -103 | dates.date_range - | ^^^^^^^^^^ AIR301 -104 | dates.days_ago - | - -AIR301_names.py:104:7: AIR301 `airflow.utils.dates.days_ago` is removed in Airflow 3.0 - | -102 | # airflow.utils.date -103 | dates.date_range -104 | dates.days_ago - | ^^^^^^^^ AIR301 -105 | -106 | date_range - | - = help: Use `pendulum.today('UTC').add(days=-N, ...)` instead - -AIR301_names.py:106:1: AIR301 `airflow.utils.dates.date_range` is removed in Airflow 3.0 - | -104 | dates.days_ago -105 | -106 | date_range +106 | # airflow.utils.dag_cycle_tester +107 | test_cycle | ^^^^^^^^^^ AIR301 -107 | days_ago -108 | infer_time_unit | -AIR301_names.py:107:1: AIR301 `airflow.utils.dates.days_ago` is removed in Airflow 3.0 +AIR301_names.py:111:1: AIR301 `airflow.utils.db.create_session` is removed in Airflow 3.0 | -106 | date_range -107 | days_ago - | ^^^^^^^^ AIR301 -108 | infer_time_unit -109 | parse_execution_date - | - = help: Use `pendulum.today('UTC').add(days=-N, ...)` instead - -AIR301_names.py:108:1: AIR301 `airflow.utils.dates.infer_time_unit` is removed in Airflow 3.0 - | -106 | date_range -107 | days_ago -108 | infer_time_unit - | ^^^^^^^^^^^^^^^ AIR301 -109 | parse_execution_date -110 | round_time - | - -AIR301_names.py:109:1: AIR301 `airflow.utils.dates.parse_execution_date` is removed in Airflow 3.0 - | -107 | days_ago -108 | infer_time_unit -109 | parse_execution_date - | ^^^^^^^^^^^^^^^^^^^^ AIR301 -110 | round_time -111 | scale_time_units - | - -AIR301_names.py:110:1: AIR301 `airflow.utils.dates.round_time` is removed in Airflow 3.0 - | -108 | infer_time_unit -109 | parse_execution_date -110 | round_time - | ^^^^^^^^^^ AIR301 -111 | scale_time_units - | - -AIR301_names.py:111:1: AIR301 `airflow.utils.dates.scale_time_units` is removed in Airflow 3.0 - | -109 | parse_execution_date -110 | round_time -111 | scale_time_units - | ^^^^^^^^^^^^^^^^ AIR301 +110 | # airflow.utils.db +111 | create_session + | ^^^^^^^^^^^^^^ AIR301 112 | -113 | # This one was not deprecated. +113 | # airflow.utils.decorators | -AIR301_names.py:118:1: AIR301 `airflow.utils.dag_cycle_tester.test_cycle` is removed in Airflow 3.0 +AIR301_names.py:114:1: AIR301 `airflow.utils.decorators.apply_defaults` is removed in Airflow 3.0 | -117 | # airflow.utils.dag_cycle_tester -118 | test_cycle - | ^^^^^^^^^^ AIR301 - | - -AIR301_names.py:122:1: AIR301 `airflow.utils.db.create_session` is removed in Airflow 3.0 - | -121 | # airflow.utils.db -122 | create_session +113 | # airflow.utils.decorators +114 | apply_defaults | ^^^^^^^^^^^^^^ AIR301 -123 | -124 | # airflow.utils.decorators +115 | +116 | # airflow.utils.file | + = help: `apply_defaults` is now unconditionally done and can be safely removed. -AIR301_names.py:125:1: AIR301 `airflow.utils.decorators.apply_defaults` is removed in Airflow 3.0; `apply_defaults` is now unconditionally done and can be safely removed. +AIR301_names.py:117:1: AIR301 `airflow.utils.file.TemporaryDirectory` is removed in Airflow 3.0 | -124 | # airflow.utils.decorators -125 | apply_defaults - | ^^^^^^^^^^^^^^ AIR301 -126 | -127 | # airflow.utils.file - | - -AIR301_names.py:128:1: AIR301 `airflow.utils.file.TemporaryDirectory` is removed in Airflow 3.0 - | -127 | # airflow.utils.file -128 | TemporaryDirectory() +116 | # airflow.utils.file +117 | TemporaryDirectory() | ^^^^^^^^^^^^^^^^^^ AIR301 -129 | mkdirs +118 | mkdirs | = help: Use `tempfile.TemporaryDirectory` instead -AIR301_names.py:129:1: AIR301 `airflow.utils.file.mkdirs` is removed in Airflow 3.0 +AIR301_names.py:118:1: AIR301 `airflow.utils.file.mkdirs` is removed in Airflow 3.0 | -127 | # airflow.utils.file -128 | TemporaryDirectory() -129 | mkdirs +116 | # airflow.utils.file +117 | TemporaryDirectory() +118 | mkdirs | ^^^^^^ AIR301 -130 | -131 | # airflow.utils.helpers +119 | +120 | # airflow.utils.helpers | = help: Use `pathlib.Path({path}).mkdir` instead -AIR301_names.py:132:1: AIR301 `airflow.utils.helpers.chain` is removed in Airflow 3.0 +AIR301_names.py:121:1: AIR301 [*] `airflow.utils.helpers.chain` is removed in Airflow 3.0 | -131 | # airflow.utils.helpers -132 | helper_chain +120 | # airflow.utils.helpers +121 | helper_chain | ^^^^^^^^^^^^ AIR301 -133 | helper_cross_downstream +122 | helper_cross_downstream | = help: Use `airflow.sdk.chain` instead -AIR301_names.py:133:1: AIR301 `airflow.utils.helpers.cross_downstream` is removed in Airflow 3.0 +ℹ Safe fix +48 48 | from airflow.utils.trigger_rule import TriggerRule +49 49 | from airflow.www.auth import has_access +50 50 | from airflow.www.utils import get_sensitive_variables_fields, should_hide_value_for_key + 51 |+from airflow.sdk import chain +51 52 | +52 53 | # airflow root +53 54 | PY36, PY37, PY38, PY39, PY310, PY311, PY312 +-------------------------------------------------------------------------------- +118 119 | mkdirs +119 120 | +120 121 | # airflow.utils.helpers +121 |-helper_chain + 122 |+chain +122 123 | helper_cross_downstream +123 124 | +124 125 | # airflow.utils.log + +AIR301_names.py:122:1: AIR301 [*] `airflow.utils.helpers.cross_downstream` is removed in Airflow 3.0 | -131 | # airflow.utils.helpers -132 | helper_chain -133 | helper_cross_downstream +120 | # airflow.utils.helpers +121 | helper_chain +122 | helper_cross_downstream | ^^^^^^^^^^^^^^^^^^^^^^^ AIR301 -134 | -135 | # airflow.utils.log +123 | +124 | # airflow.utils.log | = help: Use `airflow.sdk.cross_downstream` instead -AIR301_names.py:136:1: AIR301 `airflow.utils.log.secrets_masker` is removed in Airflow 3.0 +ℹ Safe fix +48 48 | from airflow.utils.trigger_rule import TriggerRule +49 49 | from airflow.www.auth import has_access +50 50 | from airflow.www.utils import get_sensitive_variables_fields, should_hide_value_for_key + 51 |+from airflow.sdk import cross_downstream +51 52 | +52 53 | # airflow root +53 54 | PY36, PY37, PY38, PY39, PY310, PY311, PY312 +-------------------------------------------------------------------------------- +119 120 | +120 121 | # airflow.utils.helpers +121 122 | helper_chain +122 |-helper_cross_downstream + 123 |+cross_downstream +123 124 | +124 125 | # airflow.utils.log +125 126 | secrets_masker + +AIR301_names.py:125:1: AIR301 `airflow.utils.log.secrets_masker` is removed in Airflow 3.0 | -135 | # airflow.utils.log -136 | secrets_masker +124 | # airflow.utils.log +125 | secrets_masker | ^^^^^^^^^^^^^^ AIR301 -137 | -138 | # airflow.utils.state +126 | +127 | # airflow.utils.state | = help: Use `airflow.sdk.execution_time.secrets_masker` instead -AIR301_names.py:139:1: AIR301 `airflow.utils.state.SHUTDOWN` is removed in Airflow 3.0 +AIR301_names.py:128:1: AIR301 `airflow.utils.state.SHUTDOWN` is removed in Airflow 3.0 | -138 | # airflow.utils.state -139 | SHUTDOWN +127 | # airflow.utils.state +128 | SHUTDOWN | ^^^^^^^^ AIR301 -140 | terminating_states +129 | terminating_states | -AIR301_names.py:140:1: AIR301 `airflow.utils.state.terminating_states` is removed in Airflow 3.0 +AIR301_names.py:129:1: AIR301 `airflow.utils.state.terminating_states` is removed in Airflow 3.0 | -138 | # airflow.utils.state -139 | SHUTDOWN -140 | terminating_states +127 | # airflow.utils.state +128 | SHUTDOWN +129 | terminating_states | ^^^^^^^^^^^^^^^^^^ AIR301 -141 | -142 | # airflow.utils.trigger_rule +130 | +131 | # airflow.utils.trigger_rule | -AIR301_names.py:143:13: AIR301 `airflow.utils.trigger_rule.TriggerRule.DUMMY` is removed in Airflow 3.0 +AIR301_names.py:132:13: AIR301 `airflow.utils.trigger_rule.TriggerRule.DUMMY` is removed in Airflow 3.0 | -142 | # airflow.utils.trigger_rule -143 | TriggerRule.DUMMY +131 | # airflow.utils.trigger_rule +132 | TriggerRule.DUMMY | ^^^^^ AIR301 -144 | TriggerRule.NONE_FAILED_OR_SKIPPED +133 | TriggerRule.NONE_FAILED_OR_SKIPPED | -AIR301_names.py:144:13: AIR301 `airflow.utils.trigger_rule.TriggerRule.NONE_FAILED_OR_SKIPPED` is removed in Airflow 3.0 +AIR301_names.py:133:13: AIR301 `airflow.utils.trigger_rule.TriggerRule.NONE_FAILED_OR_SKIPPED` is removed in Airflow 3.0 | -142 | # airflow.utils.trigger_rule -143 | TriggerRule.DUMMY -144 | TriggerRule.NONE_FAILED_OR_SKIPPED +131 | # airflow.utils.trigger_rule +132 | TriggerRule.DUMMY +133 | TriggerRule.NONE_FAILED_OR_SKIPPED | ^^^^^^^^^^^^^^^^^^^^^^ AIR301 | -AIR301_names.py:148:1: AIR301 `airflow.www.auth.has_access` is removed in Airflow 3.0 +AIR301_names.py:137:1: AIR301 `airflow.www.auth.has_access` is removed in Airflow 3.0 | -147 | # airflow.www.auth -148 | has_access +136 | # airflow.www.auth +137 | has_access | ^^^^^^^^^^ AIR301 -149 | -150 | # airflow.www.utils +138 | +139 | # airflow.www.utils | = help: Use `airflow.www.auth.has_access_*` instead -AIR301_names.py:151:1: AIR301 `airflow.www.utils.get_sensitive_variables_fields` is removed in Airflow 3.0 +AIR301_names.py:140:1: AIR301 `airflow.www.utils.get_sensitive_variables_fields` is removed in Airflow 3.0 | -150 | # airflow.www.utils -151 | get_sensitive_variables_fields +139 | # airflow.www.utils +140 | get_sensitive_variables_fields | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AIR301 -152 | should_hide_value_for_key +141 | should_hide_value_for_key | = help: Use `airflow.utils.log.secrets_masker.get_sensitive_variables_fields` instead -AIR301_names.py:152:1: AIR301 `airflow.www.utils.should_hide_value_for_key` is removed in Airflow 3.0 +AIR301_names.py:141:1: AIR301 `airflow.www.utils.should_hide_value_for_key` is removed in Airflow 3.0 | -150 | # airflow.www.utils -151 | get_sensitive_variables_fields -152 | should_hide_value_for_key +139 | # airflow.www.utils +140 | get_sensitive_variables_fields +141 | should_hide_value_for_key | ^^^^^^^^^^^^^^^^^^^^^^^^^ AIR301 -153 | -154 | # airflow.operators.python +142 | +143 | # airflow.operators.python | = help: Use `airflow.utils.log.secrets_masker.should_hide_value_for_key` instead -AIR301_names.py:157:1: AIR301 `airflow.operators.python.get_current_context` is removed in Airflow 3.0 +AIR301_names.py:146:1: AIR301 `airflow.operators.python.get_current_context` is removed in Airflow 3.0 | -155 | from airflow.operators.python import get_current_context -156 | -157 | get_current_context() +144 | from airflow.operators.python import get_current_context +145 | +146 | get_current_context() | ^^^^^^^^^^^^^^^^^^^ AIR301 +147 | +148 | # airflow.providers.mysql | = help: Use `airflow.sdk.get_current_context` instead + +AIR301_names.py:151:1: AIR301 `airflow.providers.mysql.datasets.mysql.sanitize_uri` is removed in Airflow 3.0 + | +149 | from airflow.providers.mysql.datasets.mysql import sanitize_uri +150 | +151 | sanitize_uri + | ^^^^^^^^^^^^ AIR301 +152 | +153 | # airflow.providers.postgres + | + = help: Use `airflow.providers.mysql.assets.mysql.sanitize_uri` instead + +AIR301_names.py:156:1: AIR301 `airflow.providers.postgres.datasets.postgres.sanitize_uri` is removed in Airflow 3.0 + | +154 | from airflow.providers.postgres.datasets.postgres import sanitize_uri +155 | +156 | sanitize_uri + | ^^^^^^^^^^^^ AIR301 +157 | +158 | # airflow.providers.trino + | + = help: Use `airflow.providers.postgres.assets.postgres.sanitize_uri` instead + +AIR301_names.py:161:1: AIR301 `airflow.providers.trino.datasets.trino.sanitize_uri` is removed in Airflow 3.0 + | +159 | from airflow.providers.trino.datasets.trino import sanitize_uri +160 | +161 | sanitize_uri + | ^^^^^^^^^^^^ AIR301 + | + = help: Use `airflow.providers.trino.assets.trino.sanitize_uri` instead