mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-04 02:38:25 +00:00
[airflow
] Extend airflow context parameter check for BaseOperator.execute
(AIR302
) (#15713)
## Summary <!-- What's the purpose of the change? What does it do, and why? --> * feat * add is_execute_method_inherits_from_airflow_operator for checking the removed context key in the execute method * refactor: rename * is_airflow_task as is_airflow_task_function_def * in_airflow_task as in_airflow_task_function_def * removed_in_3 as airflow_3_removal_expr * removed_in_3_function_def as airflow_3_removal_function_def * test: * reorganize test cases ## Test Plan a test fixture has been updated --------- Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
This commit is contained in:
parent
646f1942aa
commit
c161e4fb12
5 changed files with 404 additions and 323 deletions
|
@ -1,7 +1,8 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
import pendulum
|
||||
|
||||
from airflow.decorators import dag, task
|
||||
from airflow.models import DAG
|
||||
from airflow.models.baseoperator import BaseOperator
|
||||
|
@ -13,30 +14,22 @@ from airflow.utils.context import get_current_context
|
|||
|
||||
def access_invalid_key_in_context(**context):
|
||||
print("access invalid key", context["conf"])
|
||||
print("access invalid key", context.get("conf"))
|
||||
|
||||
|
||||
@task
|
||||
def access_invalid_key_task_out_of_dag(**context):
|
||||
print("access invalid key", context["conf"])
|
||||
print("access invalid key", context.get("conf"))
|
||||
|
||||
@dag(
|
||||
schedule=None,
|
||||
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
|
||||
catchup=False,
|
||||
tags=[""],
|
||||
)
|
||||
def invalid_dag():
|
||||
@task()
|
||||
def access_invalid_key_task(**context):
|
||||
print("access invalid key", context.get("conf"))
|
||||
|
||||
task1 = PythonOperator(
|
||||
task_id="task1",
|
||||
python_callable=access_invalid_key_in_context,
|
||||
)
|
||||
access_invalid_key_task() >> task1
|
||||
access_invalid_key_task_out_of_dag()
|
||||
@task
|
||||
def access_invalid_argument_task_out_of_dag(
|
||||
execution_date, tomorrow_ds, logical_date, **context
|
||||
):
|
||||
print("execution date", execution_date)
|
||||
print("access invalid key", context.get("conf"))
|
||||
|
||||
invalid_dag()
|
||||
|
||||
@task
|
||||
def print_config(**context):
|
||||
|
@ -56,31 +49,9 @@ def print_config(**context):
|
|||
yesterday_ds = context["yesterday_ds"]
|
||||
yesterday_ds_nodash = context["yesterday_ds_nodash"]
|
||||
|
||||
with DAG(
|
||||
dag_id="example_dag",
|
||||
schedule_interval="@daily",
|
||||
start_date=datetime(2023, 1, 1),
|
||||
template_searchpath=["/templates"],
|
||||
) as dag:
|
||||
task1 = DummyOperator(
|
||||
task_id="task1",
|
||||
params={
|
||||
# Removed variables in template
|
||||
"execution_date": "{{ execution_date }}",
|
||||
"next_ds": "{{ next_ds }}",
|
||||
"prev_ds": "{{ prev_ds }}"
|
||||
},
|
||||
)
|
||||
|
||||
class CustomMacrosPlugin(AirflowPlugin):
|
||||
name = "custom_macros"
|
||||
macros = {
|
||||
"execution_date_macro": lambda context: context["execution_date"],
|
||||
"next_ds_macro": lambda context: context["next_ds"]
|
||||
}
|
||||
|
||||
@task
|
||||
def print_config():
|
||||
def print_config_with_get_current_context():
|
||||
context = get_current_context()
|
||||
execution_date = context["execution_date"]
|
||||
next_ds = context["next_ds"]
|
||||
|
@ -94,8 +65,74 @@ def print_config():
|
|||
yesterday_ds = context["yesterday_ds"]
|
||||
yesterday_ds_nodash = context["yesterday_ds_nodash"]
|
||||
|
||||
|
||||
@task(task_id="print_the_context")
|
||||
def print_context(ds=None, **kwargs):
|
||||
"""Print the Airflow context and ds variable from the context."""
|
||||
print(ds)
|
||||
print(kwargs.get("tomorrow_ds"))
|
||||
c = get_current_context()
|
||||
c.get("execution_date")
|
||||
|
||||
|
||||
@dag(
|
||||
schedule=None,
|
||||
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
|
||||
catchup=False,
|
||||
tags=[""],
|
||||
)
|
||||
def invalid_dag():
|
||||
@task()
|
||||
def access_invalid_key_task(**context):
|
||||
print("access invalid key", context.get("conf"))
|
||||
|
||||
@task()
|
||||
def access_invalid_key_explicit_task(execution_date):
|
||||
print(execution_date)
|
||||
|
||||
task1 = PythonOperator(
|
||||
task_id="task1",
|
||||
python_callable=access_invalid_key_in_context,
|
||||
)
|
||||
|
||||
access_invalid_key_task() >> task1
|
||||
access_invalid_key_explicit_task()
|
||||
access_invalid_argument_task_out_of_dag()
|
||||
access_invalid_key_task_out_of_dag()
|
||||
print_config()
|
||||
print_config_with_get_current_context()
|
||||
print_context()
|
||||
|
||||
|
||||
invalid_dag()
|
||||
|
||||
with DAG(
|
||||
dag_id="example_dag",
|
||||
schedule_interval="@daily",
|
||||
start_date=datetime(2023, 1, 1),
|
||||
template_searchpath=["/templates"],
|
||||
) as dag:
|
||||
task1 = DummyOperator(
|
||||
task_id="task1",
|
||||
params={
|
||||
# Removed variables in template
|
||||
"execution_date": "{{ execution_date }}",
|
||||
"next_ds": "{{ next_ds }}",
|
||||
"prev_ds": "{{ prev_ds }}",
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
class CustomMacrosPlugin(AirflowPlugin):
|
||||
name = "custom_macros"
|
||||
macros = {
|
||||
"execution_date_macro": lambda context: context["execution_date"],
|
||||
"next_ds_macro": lambda context: context["next_ds"],
|
||||
}
|
||||
|
||||
|
||||
class CustomOperator(BaseOperator):
|
||||
def execute(self, context):
|
||||
def execute(self, next_ds, context):
|
||||
execution_date = context["execution_date"]
|
||||
next_ds = context["next_ds"]
|
||||
next_ds_nodash = context["next_ds_nodash"]
|
||||
|
@ -108,18 +145,6 @@ class CustomOperator(BaseOperator):
|
|||
yesterday_ds = context["yesterday_ds"]
|
||||
yesterday_ds_nodash = context["yesterday_ds_nodash"]
|
||||
|
||||
@task
|
||||
def access_invalid_argument_task_out_of_dag(execution_date, tomorrow_ds, logical_date, **context):
|
||||
print("execution date", execution_date)
|
||||
print("access invalid key", context.get("conf"))
|
||||
|
||||
@task(task_id="print_the_context")
|
||||
def print_context(ds=None, **kwargs):
|
||||
"""Print the Airflow context and ds variable from the context."""
|
||||
print(ds)
|
||||
print(kwargs.get("tomorrow_ds"))
|
||||
c = get_current_context()
|
||||
c.get("execution_date")
|
||||
|
||||
class CustomOperatorNew(BaseOperator):
|
||||
def execute(self, context):
|
||||
|
|
|
@ -176,7 +176,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
|||
pyupgrade::rules::use_pep646_unpack(checker, subscript);
|
||||
}
|
||||
if checker.enabled(Rule::Airflow3Removal) {
|
||||
airflow::rules::removed_in_3(checker, expr);
|
||||
airflow::rules::airflow_3_removal_expr(checker, expr);
|
||||
}
|
||||
pandas_vet::rules::subscript(checker, value, expr);
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
|||
refurb::rules::regex_flag_alias(checker, expr);
|
||||
}
|
||||
if checker.enabled(Rule::Airflow3Removal) {
|
||||
airflow::rules::removed_in_3(checker, expr);
|
||||
airflow::rules::airflow_3_removal_expr(checker, expr);
|
||||
}
|
||||
if checker.enabled(Rule::Airflow3MovedToProvider) {
|
||||
airflow::rules::moved_to_provider_in_3(checker, expr);
|
||||
|
@ -311,7 +311,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
|||
}
|
||||
}
|
||||
if checker.enabled(Rule::Airflow3Removal) {
|
||||
airflow::rules::removed_in_3(checker, expr);
|
||||
airflow::rules::airflow_3_removal_expr(checker, expr);
|
||||
}
|
||||
if checker.enabled(Rule::MixedCaseVariableInGlobalScope) {
|
||||
if matches!(checker.semantic.current_scope().kind, ScopeKind::Module) {
|
||||
|
@ -449,7 +449,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
|||
flake8_pyi::rules::bytestring_attribute(checker, expr);
|
||||
}
|
||||
if checker.enabled(Rule::Airflow3Removal) {
|
||||
airflow::rules::removed_in_3(checker, expr);
|
||||
airflow::rules::airflow_3_removal_expr(checker, expr);
|
||||
}
|
||||
}
|
||||
Expr::Call(
|
||||
|
@ -1150,7 +1150,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
|||
ruff::rules::unnecessary_regular_expression(checker, call);
|
||||
}
|
||||
if checker.enabled(Rule::Airflow3Removal) {
|
||||
airflow::rules::removed_in_3(checker, expr);
|
||||
airflow::rules::airflow_3_removal_expr(checker, expr);
|
||||
}
|
||||
if checker.enabled(Rule::UnnecessaryCastToInt) {
|
||||
ruff::rules::unnecessary_cast_to_int(checker, call);
|
||||
|
|
|
@ -377,7 +377,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
flake8_pytest_style::rules::parameter_with_default_argument(checker, function_def);
|
||||
}
|
||||
if checker.enabled(Rule::Airflow3Removal) {
|
||||
airflow::rules::removed_in_3_function_def(checker, function_def);
|
||||
airflow::rules::airflow_3_removal_function_def(checker, function_def);
|
||||
}
|
||||
if checker.enabled(Rule::NonPEP695GenericFunction) {
|
||||
pyupgrade::rules::non_pep695_generic_function(checker, function_def);
|
||||
|
|
|
@ -80,7 +80,7 @@ enum Replacement {
|
|||
}
|
||||
|
||||
/// AIR302
|
||||
pub(crate) fn removed_in_3(checker: &mut Checker, expr: &Expr) {
|
||||
pub(crate) fn airflow_3_removal_expr(checker: &mut Checker, expr: &Expr) {
|
||||
if !checker.semantic().seen_module(Modules::AIRFLOW) {
|
||||
return;
|
||||
}
|
||||
|
@ -117,7 +117,10 @@ pub(crate) fn removed_in_3(checker: &mut Checker, expr: &Expr) {
|
|||
}
|
||||
|
||||
/// AIR302
|
||||
pub(crate) fn removed_in_3_function_def(checker: &mut Checker, function_def: &StmtFunctionDef) {
|
||||
pub(crate) fn airflow_3_removal_function_def(
|
||||
checker: &mut Checker,
|
||||
function_def: &StmtFunctionDef,
|
||||
) {
|
||||
if !checker.semantic().seen_module(Modules::AIRFLOW) {
|
||||
return;
|
||||
}
|
||||
|
@ -154,7 +157,9 @@ const REMOVED_CONTEXT_KEYS: [&str; 12] = [
|
|||
/// pass
|
||||
/// ```
|
||||
fn check_function_parameters(checker: &mut Checker, function_def: &StmtFunctionDef) {
|
||||
if !is_airflow_task(function_def, checker.semantic()) {
|
||||
if !is_airflow_task_function_def(function_def, checker.semantic())
|
||||
&& !is_execute_method_inherits_from_airflow_operator(function_def, checker.semantic())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -346,7 +351,7 @@ fn check_class_attribute(checker: &mut Checker, attribute_expr: &ExprAttribute)
|
|||
/// context.get("conf") # 'conf' is removed in Airflow 3.0
|
||||
/// ```
|
||||
fn check_context_key_usage_in_call(checker: &mut Checker, call_expr: &ExprCall) {
|
||||
if !in_airflow_task_function(checker.semantic()) {
|
||||
if !in_airflow_task_function_def(checker.semantic()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -395,7 +400,7 @@ fn check_context_key_usage_in_call(checker: &mut Checker, call_expr: &ExprCall)
|
|||
/// Check if a subscript expression accesses a removed Airflow context variable.
|
||||
/// If a removed key is found, push a corresponding diagnostic.
|
||||
fn check_context_key_usage_in_subscript(checker: &mut Checker, subscript: &ExprSubscript) {
|
||||
if !in_airflow_task_function(checker.semantic()) {
|
||||
if !in_airflow_task_function_def(checker.semantic()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1059,15 +1064,15 @@ fn is_airflow_builtin_or_provider(segments: &[&str], module: &str, symbol_suffix
|
|||
|
||||
/// Returns `true` if the current statement hierarchy has a function that's decorated with
|
||||
/// `@airflow.decorators.task`.
|
||||
fn in_airflow_task_function(semantic: &SemanticModel) -> bool {
|
||||
fn in_airflow_task_function_def(semantic: &SemanticModel) -> bool {
|
||||
semantic
|
||||
.current_statements()
|
||||
.find_map(|stmt| stmt.as_function_def_stmt())
|
||||
.is_some_and(|function_def| is_airflow_task(function_def, semantic))
|
||||
.is_some_and(|function_def| is_airflow_task_function_def(function_def, semantic))
|
||||
}
|
||||
|
||||
/// Returns `true` if the given function is decorated with `@airflow.decorators.task`.
|
||||
fn is_airflow_task(function_def: &StmtFunctionDef, semantic: &SemanticModel) -> bool {
|
||||
fn is_airflow_task_function_def(function_def: &StmtFunctionDef, semantic: &SemanticModel) -> bool {
|
||||
function_def.decorator_list.iter().any(|decorator| {
|
||||
semantic
|
||||
.resolve_qualified_name(map_callable(&decorator.expression))
|
||||
|
@ -1076,3 +1081,35 @@ fn is_airflow_task(function_def: &StmtFunctionDef, semantic: &SemanticModel) ->
|
|||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// Check it's "execute" method inherits from Airflow base operator
|
||||
///
|
||||
/// For example:
|
||||
///
|
||||
/// ```python
|
||||
/// from airflow.models.baseoperator import BaseOperator
|
||||
///
|
||||
/// class CustomOperator(BaseOperator):
|
||||
/// def execute(self):
|
||||
/// pass
|
||||
/// ```
|
||||
fn is_execute_method_inherits_from_airflow_operator(
|
||||
function_def: &StmtFunctionDef,
|
||||
semantic: &SemanticModel,
|
||||
) -> bool {
|
||||
if function_def.name.as_str() != "execute" {
|
||||
return false;
|
||||
}
|
||||
|
||||
let ScopeKind::Class(class_def) = semantic.current_scope().kind else {
|
||||
return false;
|
||||
};
|
||||
|
||||
class_def.bases().iter().any(|class_base| {
|
||||
semantic
|
||||
.resolve_qualified_name(class_base)
|
||||
.is_some_and(|qualified_name| {
|
||||
matches!(qualified_name.segments(), ["airflow", .., "BaseOperator"])
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,319 +1,338 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/airflow/mod.rs
|
||||
snapshot_kind: text
|
||||
---
|
||||
AIR302_context.py:19:45: AIR302 `conf` is removed in Airflow 3.0
|
||||
AIR302_context.py:22:41: AIR302 `conf` is removed in Airflow 3.0
|
||||
|
|
||||
17 | @task
|
||||
18 | def access_invalid_key_task_out_of_dag(**context):
|
||||
19 | print("access invalid key", context.get("conf"))
|
||||
20 | @task
|
||||
21 | def access_invalid_key_task_out_of_dag(**context):
|
||||
22 | print("access invalid key", context["conf"])
|
||||
| ^^^^^^ AIR302
|
||||
23 | print("access invalid key", context.get("conf"))
|
||||
|
|
||||
|
||||
AIR302_context.py:23:45: AIR302 `conf` is removed in Airflow 3.0
|
||||
|
|
||||
21 | def access_invalid_key_task_out_of_dag(**context):
|
||||
22 | print("access invalid key", context["conf"])
|
||||
23 | print("access invalid key", context.get("conf"))
|
||||
| ^^^^^^ AIR302
|
||||
20 |
|
||||
21 | @dag(
|
||||
|
|
||||
|
||||
AIR302_context.py:30:49: AIR302 `conf` is removed in Airflow 3.0
|
||||
AIR302_context.py:28:5: AIR302 `execution_date` is removed in Airflow 3.0
|
||||
|
|
||||
28 | @task()
|
||||
29 | def access_invalid_key_task(**context):
|
||||
30 | print("access invalid key", context.get("conf"))
|
||||
| ^^^^^^ AIR302
|
||||
31 |
|
||||
32 | task1 = PythonOperator(
|
||||
26 | @task
|
||||
27 | def access_invalid_argument_task_out_of_dag(
|
||||
28 | execution_date, tomorrow_ds, logical_date, **context
|
||||
| ^^^^^^^^^^^^^^ AIR302
|
||||
29 | ):
|
||||
30 | print("execution date", execution_date)
|
||||
|
|
||||
|
||||
AIR302_context.py:47:30: AIR302 `execution_date` is removed in Airflow 3.0
|
||||
AIR302_context.py:28:21: AIR302 `tomorrow_ds` is removed in Airflow 3.0
|
||||
|
|
||||
46 | # Removed usage - should trigger violations
|
||||
47 | execution_date = context["execution_date"]
|
||||
26 | @task
|
||||
27 | def access_invalid_argument_task_out_of_dag(
|
||||
28 | execution_date, tomorrow_ds, logical_date, **context
|
||||
| ^^^^^^^^^^^ AIR302
|
||||
29 | ):
|
||||
30 | print("execution date", execution_date)
|
||||
|
|
||||
|
||||
AIR302_context.py:31:45: AIR302 `conf` is removed in Airflow 3.0
|
||||
|
|
||||
29 | ):
|
||||
30 | print("execution date", execution_date)
|
||||
31 | print("access invalid key", context.get("conf"))
|
||||
| ^^^^^^ AIR302
|
||||
|
|
||||
|
||||
AIR302_context.py:40:30: AIR302 `execution_date` is removed in Airflow 3.0
|
||||
|
|
||||
39 | # Removed usage - should trigger violations
|
||||
40 | execution_date = context["execution_date"]
|
||||
| ^^^^^^^^^^^^^^^^ AIR302
|
||||
48 | next_ds = context["next_ds"]
|
||||
49 | next_ds_nodash = context["next_ds_nodash"]
|
||||
41 | next_ds = context["next_ds"]
|
||||
42 | next_ds_nodash = context["next_ds_nodash"]
|
||||
|
|
||||
|
||||
AIR302_context.py:48:23: AIR302 `next_ds` is removed in Airflow 3.0
|
||||
AIR302_context.py:41:23: AIR302 `next_ds` is removed in Airflow 3.0
|
||||
|
|
||||
46 | # Removed usage - should trigger violations
|
||||
47 | execution_date = context["execution_date"]
|
||||
48 | next_ds = context["next_ds"]
|
||||
39 | # Removed usage - should trigger violations
|
||||
40 | execution_date = context["execution_date"]
|
||||
41 | next_ds = context["next_ds"]
|
||||
| ^^^^^^^^^ AIR302
|
||||
49 | next_ds_nodash = context["next_ds_nodash"]
|
||||
50 | next_execution_date = context["next_execution_date"]
|
||||
42 | next_ds_nodash = context["next_ds_nodash"]
|
||||
43 | next_execution_date = context["next_execution_date"]
|
||||
|
|
||||
|
||||
AIR302_context.py:49:30: AIR302 `next_ds_nodash` is removed in Airflow 3.0
|
||||
AIR302_context.py:42:30: AIR302 `next_ds_nodash` is removed in Airflow 3.0
|
||||
|
|
||||
47 | execution_date = context["execution_date"]
|
||||
48 | next_ds = context["next_ds"]
|
||||
49 | next_ds_nodash = context["next_ds_nodash"]
|
||||
40 | execution_date = context["execution_date"]
|
||||
41 | next_ds = context["next_ds"]
|
||||
42 | next_ds_nodash = context["next_ds_nodash"]
|
||||
| ^^^^^^^^^^^^^^^^ AIR302
|
||||
50 | next_execution_date = context["next_execution_date"]
|
||||
51 | prev_ds = context["prev_ds"]
|
||||
43 | next_execution_date = context["next_execution_date"]
|
||||
44 | prev_ds = context["prev_ds"]
|
||||
|
|
||||
|
||||
AIR302_context.py:50:35: AIR302 `next_execution_date` is removed in Airflow 3.0
|
||||
AIR302_context.py:43:35: AIR302 `next_execution_date` is removed in Airflow 3.0
|
||||
|
|
||||
48 | next_ds = context["next_ds"]
|
||||
49 | next_ds_nodash = context["next_ds_nodash"]
|
||||
50 | next_execution_date = context["next_execution_date"]
|
||||
41 | next_ds = context["next_ds"]
|
||||
42 | next_ds_nodash = context["next_ds_nodash"]
|
||||
43 | next_execution_date = context["next_execution_date"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
51 | prev_ds = context["prev_ds"]
|
||||
52 | prev_ds_nodash = context["prev_ds_nodash"]
|
||||
44 | prev_ds = context["prev_ds"]
|
||||
45 | prev_ds_nodash = context["prev_ds_nodash"]
|
||||
|
|
||||
|
||||
AIR302_context.py:51:23: AIR302 `prev_ds` is removed in Airflow 3.0
|
||||
AIR302_context.py:44:23: AIR302 `prev_ds` is removed in Airflow 3.0
|
||||
|
|
||||
49 | next_ds_nodash = context["next_ds_nodash"]
|
||||
50 | next_execution_date = context["next_execution_date"]
|
||||
51 | prev_ds = context["prev_ds"]
|
||||
42 | next_ds_nodash = context["next_ds_nodash"]
|
||||
43 | next_execution_date = context["next_execution_date"]
|
||||
44 | prev_ds = context["prev_ds"]
|
||||
| ^^^^^^^^^ AIR302
|
||||
52 | prev_ds_nodash = context["prev_ds_nodash"]
|
||||
53 | prev_execution_date = context["prev_execution_date"]
|
||||
45 | prev_ds_nodash = context["prev_ds_nodash"]
|
||||
46 | prev_execution_date = context["prev_execution_date"]
|
||||
|
|
||||
|
||||
AIR302_context.py:52:30: AIR302 `prev_ds_nodash` is removed in Airflow 3.0
|
||||
AIR302_context.py:45:30: AIR302 `prev_ds_nodash` is removed in Airflow 3.0
|
||||
|
|
||||
50 | next_execution_date = context["next_execution_date"]
|
||||
51 | prev_ds = context["prev_ds"]
|
||||
52 | prev_ds_nodash = context["prev_ds_nodash"]
|
||||
43 | next_execution_date = context["next_execution_date"]
|
||||
44 | prev_ds = context["prev_ds"]
|
||||
45 | prev_ds_nodash = context["prev_ds_nodash"]
|
||||
| ^^^^^^^^^^^^^^^^ AIR302
|
||||
53 | prev_execution_date = context["prev_execution_date"]
|
||||
54 | prev_execution_date_success = context["prev_execution_date_success"]
|
||||
46 | prev_execution_date = context["prev_execution_date"]
|
||||
47 | prev_execution_date_success = context["prev_execution_date_success"]
|
||||
|
|
||||
|
||||
AIR302_context.py:53:35: AIR302 `prev_execution_date` is removed in Airflow 3.0
|
||||
AIR302_context.py:46:35: AIR302 `prev_execution_date` is removed in Airflow 3.0
|
||||
|
|
||||
51 | prev_ds = context["prev_ds"]
|
||||
52 | prev_ds_nodash = context["prev_ds_nodash"]
|
||||
53 | prev_execution_date = context["prev_execution_date"]
|
||||
44 | prev_ds = context["prev_ds"]
|
||||
45 | prev_ds_nodash = context["prev_ds_nodash"]
|
||||
46 | prev_execution_date = context["prev_execution_date"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
54 | prev_execution_date_success = context["prev_execution_date_success"]
|
||||
55 | tomorrow_ds = context["tomorrow_ds"]
|
||||
47 | prev_execution_date_success = context["prev_execution_date_success"]
|
||||
48 | tomorrow_ds = context["tomorrow_ds"]
|
||||
|
|
||||
|
||||
AIR302_context.py:54:43: AIR302 `prev_execution_date_success` is removed in Airflow 3.0
|
||||
AIR302_context.py:47:43: AIR302 `prev_execution_date_success` is removed in Airflow 3.0
|
||||
|
|
||||
52 | prev_ds_nodash = context["prev_ds_nodash"]
|
||||
53 | prev_execution_date = context["prev_execution_date"]
|
||||
54 | prev_execution_date_success = context["prev_execution_date_success"]
|
||||
45 | prev_ds_nodash = context["prev_ds_nodash"]
|
||||
46 | prev_execution_date = context["prev_execution_date"]
|
||||
47 | prev_execution_date_success = context["prev_execution_date_success"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
55 | tomorrow_ds = context["tomorrow_ds"]
|
||||
56 | yesterday_ds = context["yesterday_ds"]
|
||||
48 | tomorrow_ds = context["tomorrow_ds"]
|
||||
49 | yesterday_ds = context["yesterday_ds"]
|
||||
|
|
||||
|
||||
AIR302_context.py:55:27: AIR302 `tomorrow_ds` is removed in Airflow 3.0
|
||||
AIR302_context.py:48:27: AIR302 `tomorrow_ds` is removed in Airflow 3.0
|
||||
|
|
||||
53 | prev_execution_date = context["prev_execution_date"]
|
||||
54 | prev_execution_date_success = context["prev_execution_date_success"]
|
||||
55 | tomorrow_ds = context["tomorrow_ds"]
|
||||
46 | prev_execution_date = context["prev_execution_date"]
|
||||
47 | prev_execution_date_success = context["prev_execution_date_success"]
|
||||
48 | tomorrow_ds = context["tomorrow_ds"]
|
||||
| ^^^^^^^^^^^^^ AIR302
|
||||
56 | yesterday_ds = context["yesterday_ds"]
|
||||
57 | yesterday_ds_nodash = context["yesterday_ds_nodash"]
|
||||
49 | yesterday_ds = context["yesterday_ds"]
|
||||
50 | yesterday_ds_nodash = context["yesterday_ds_nodash"]
|
||||
|
|
||||
|
||||
AIR302_context.py:56:28: AIR302 `yesterday_ds` is removed in Airflow 3.0
|
||||
AIR302_context.py:49:28: AIR302 `yesterday_ds` is removed in Airflow 3.0
|
||||
|
|
||||
54 | prev_execution_date_success = context["prev_execution_date_success"]
|
||||
55 | tomorrow_ds = context["tomorrow_ds"]
|
||||
56 | yesterday_ds = context["yesterday_ds"]
|
||||
47 | prev_execution_date_success = context["prev_execution_date_success"]
|
||||
48 | tomorrow_ds = context["tomorrow_ds"]
|
||||
49 | yesterday_ds = context["yesterday_ds"]
|
||||
| ^^^^^^^^^^^^^^ AIR302
|
||||
57 | yesterday_ds_nodash = context["yesterday_ds_nodash"]
|
||||
50 | yesterday_ds_nodash = context["yesterday_ds_nodash"]
|
||||
|
|
||||
|
||||
AIR302_context.py:57:35: AIR302 `yesterday_ds_nodash` is removed in Airflow 3.0
|
||||
AIR302_context.py:50:35: AIR302 `yesterday_ds_nodash` is removed in Airflow 3.0
|
||||
|
|
||||
55 | tomorrow_ds = context["tomorrow_ds"]
|
||||
56 | yesterday_ds = context["yesterday_ds"]
|
||||
57 | yesterday_ds_nodash = context["yesterday_ds_nodash"]
|
||||
48 | tomorrow_ds = context["tomorrow_ds"]
|
||||
49 | yesterday_ds = context["yesterday_ds"]
|
||||
50 | yesterday_ds_nodash = context["yesterday_ds_nodash"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
58 |
|
||||
59 | with DAG(
|
||||
|
|
||||
|
||||
AIR302_context.py:61:5: AIR302 [*] `schedule_interval` is removed in Airflow 3.0
|
||||
AIR302_context.py:56:30: AIR302 `execution_date` is removed in Airflow 3.0
|
||||
|
|
||||
59 | with DAG(
|
||||
60 | dag_id="example_dag",
|
||||
61 | schedule_interval="@daily",
|
||||
| ^^^^^^^^^^^^^^^^^ AIR302
|
||||
62 | start_date=datetime(2023, 1, 1),
|
||||
63 | template_searchpath=["/templates"],
|
||||
54 | def print_config_with_get_current_context():
|
||||
55 | context = get_current_context()
|
||||
56 | execution_date = context["execution_date"]
|
||||
| ^^^^^^^^^^^^^^^^ AIR302
|
||||
57 | next_ds = context["next_ds"]
|
||||
58 | next_ds_nodash = context["next_ds_nodash"]
|
||||
|
|
||||
= help: Use `schedule` instead
|
||||
|
||||
AIR302_context.py:57:23: AIR302 `next_ds` is removed in Airflow 3.0
|
||||
|
|
||||
55 | context = get_current_context()
|
||||
56 | execution_date = context["execution_date"]
|
||||
57 | next_ds = context["next_ds"]
|
||||
| ^^^^^^^^^ AIR302
|
||||
58 | next_ds_nodash = context["next_ds_nodash"]
|
||||
59 | next_execution_date = context["next_execution_date"]
|
||||
|
|
||||
|
||||
AIR302_context.py:58:30: AIR302 `next_ds_nodash` is removed in Airflow 3.0
|
||||
|
|
||||
56 | execution_date = context["execution_date"]
|
||||
57 | next_ds = context["next_ds"]
|
||||
58 | next_ds_nodash = context["next_ds_nodash"]
|
||||
| ^^^^^^^^^^^^^^^^ AIR302
|
||||
59 | next_execution_date = context["next_execution_date"]
|
||||
60 | prev_ds = context["prev_ds"]
|
||||
|
|
||||
|
||||
AIR302_context.py:59:35: AIR302 `next_execution_date` is removed in Airflow 3.0
|
||||
|
|
||||
57 | next_ds = context["next_ds"]
|
||||
58 | next_ds_nodash = context["next_ds_nodash"]
|
||||
59 | next_execution_date = context["next_execution_date"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
60 | prev_ds = context["prev_ds"]
|
||||
61 | prev_ds_nodash = context["prev_ds_nodash"]
|
||||
|
|
||||
|
||||
AIR302_context.py:60:23: AIR302 `prev_ds` is removed in Airflow 3.0
|
||||
|
|
||||
58 | next_ds_nodash = context["next_ds_nodash"]
|
||||
59 | next_execution_date = context["next_execution_date"]
|
||||
60 | prev_ds = context["prev_ds"]
|
||||
| ^^^^^^^^^ AIR302
|
||||
61 | prev_ds_nodash = context["prev_ds_nodash"]
|
||||
62 | prev_execution_date = context["prev_execution_date"]
|
||||
|
|
||||
|
||||
AIR302_context.py:61:30: AIR302 `prev_ds_nodash` is removed in Airflow 3.0
|
||||
|
|
||||
59 | next_execution_date = context["next_execution_date"]
|
||||
60 | prev_ds = context["prev_ds"]
|
||||
61 | prev_ds_nodash = context["prev_ds_nodash"]
|
||||
| ^^^^^^^^^^^^^^^^ AIR302
|
||||
62 | prev_execution_date = context["prev_execution_date"]
|
||||
63 | prev_execution_date_success = context["prev_execution_date_success"]
|
||||
|
|
||||
|
||||
AIR302_context.py:62:35: AIR302 `prev_execution_date` is removed in Airflow 3.0
|
||||
|
|
||||
60 | prev_ds = context["prev_ds"]
|
||||
61 | prev_ds_nodash = context["prev_ds_nodash"]
|
||||
62 | prev_execution_date = context["prev_execution_date"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
63 | prev_execution_date_success = context["prev_execution_date_success"]
|
||||
64 | tomorrow_ds = context["tomorrow_ds"]
|
||||
|
|
||||
|
||||
AIR302_context.py:63:43: AIR302 `prev_execution_date_success` is removed in Airflow 3.0
|
||||
|
|
||||
61 | prev_ds_nodash = context["prev_ds_nodash"]
|
||||
62 | prev_execution_date = context["prev_execution_date"]
|
||||
63 | prev_execution_date_success = context["prev_execution_date_success"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
64 | tomorrow_ds = context["tomorrow_ds"]
|
||||
65 | yesterday_ds = context["yesterday_ds"]
|
||||
|
|
||||
|
||||
AIR302_context.py:64:27: AIR302 `tomorrow_ds` is removed in Airflow 3.0
|
||||
|
|
||||
62 | prev_execution_date = context["prev_execution_date"]
|
||||
63 | prev_execution_date_success = context["prev_execution_date_success"]
|
||||
64 | tomorrow_ds = context["tomorrow_ds"]
|
||||
| ^^^^^^^^^^^^^ AIR302
|
||||
65 | yesterday_ds = context["yesterday_ds"]
|
||||
66 | yesterday_ds_nodash = context["yesterday_ds_nodash"]
|
||||
|
|
||||
|
||||
AIR302_context.py:65:28: AIR302 `yesterday_ds` is removed in Airflow 3.0
|
||||
|
|
||||
63 | prev_execution_date_success = context["prev_execution_date_success"]
|
||||
64 | tomorrow_ds = context["tomorrow_ds"]
|
||||
65 | yesterday_ds = context["yesterday_ds"]
|
||||
| ^^^^^^^^^^^^^^ AIR302
|
||||
66 | yesterday_ds_nodash = context["yesterday_ds_nodash"]
|
||||
|
|
||||
|
||||
AIR302_context.py:66:35: AIR302 `yesterday_ds_nodash` is removed in Airflow 3.0
|
||||
|
|
||||
64 | tomorrow_ds = context["tomorrow_ds"]
|
||||
65 | yesterday_ds = context["yesterday_ds"]
|
||||
66 | yesterday_ds_nodash = context["yesterday_ds_nodash"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
|
|
||||
|
||||
AIR302_context.py:73:22: AIR302 `tomorrow_ds` is removed in Airflow 3.0
|
||||
|
|
||||
71 | """Print the Airflow context and ds variable from the context."""
|
||||
72 | print(ds)
|
||||
73 | print(kwargs.get("tomorrow_ds"))
|
||||
| ^^^^^^^^^^^^^ AIR302
|
||||
74 | c = get_current_context()
|
||||
75 | c.get("execution_date")
|
||||
|
|
||||
|
||||
AIR302_context.py:75:11: AIR302 `execution_date` is removed in Airflow 3.0
|
||||
|
|
||||
73 | print(kwargs.get("tomorrow_ds"))
|
||||
74 | c = get_current_context()
|
||||
75 | c.get("execution_date")
|
||||
| ^^^^^^^^^^^^^^^^ AIR302
|
||||
|
|
||||
|
||||
AIR302_context.py:87:49: AIR302 `conf` is removed in Airflow 3.0
|
||||
|
|
||||
85 | @task()
|
||||
86 | def access_invalid_key_task(**context):
|
||||
87 | print("access invalid key", context.get("conf"))
|
||||
| ^^^^^^ AIR302
|
||||
88 |
|
||||
89 | @task()
|
||||
|
|
||||
|
||||
AIR302_context.py:90:42: AIR302 `execution_date` is removed in Airflow 3.0
|
||||
|
|
||||
89 | @task()
|
||||
90 | def access_invalid_key_explicit_task(execution_date):
|
||||
| ^^^^^^^^^^^^^^ AIR302
|
||||
91 | print(execution_date)
|
||||
|
|
||||
|
||||
AIR302_context.py:111:5: AIR302 [*] `schedule_interval` is removed in Airflow 3.0
|
||||
|
|
||||
109 | with DAG(
|
||||
110 | dag_id="example_dag",
|
||||
111 | schedule_interval="@daily",
|
||||
| ^^^^^^^^^^^^^^^^^ AIR302
|
||||
112 | start_date=datetime(2023, 1, 1),
|
||||
113 | template_searchpath=["/templates"],
|
||||
|
|
||||
= help: Use `schedule` instead
|
||||
|
||||
ℹ Safe fix
|
||||
58 58 |
|
||||
59 59 | with DAG(
|
||||
60 60 | dag_id="example_dag",
|
||||
61 |- schedule_interval="@daily",
|
||||
61 |+ schedule="@daily",
|
||||
62 62 | start_date=datetime(2023, 1, 1),
|
||||
63 63 | template_searchpath=["/templates"],
|
||||
64 64 | ) as dag:
|
||||
108 108 |
|
||||
109 109 | with DAG(
|
||||
110 110 | dag_id="example_dag",
|
||||
111 |- schedule_interval="@daily",
|
||||
111 |+ schedule="@daily",
|
||||
112 112 | start_date=datetime(2023, 1, 1),
|
||||
113 113 | template_searchpath=["/templates"],
|
||||
114 114 | ) as dag:
|
||||
|
||||
AIR302_context.py:65:13: AIR302 `airflow.operators.dummy.DummyOperator` is removed in Airflow 3.0
|
||||
|
|
||||
63 | template_searchpath=["/templates"],
|
||||
64 | ) as dag:
|
||||
65 | task1 = DummyOperator(
|
||||
| ^^^^^^^^^^^^^ AIR302
|
||||
66 | task_id="task1",
|
||||
67 | params={
|
||||
|
|
||||
= help: Use `airflow.operators.empty.EmptyOperator` instead
|
||||
|
||||
AIR302_context.py:85:30: AIR302 `execution_date` is removed in Airflow 3.0
|
||||
|
|
||||
83 | def print_config():
|
||||
84 | context = get_current_context()
|
||||
85 | execution_date = context["execution_date"]
|
||||
| ^^^^^^^^^^^^^^^^ AIR302
|
||||
86 | next_ds = context["next_ds"]
|
||||
87 | next_ds_nodash = context["next_ds_nodash"]
|
||||
|
|
||||
|
||||
AIR302_context.py:86:23: AIR302 `next_ds` is removed in Airflow 3.0
|
||||
|
|
||||
84 | context = get_current_context()
|
||||
85 | execution_date = context["execution_date"]
|
||||
86 | next_ds = context["next_ds"]
|
||||
| ^^^^^^^^^ AIR302
|
||||
87 | next_ds_nodash = context["next_ds_nodash"]
|
||||
88 | next_execution_date = context["next_execution_date"]
|
||||
|
|
||||
|
||||
AIR302_context.py:87:30: AIR302 `next_ds_nodash` is removed in Airflow 3.0
|
||||
|
|
||||
85 | execution_date = context["execution_date"]
|
||||
86 | next_ds = context["next_ds"]
|
||||
87 | next_ds_nodash = context["next_ds_nodash"]
|
||||
| ^^^^^^^^^^^^^^^^ AIR302
|
||||
88 | next_execution_date = context["next_execution_date"]
|
||||
89 | prev_ds = context["prev_ds"]
|
||||
|
|
||||
|
||||
AIR302_context.py:88:35: AIR302 `next_execution_date` is removed in Airflow 3.0
|
||||
|
|
||||
86 | next_ds = context["next_ds"]
|
||||
87 | next_ds_nodash = context["next_ds_nodash"]
|
||||
88 | next_execution_date = context["next_execution_date"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
89 | prev_ds = context["prev_ds"]
|
||||
90 | prev_ds_nodash = context["prev_ds_nodash"]
|
||||
|
|
||||
|
||||
AIR302_context.py:89:23: AIR302 `prev_ds` is removed in Airflow 3.0
|
||||
|
|
||||
87 | next_ds_nodash = context["next_ds_nodash"]
|
||||
88 | next_execution_date = context["next_execution_date"]
|
||||
89 | prev_ds = context["prev_ds"]
|
||||
| ^^^^^^^^^ AIR302
|
||||
90 | prev_ds_nodash = context["prev_ds_nodash"]
|
||||
91 | prev_execution_date = context["prev_execution_date"]
|
||||
|
|
||||
|
||||
AIR302_context.py:90:30: AIR302 `prev_ds_nodash` is removed in Airflow 3.0
|
||||
|
|
||||
88 | next_execution_date = context["next_execution_date"]
|
||||
89 | prev_ds = context["prev_ds"]
|
||||
90 | prev_ds_nodash = context["prev_ds_nodash"]
|
||||
| ^^^^^^^^^^^^^^^^ AIR302
|
||||
91 | prev_execution_date = context["prev_execution_date"]
|
||||
92 | prev_execution_date_success = context["prev_execution_date_success"]
|
||||
|
|
||||
|
||||
AIR302_context.py:91:35: AIR302 `prev_execution_date` is removed in Airflow 3.0
|
||||
|
|
||||
89 | prev_ds = context["prev_ds"]
|
||||
90 | prev_ds_nodash = context["prev_ds_nodash"]
|
||||
91 | prev_execution_date = context["prev_execution_date"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
92 | prev_execution_date_success = context["prev_execution_date_success"]
|
||||
93 | tomorrow_ds = context["tomorrow_ds"]
|
||||
|
|
||||
|
||||
AIR302_context.py:92:43: AIR302 `prev_execution_date_success` is removed in Airflow 3.0
|
||||
|
|
||||
90 | prev_ds_nodash = context["prev_ds_nodash"]
|
||||
91 | prev_execution_date = context["prev_execution_date"]
|
||||
92 | prev_execution_date_success = context["prev_execution_date_success"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
93 | tomorrow_ds = context["tomorrow_ds"]
|
||||
94 | yesterday_ds = context["yesterday_ds"]
|
||||
|
|
||||
|
||||
AIR302_context.py:93:27: AIR302 `tomorrow_ds` is removed in Airflow 3.0
|
||||
|
|
||||
91 | prev_execution_date = context["prev_execution_date"]
|
||||
92 | prev_execution_date_success = context["prev_execution_date_success"]
|
||||
93 | tomorrow_ds = context["tomorrow_ds"]
|
||||
| ^^^^^^^^^^^^^ AIR302
|
||||
94 | yesterday_ds = context["yesterday_ds"]
|
||||
95 | yesterday_ds_nodash = context["yesterday_ds_nodash"]
|
||||
|
|
||||
|
||||
AIR302_context.py:94:28: AIR302 `yesterday_ds` is removed in Airflow 3.0
|
||||
|
|
||||
92 | prev_execution_date_success = context["prev_execution_date_success"]
|
||||
93 | tomorrow_ds = context["tomorrow_ds"]
|
||||
94 | yesterday_ds = context["yesterday_ds"]
|
||||
| ^^^^^^^^^^^^^^ AIR302
|
||||
95 | yesterday_ds_nodash = context["yesterday_ds_nodash"]
|
||||
|
|
||||
|
||||
AIR302_context.py:95:35: AIR302 `yesterday_ds_nodash` is removed in Airflow 3.0
|
||||
|
|
||||
93 | tomorrow_ds = context["tomorrow_ds"]
|
||||
94 | yesterday_ds = context["yesterday_ds"]
|
||||
95 | yesterday_ds_nodash = context["yesterday_ds_nodash"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
96 |
|
||||
97 | class CustomOperator(BaseOperator):
|
||||
|
|
||||
|
||||
AIR302_context.py:112:45: AIR302 `execution_date` is removed in Airflow 3.0
|
||||
AIR302_context.py:115:13: AIR302 `airflow.operators.dummy.DummyOperator` is removed in Airflow 3.0
|
||||
|
|
||||
111 | @task
|
||||
112 | def access_invalid_argument_task_out_of_dag(execution_date, tomorrow_ds, logical_date, **context):
|
||||
| ^^^^^^^^^^^^^^ AIR302
|
||||
113 | print("execution date", execution_date)
|
||||
114 | print("access invalid key", context.get("conf"))
|
||||
113 | template_searchpath=["/templates"],
|
||||
114 | ) as dag:
|
||||
115 | task1 = DummyOperator(
|
||||
| ^^^^^^^^^^^^^ AIR302
|
||||
116 | task_id="task1",
|
||||
117 | params={
|
||||
|
|
||||
= help: Use `airflow.operators.empty.EmptyOperator` instead
|
||||
|
||||
AIR302_context.py:112:61: AIR302 `tomorrow_ds` is removed in Airflow 3.0
|
||||
AIR302_context.py:135:23: AIR302 `next_ds` is removed in Airflow 3.0
|
||||
|
|
||||
111 | @task
|
||||
112 | def access_invalid_argument_task_out_of_dag(execution_date, tomorrow_ds, logical_date, **context):
|
||||
| ^^^^^^^^^^^ AIR302
|
||||
113 | print("execution date", execution_date)
|
||||
114 | print("access invalid key", context.get("conf"))
|
||||
|
|
||||
|
||||
AIR302_context.py:114:45: AIR302 `conf` is removed in Airflow 3.0
|
||||
|
|
||||
112 | def access_invalid_argument_task_out_of_dag(execution_date, tomorrow_ds, logical_date, **context):
|
||||
113 | print("execution date", execution_date)
|
||||
114 | print("access invalid key", context.get("conf"))
|
||||
| ^^^^^^ AIR302
|
||||
115 |
|
||||
116 | @task(task_id="print_the_context")
|
||||
|
|
||||
|
||||
AIR302_context.py:120:22: AIR302 `tomorrow_ds` is removed in Airflow 3.0
|
||||
|
|
||||
118 | """Print the Airflow context and ds variable from the context."""
|
||||
119 | print(ds)
|
||||
120 | print(kwargs.get("tomorrow_ds"))
|
||||
| ^^^^^^^^^^^^^ AIR302
|
||||
121 | c = get_current_context()
|
||||
122 | c.get("execution_date")
|
||||
|
|
||||
|
||||
AIR302_context.py:122:11: AIR302 `execution_date` is removed in Airflow 3.0
|
||||
|
|
||||
120 | print(kwargs.get("tomorrow_ds"))
|
||||
121 | c = get_current_context()
|
||||
122 | c.get("execution_date")
|
||||
| ^^^^^^^^^^^^^^^^ AIR302
|
||||
123 |
|
||||
124 | class CustomOperatorNew(BaseOperator):
|
||||
134 | class CustomOperator(BaseOperator):
|
||||
135 | def execute(self, next_ds, context):
|
||||
| ^^^^^^^ AIR302
|
||||
136 | execution_date = context["execution_date"]
|
||||
137 | next_ds = context["next_ds"]
|
||||
|
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue