mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-04 10:48:32 +00:00
[airflow
] Extract AIR312
from AIR302
rules (AIR302
, AIR312
) (#17152)
<!-- Thank you for contributing to Ruff! To help us out with reviewing, please consider the following: - Does this pull request include a summary of the change? (See below.) - Does this pull request include a descriptive title? - Does this pull request include references to any relevant issues? --> ## Summary <!-- What's the purpose of the change? What does it do, and why? --> As discussed in https://github.com/astral-sh/ruff/issues/14626#issuecomment-2766146129, we're to separate suggested changes from required changes. The following symbols has been moved to AIR312 from AIR302. They still work in Airflow 3.0, but they're suggested to be changed as they're expected to be removed in future version ```python from airflow.hooks.filesystem import FSHook from airflow.hooks.package_index import PackageIndexHook from airflow.hooks.subprocess import (SubprocessHook, SubprocessResult, working_directory) from airflow.operators.bash import BashOperator from airflow.operators.datetime import BranchDateTimeOperator, target_times_as_dates from airflow.operators.trigger_dagrun import TriggerDagRunLink, TriggerDagRunOperator from airflow.operators.empty import EmptyOperator from airflow.operators.latest_only import LatestOnlyOperator from airflow.operators.python import (BranchPythonOperator, PythonOperator, PythonVirtualenvOperator, ShortCircuitOperator) from airflow.operators.weekday import BranchDayOfWeekOperator from airflow.sensors.date_time import DateTimeSensor, DateTimeSensorAsync from airflow.sensors.external_task import ExternalTaskMarker, ExternalTaskSensor, ExternalTaskSensorLink from airflow.sensors.filesystem import FileSensor from airflow.sensors.time_sensor import TimeSensor, TimeSensorAsync from airflow.sensors.time_delta import TimeDeltaSensor, TimeDeltaSensorAsync, WaitSensor from airflow.sensors.weekday import DayOfWeekSensor from airflow.triggers.external_task import DagStateTrigger, WorkflowTrigger from airflow.triggers.file import FileTrigger from airflow.triggers.temporal import DateTimeTrigger, TimeDeltaTrigger ``` ## Test Plan <!-- How was it tested? --> The test fixture has been updated acccordingly --------- Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
This commit is contained in:
parent
6ec4c6a97e
commit
7207c86971
11 changed files with 889 additions and 703 deletions
55
crates/ruff_linter/resources/test/fixtures/airflow/AIR312.py
vendored
Normal file
55
crates/ruff_linter/resources/test/fixtures/airflow/AIR312.py
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from airflow.hooks.filesystem import FSHook
|
||||
from airflow.hooks.package_index import PackageIndexHook
|
||||
from airflow.hooks.subprocess import SubprocessHook, SubprocessResult, working_directory
|
||||
from airflow.operators.bash import BashOperator
|
||||
from airflow.operators.datetime import BranchDateTimeOperator, target_times_as_dates
|
||||
from airflow.operators.empty import EmptyOperator
|
||||
from airflow.operators.latest_only import LatestOnlyOperator
|
||||
from airflow.operators.python import (
|
||||
BranchPythonOperator,
|
||||
PythonOperator,
|
||||
PythonVirtualenvOperator,
|
||||
ShortCircuitOperator,
|
||||
)
|
||||
from airflow.operators.trigger_dagrun import TriggerDagRunLink, TriggerDagRunOperator
|
||||
from airflow.operators.weekday import BranchDayOfWeekOperator
|
||||
from airflow.sensors.date_time import DateTimeSensor, DateTimeSensorAsync
|
||||
from airflow.sensors.external_task import (
|
||||
ExternalTaskMarker,
|
||||
ExternalTaskSensor,
|
||||
ExternalTaskSensorLink,
|
||||
)
|
||||
from airflow.sensors.filesystem import FileSensor
|
||||
from airflow.sensors.time_delta import TimeDeltaSensor, TimeDeltaSensorAsync, WaitSensor
|
||||
from airflow.sensors.time_sensor import TimeSensor, TimeSensorAsync
|
||||
from airflow.sensors.weekday import DayOfWeekSensor
|
||||
from airflow.triggers.external_task import DagStateTrigger, WorkflowTrigger
|
||||
from airflow.triggers.file import FileTrigger
|
||||
from airflow.triggers.temporal import DateTimeTrigger, TimeDeltaTrigger
|
||||
|
||||
FSHook()
|
||||
PackageIndexHook()
|
||||
SubprocessHook(), SubprocessResult(), working_directory()
|
||||
BashOperator()
|
||||
BranchDateTimeOperator(), target_times_as_dates()
|
||||
TriggerDagRunLink(), TriggerDagRunOperator()
|
||||
EmptyOperator()
|
||||
LatestOnlyOperator()
|
||||
(
|
||||
BranchPythonOperator(),
|
||||
PythonOperator(),
|
||||
PythonVirtualenvOperator(),
|
||||
ShortCircuitOperator(),
|
||||
)
|
||||
BranchDayOfWeekOperator()
|
||||
DateTimeSensor(), DateTimeSensorAsync()
|
||||
ExternalTaskMarker(), ExternalTaskSensor(), ExternalTaskSensorLink()
|
||||
FileSensor()
|
||||
TimeSensor(), TimeSensorAsync()
|
||||
TimeDeltaSensor(), TimeDeltaSensorAsync(), WaitSensor()
|
||||
DayOfWeekSensor()
|
||||
DagStateTrigger(), WorkflowTrigger()
|
||||
FileTrigger()
|
||||
DateTimeTrigger(), TimeDeltaTrigger()
|
|
@ -232,6 +232,9 @@ pub(crate) fn expression(expr: &Expr, checker: &Checker) {
|
|||
if checker.enabled(Rule::Airflow3MovedToProvider) {
|
||||
airflow::rules::moved_to_provider_in_3(checker, expr);
|
||||
}
|
||||
if checker.enabled(Rule::Airflow3SuggestedToMoveToProvider) {
|
||||
airflow::rules::suggested_to_move_to_provider_in_3(checker, expr);
|
||||
}
|
||||
if checker.any_enabled(&[
|
||||
Rule::SuspiciousPickleUsage,
|
||||
Rule::SuspiciousMarshalUsage,
|
||||
|
@ -448,6 +451,9 @@ pub(crate) fn expression(expr: &Expr, checker: &Checker) {
|
|||
if checker.enabled(Rule::Airflow3Removal) {
|
||||
airflow::rules::airflow_3_removal_expr(checker, expr);
|
||||
}
|
||||
if checker.enabled(Rule::Airflow3SuggestedToMoveToProvider) {
|
||||
airflow::rules::suggested_to_move_to_provider_in_3(checker, expr);
|
||||
}
|
||||
}
|
||||
Expr::Call(
|
||||
call @ ast::ExprCall {
|
||||
|
|
|
@ -1072,6 +1072,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
|
|||
(Airflow, "002") => (RuleGroup::Preview, rules::airflow::rules::AirflowDagNoScheduleArgument),
|
||||
(Airflow, "301") => (RuleGroup::Preview, rules::airflow::rules::Airflow3Removal),
|
||||
(Airflow, "302") => (RuleGroup::Preview, rules::airflow::rules::Airflow3MovedToProvider),
|
||||
(Airflow, "312") => (RuleGroup::Preview, rules::airflow::rules::Airflow3SuggestedToMoveToProvider),
|
||||
|
||||
// perflint
|
||||
(Perflint, "101") => (RuleGroup::Stable, rules::perflint::rules::UnnecessaryListCast),
|
||||
|
|
|
@ -15,6 +15,21 @@ pub(crate) enum Replacement {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub(crate) enum ProviderReplacement {
|
||||
ProviderName {
|
||||
name: &'static str,
|
||||
provider: &'static str,
|
||||
version: &'static str,
|
||||
},
|
||||
SourceModuleMovedToProvider {
|
||||
name: String,
|
||||
module: &'static str,
|
||||
provider: &'static str,
|
||||
version: &'static str,
|
||||
},
|
||||
}
|
||||
|
||||
pub(crate) fn is_guarded_by_try_except(
|
||||
expr: &Expr,
|
||||
replacement: &Replacement,
|
||||
|
|
|
@ -22,6 +22,7 @@ mod tests {
|
|||
#[test_case(Rule::Airflow3Removal, Path::new("AIR301_airflow_plugin.py"))]
|
||||
#[test_case(Rule::Airflow3Removal, Path::new("AIR301_context.py"))]
|
||||
#[test_case(Rule::Airflow3MovedToProvider, Path::new("AIR302.py"))]
|
||||
#[test_case(Rule::Airflow3SuggestedToMoveToProvider, Path::new("AIR312.py"))]
|
||||
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy());
|
||||
let diagnostics = test_path(
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
pub(crate) use dag_schedule_argument::*;
|
||||
pub(crate) use moved_to_provider_in_3::*;
|
||||
pub(crate) use removal_in_3::*;
|
||||
pub(crate) use suggested_to_move_to_provider_in_3::*;
|
||||
pub(crate) use task_variable_name::*;
|
||||
|
||||
mod dag_schedule_argument;
|
||||
mod moved_to_provider_in_3;
|
||||
mod removal_in_3;
|
||||
mod suggested_to_move_to_provider_in_3;
|
||||
mod task_variable_name;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,249 @@
|
|||
use crate::rules::airflow::helpers::ProviderReplacement;
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, ViolationMetadata};
|
||||
use ruff_python_ast::{Expr, ExprAttribute};
|
||||
use ruff_python_semantic::Modules;
|
||||
use ruff_text_size::Ranged;
|
||||
use ruff_text_size::TextRange;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for uses of Airflow functions and values that have been moved to its providers
|
||||
/// but still have a compatibility layer (e.g., `apache-airflow-providers-standard`).
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Airflow 3.0 moved various deprecated functions, members, and other
|
||||
/// values to its providers. Even though these symbols still work fine on Airflow 3.0,
|
||||
/// they are expected to be removed in a future version. The user is suggested to install
|
||||
/// the corresponding provider and replace the original usage with the one in the provider.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// from airflow.operators.python import PythonOperator
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// from airflow.providers.standard.operators.python import PythonOperator
|
||||
/// ```
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct Airflow3SuggestedToMoveToProvider {
|
||||
deprecated: String,
|
||||
replacement: ProviderReplacement,
|
||||
}
|
||||
|
||||
impl Violation for Airflow3SuggestedToMoveToProvider {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let Airflow3SuggestedToMoveToProvider {
|
||||
deprecated,
|
||||
replacement,
|
||||
} = self;
|
||||
match replacement {
|
||||
ProviderReplacement::ProviderName {
|
||||
name: _,
|
||||
provider,
|
||||
version: _,
|
||||
}
|
||||
| ProviderReplacement::SourceModuleMovedToProvider {
|
||||
name: _,
|
||||
module: _,
|
||||
provider,
|
||||
version: _,
|
||||
} => {
|
||||
format!("`{deprecated}` is deprecated and moved into `{provider}` provider in Airflow 3.0; \
|
||||
It still works in Airflow 3.0 but is expected to be removed in a future version."
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fix_title(&self) -> Option<String> {
|
||||
let Airflow3SuggestedToMoveToProvider { replacement, .. } = self;
|
||||
match replacement {
|
||||
ProviderReplacement::ProviderName {
|
||||
name,
|
||||
provider,
|
||||
version,
|
||||
} => {
|
||||
Some(format!(
|
||||
"Install `apache-airflow-provider-{provider}>={version}` and use `{name}` instead."
|
||||
))
|
||||
},
|
||||
ProviderReplacement::SourceModuleMovedToProvider {
|
||||
name,
|
||||
module,
|
||||
provider,
|
||||
version,
|
||||
} => {
|
||||
Some(format!("Install `apache-airflow-provider-{provider}>={version}` and use `{module}.{name}` instead."))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AIR312
|
||||
pub(crate) fn suggested_to_move_to_provider_in_3(checker: &Checker, expr: &Expr) {
|
||||
if !checker.semantic().seen_module(Modules::AIRFLOW) {
|
||||
return;
|
||||
}
|
||||
|
||||
match expr {
|
||||
Expr::Attribute(ExprAttribute { attr, .. }) => {
|
||||
check_names_moved_to_provider(checker, expr, attr.range());
|
||||
}
|
||||
Expr::Name(_) => check_names_moved_to_provider(checker, expr, expr.range()),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_names_moved_to_provider(checker: &Checker, expr: &Expr, ranged: TextRange) {
|
||||
let Some(qualified_name) = checker.semantic().resolve_qualified_name(expr) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let replacement = match qualified_name.segments() {
|
||||
// apache-airflow-providers-standard
|
||||
["airflow", "hooks", "filesystem", "FSHook"] => ProviderReplacement::ProviderName {
|
||||
name: "airflow.providers.standard.hooks.filesystem.FSHook",
|
||||
provider: "standard",
|
||||
version: "0.0.1",
|
||||
},
|
||||
["airflow", "hooks", "package_index", "PackageIndexHook"] => {
|
||||
ProviderReplacement::ProviderName {
|
||||
name: "airflow.providers.standard.hooks.package_index.PackageIndexHook",
|
||||
provider: "standard",
|
||||
version: "0.0.1",
|
||||
}
|
||||
}
|
||||
["airflow", "hooks", "subprocess", rest @ ("SubprocessHook" | "SubprocessResult" | "working_directory")] => {
|
||||
ProviderReplacement::SourceModuleMovedToProvider {
|
||||
name: (*rest).to_string(),
|
||||
module: "airflow.providers.standard.hooks.subprocess",
|
||||
provider: "standard",
|
||||
version: "0.0.3",
|
||||
}
|
||||
}
|
||||
["airflow", "operators", "bash", "BashOperator"] => ProviderReplacement::ProviderName {
|
||||
name: "airflow.providers.standard.operators.bash.BashOperator",
|
||||
provider: "standard",
|
||||
version: "0.0.1",
|
||||
},
|
||||
["airflow", "operators", "datetime", rest @ ("BranchDateTimeOperator" | "target_times_as_dates")] => {
|
||||
ProviderReplacement::SourceModuleMovedToProvider {
|
||||
name: (*rest).to_string(),
|
||||
module: "airflow.providers.standard.time.operators.datetime",
|
||||
provider: "standard",
|
||||
version: "0.0.1",
|
||||
}
|
||||
}
|
||||
["airflow", "operators", "trigger_dagrun", rest @ ("TriggerDagRunLink" | "TriggerDagRunOperator")] => {
|
||||
ProviderReplacement::SourceModuleMovedToProvider {
|
||||
name: (*rest).to_string(),
|
||||
module: "airflow.providers.standard.operators.trigger_dagrun",
|
||||
provider: "standard",
|
||||
version: "0.0.2",
|
||||
}
|
||||
}
|
||||
["airflow", "operators", "empty", "EmptyOperator"] => ProviderReplacement::ProviderName {
|
||||
name: "airflow.providers.standard.operators.empty.EmptyOperator",
|
||||
provider: "standard",
|
||||
version: "0.0.2",
|
||||
},
|
||||
["airflow", "operators", "latest_only", "LatestOnlyOperator"] => {
|
||||
ProviderReplacement::ProviderName {
|
||||
name: "airflow.providers.standard.operators.latest_only.LatestOnlyOperator",
|
||||
provider: "standard",
|
||||
version: "0.0.3",
|
||||
}
|
||||
}
|
||||
["airflow", "operators", "python", rest @ ("BranchPythonOperator"
|
||||
| "PythonOperator"
|
||||
| "PythonVirtualenvOperator"
|
||||
| "ShortCircuitOperator")] => ProviderReplacement::SourceModuleMovedToProvider {
|
||||
name: (*rest).to_string(),
|
||||
module: "airflow.providers.standard.operators.python",
|
||||
provider: "standard",
|
||||
version: "0.0.1",
|
||||
},
|
||||
["airflow", "operators", "weekday", "BranchDayOfWeekOperator"] => {
|
||||
ProviderReplacement::ProviderName {
|
||||
name: "airflow.providers.standard.time.operators.weekday.BranchDayOfWeekOperator",
|
||||
provider: "standard",
|
||||
version: "0.0.1",
|
||||
}
|
||||
}
|
||||
["airflow", "sensors", "date_time", rest @ ("DateTimeSensor" | "DateTimeSensorAsync")] => {
|
||||
ProviderReplacement::SourceModuleMovedToProvider {
|
||||
name: (*rest).to_string(),
|
||||
module: "airflow.providers.standard.time.sensors.date_time",
|
||||
provider: "standard",
|
||||
version: "0.0.1",
|
||||
}
|
||||
}
|
||||
["airflow", "sensors", "external_task", rest @ ("ExternalTaskMarker" | "ExternalTaskSensor" | "ExternalTaskSensorLink")] => {
|
||||
ProviderReplacement::SourceModuleMovedToProvider {
|
||||
name: (*rest).to_string(),
|
||||
module: "airflow.providers.standard.sensors.external_task",
|
||||
provider: "standard",
|
||||
version: "0.0.3",
|
||||
}
|
||||
}
|
||||
["airflow", "sensors", "filesystem", "FileSensor"] => ProviderReplacement::ProviderName {
|
||||
name: "airflow.providers.standard.sensors.filesystem.FileSensor",
|
||||
provider: "standard",
|
||||
version: "0.0.2",
|
||||
},
|
||||
["airflow", "sensors", "time_sensor", rest @ ("TimeSensor" | "TimeSensorAsync")] => {
|
||||
ProviderReplacement::SourceModuleMovedToProvider {
|
||||
name: (*rest).to_string(),
|
||||
module: "airflow.providers.standard.time.sensors.time",
|
||||
provider: "standard",
|
||||
version: "0.0.1",
|
||||
}
|
||||
}
|
||||
["airflow", "sensors", "time_delta", rest @ ("TimeDeltaSensor" | "TimeDeltaSensorAsync" | "WaitSensor")] => {
|
||||
ProviderReplacement::SourceModuleMovedToProvider {
|
||||
name: (*rest).to_string(),
|
||||
module: "airflow.providers.standard.time.sensors.time_delta",
|
||||
provider: "standard",
|
||||
version: "0.0.1",
|
||||
}
|
||||
}
|
||||
["airflow", "sensors", "weekday", "DayOfWeekSensor"] => ProviderReplacement::ProviderName {
|
||||
name: "airflow.providers.standard.time.sensors.weekday.DayOfWeekSensor",
|
||||
provider: "standard",
|
||||
version: "0.0.1",
|
||||
},
|
||||
["airflow", "triggers", "external_task", rest @ ("DagStateTrigger" | "WorkflowTrigger")] => {
|
||||
ProviderReplacement::SourceModuleMovedToProvider {
|
||||
name: (*rest).to_string(),
|
||||
module: "airflow.providers.standard.triggers.external_task",
|
||||
provider: "standard",
|
||||
version: "0.0.3",
|
||||
}
|
||||
}
|
||||
["airflow", "triggers", "file", "FileTrigger"] => ProviderReplacement::ProviderName {
|
||||
name: "airflow.providers.standard.triggers.file.FileTrigger",
|
||||
provider: "standard",
|
||||
version: "0.0.3",
|
||||
},
|
||||
["airflow", "triggers", "temporal", rest @ ("DateTimeTrigger" | "TimeDeltaTrigger")] => {
|
||||
ProviderReplacement::SourceModuleMovedToProvider {
|
||||
name: (*rest).to_string(),
|
||||
module: "airflow.providers.standard.triggers.temporal",
|
||||
provider: "standard",
|
||||
version: "0.0.3",
|
||||
}
|
||||
}
|
||||
_ => return,
|
||||
};
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
Airflow3SuggestedToMoveToProvider {
|
||||
deprecated: qualified_name.to_string(),
|
||||
replacement,
|
||||
},
|
||||
ranged.range(),
|
||||
));
|
||||
}
|
|
@ -183,17 +183,6 @@ AIR302.py:246:1: AIR302 `airflow.operators.sql.BaseSQLOperator` is moved into `c
|
|||
|
|
||||
= help: Install `apache-airflow-provider-common-sql>=1.1.0` and use `airflow.providers.common.sql.operators.sql.BaseSQLOperator` instead.
|
||||
|
||||
AIR302.py:247:1: AIR302 `airflow.operators.bash.BashOperator` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
245 | parse_boolean()
|
||||
246 | BaseSQLOperator()
|
||||
247 | BashOperator()
|
||||
| ^^^^^^^^^^^^ AIR302
|
||||
248 | LegacyBashOperator()
|
||||
249 | BranchSQLOperator()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.operators.bash.BashOperator` instead.
|
||||
|
||||
AIR302.py:248:1: AIR302 `airflow.operators.bash_operator.BashOperator` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
246 | BaseSQLOperator()
|
||||
|
@ -1529,82 +1518,6 @@ AIR302.py:422:1: AIR302 `airflow.operators.email_operator.EmailOperator` is move
|
|||
|
|
||||
= help: Install `apache-airflow-provider-smtp>=1.0.0` and use `airflow.providers.smtp.operators.smtp.EmailOperator` instead.
|
||||
|
||||
AIR302.py:425:1: AIR302 `airflow.operators.datetime.BranchDateTimeOperator` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
424 | # apache-airflow-providers-standard
|
||||
425 | BranchDateTimeOperator()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
426 | BranchDayOfWeekOperator()
|
||||
427 | BranchPythonOperator()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.operators.datetime.BranchDateTimeOperator` instead.
|
||||
|
||||
AIR302.py:426:1: AIR302 `airflow.operators.weekday.BranchDayOfWeekOperator` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
424 | # apache-airflow-providers-standard
|
||||
425 | BranchDateTimeOperator()
|
||||
426 | BranchDayOfWeekOperator()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
427 | BranchPythonOperator()
|
||||
428 | DateTimeSensor()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.operators.weekday.BranchDayOfWeekOperator` instead.
|
||||
|
||||
AIR302.py:427:1: AIR302 `airflow.operators.python.BranchPythonOperator` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
425 | BranchDateTimeOperator()
|
||||
426 | BranchDayOfWeekOperator()
|
||||
427 | BranchPythonOperator()
|
||||
| ^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
428 | DateTimeSensor()
|
||||
429 | DateTimeSensorAsync()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.operators.python.BranchPythonOperator` instead.
|
||||
|
||||
AIR302.py:429:1: AIR302 `airflow.sensors.date_time.DateTimeSensorAsync` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
427 | BranchPythonOperator()
|
||||
428 | DateTimeSensor()
|
||||
429 | DateTimeSensorAsync()
|
||||
| ^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
430 | TimeSensor()
|
||||
431 | TimeDeltaSensor()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.sensors.date_time.DateTimeSensorAsync` instead.
|
||||
|
||||
AIR302.py:430:1: AIR302 `airflow.sensors.time_sensor.TimeSensor` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
428 | DateTimeSensor()
|
||||
429 | DateTimeSensorAsync()
|
||||
430 | TimeSensor()
|
||||
| ^^^^^^^^^^ AIR302
|
||||
431 | TimeDeltaSensor()
|
||||
432 | DayOfWeekSensor()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.sensors.time.TimeSensor` instead.
|
||||
|
||||
AIR302.py:431:1: AIR302 `airflow.sensors.time_delta.TimeDeltaSensor` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
429 | DateTimeSensorAsync()
|
||||
430 | TimeSensor()
|
||||
431 | TimeDeltaSensor()
|
||||
| ^^^^^^^^^^^^^^^ AIR302
|
||||
432 | DayOfWeekSensor()
|
||||
433 | DummyOperator()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.sensors.time_delta.TimeDeltaSensor` instead.
|
||||
|
||||
AIR302.py:432:1: AIR302 `airflow.sensors.weekday.DayOfWeekSensor` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
430 | TimeSensor()
|
||||
431 | TimeDeltaSensor()
|
||||
432 | DayOfWeekSensor()
|
||||
| ^^^^^^^^^^^^^^^ AIR302
|
||||
433 | DummyOperator()
|
||||
434 | EmptyOperator()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.sensors.weekday.DayOfWeekSensor` instead.
|
||||
|
||||
AIR302.py:433:1: AIR302 `airflow.operators.dummy.DummyOperator` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
431 | TimeDeltaSensor()
|
||||
|
@ -1626,319 +1539,3 @@ AIR302.py:434:1: AIR302 `airflow.operators.dummy.EmptyOperator` is moved into `s
|
|||
436 | ExternalTaskSensor()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.2` and use `airflow.providers.standard.operators.empty.EmptyOperator` instead.
|
||||
|
||||
AIR302.py:435:1: AIR302 `airflow.sensors.external_task.ExternalTaskMarker` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
433 | DummyOperator()
|
||||
434 | EmptyOperator()
|
||||
435 | ExternalTaskMarker()
|
||||
| ^^^^^^^^^^^^^^^^^^ AIR302
|
||||
436 | ExternalTaskSensor()
|
||||
437 | ExternalTaskSensorLink()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.sensors.external_task.ExternalTaskMarker` instead.
|
||||
|
||||
AIR302.py:436:1: AIR302 `airflow.sensors.external_task.ExternalTaskSensor` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
434 | EmptyOperator()
|
||||
435 | ExternalTaskMarker()
|
||||
436 | ExternalTaskSensor()
|
||||
| ^^^^^^^^^^^^^^^^^^ AIR302
|
||||
437 | ExternalTaskSensorLink()
|
||||
438 | FileSensor()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.sensors.external_task.ExternalTaskSensor` instead.
|
||||
|
||||
AIR302.py:437:1: AIR302 `airflow.sensors.external_task.ExternalTaskSensorLink` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
435 | ExternalTaskMarker()
|
||||
436 | ExternalTaskSensor()
|
||||
437 | ExternalTaskSensorLink()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
438 | FileSensor()
|
||||
439 | FileTrigger()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.sensors.external_task.ExternalTaskSensorLink` instead.
|
||||
|
||||
AIR302.py:438:1: AIR302 `airflow.sensors.filesystem.FileSensor` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
436 | ExternalTaskSensor()
|
||||
437 | ExternalTaskSensorLink()
|
||||
438 | FileSensor()
|
||||
| ^^^^^^^^^^ AIR302
|
||||
439 | FileTrigger()
|
||||
440 | FSHook()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.2` and use `airflow.providers.standard.sensors.filesystem.FileSensor` instead.
|
||||
|
||||
AIR302.py:439:1: AIR302 `airflow.triggers.file.FileTrigger` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
437 | ExternalTaskSensorLink()
|
||||
438 | FileSensor()
|
||||
439 | FileTrigger()
|
||||
| ^^^^^^^^^^^ AIR302
|
||||
440 | FSHook()
|
||||
441 | PackageIndexHook()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.triggers.file.FileTrigger` instead.
|
||||
|
||||
AIR302.py:440:1: AIR302 `airflow.hooks.filesystem.FSHook` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
438 | FileSensor()
|
||||
439 | FileTrigger()
|
||||
440 | FSHook()
|
||||
| ^^^^^^ AIR302
|
||||
441 | PackageIndexHook()
|
||||
442 | SubprocessHook()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.hooks.filesystem.FSHook` instead.
|
||||
|
||||
AIR302.py:441:1: AIR302 `airflow.hooks.package_index.PackageIndexHook` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
439 | FileTrigger()
|
||||
440 | FSHook()
|
||||
441 | PackageIndexHook()
|
||||
| ^^^^^^^^^^^^^^^^ AIR302
|
||||
442 | SubprocessHook()
|
||||
443 | ShortCircuitOperator()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.hooks.package_index.PackageIndexHook` instead.
|
||||
|
||||
AIR302.py:442:1: AIR302 `airflow.hooks.subprocess.SubprocessHook` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
440 | FSHook()
|
||||
441 | PackageIndexHook()
|
||||
442 | SubprocessHook()
|
||||
| ^^^^^^^^^^^^^^ AIR302
|
||||
443 | ShortCircuitOperator()
|
||||
444 | TimeDeltaSensor()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.hooks.subprocess.SubprocessHook` instead.
|
||||
|
||||
AIR302.py:443:1: AIR302 `airflow.operators.python.ShortCircuitOperator` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
441 | PackageIndexHook()
|
||||
442 | SubprocessHook()
|
||||
443 | ShortCircuitOperator()
|
||||
| ^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
444 | TimeDeltaSensor()
|
||||
445 | TimeSensor()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.operators.python.ShortCircuitOperator` instead.
|
||||
|
||||
AIR302.py:444:1: AIR302 `airflow.sensors.time_delta.TimeDeltaSensor` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
442 | SubprocessHook()
|
||||
443 | ShortCircuitOperator()
|
||||
444 | TimeDeltaSensor()
|
||||
| ^^^^^^^^^^^^^^^ AIR302
|
||||
445 | TimeSensor()
|
||||
446 | TriggerDagRunOperator()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.sensors.time_delta.TimeDeltaSensor` instead.
|
||||
|
||||
AIR302.py:445:1: AIR302 `airflow.sensors.time_sensor.TimeSensor` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
443 | ShortCircuitOperator()
|
||||
444 | TimeDeltaSensor()
|
||||
445 | TimeSensor()
|
||||
| ^^^^^^^^^^ AIR302
|
||||
446 | TriggerDagRunOperator()
|
||||
447 | WorkflowTrigger()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.sensors.time.TimeSensor` instead.
|
||||
|
||||
AIR302.py:446:1: AIR302 `airflow.operators.trigger_dagrun.TriggerDagRunOperator` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
444 | TimeDeltaSensor()
|
||||
445 | TimeSensor()
|
||||
446 | TriggerDagRunOperator()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
447 | WorkflowTrigger()
|
||||
448 | PythonOperator()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.2` and use `airflow.providers.standard.operators.trigger_dagrun.TriggerDagRunOperator` instead.
|
||||
|
||||
AIR302.py:447:1: AIR302 `airflow.triggers.external_task.WorkflowTrigger` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
445 | TimeSensor()
|
||||
446 | TriggerDagRunOperator()
|
||||
447 | WorkflowTrigger()
|
||||
| ^^^^^^^^^^^^^^^ AIR302
|
||||
448 | PythonOperator()
|
||||
449 | PythonVirtualenvOperator()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.triggers.external_task.WorkflowTrigger` instead.
|
||||
|
||||
AIR302.py:448:1: AIR302 `airflow.operators.python.PythonOperator` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
446 | TriggerDagRunOperator()
|
||||
447 | WorkflowTrigger()
|
||||
448 | PythonOperator()
|
||||
| ^^^^^^^^^^^^^^ AIR302
|
||||
449 | PythonVirtualenvOperator()
|
||||
450 | DagStateTrigger()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.operators.python.PythonOperator` instead.
|
||||
|
||||
AIR302.py:449:1: AIR302 `airflow.operators.python.PythonVirtualenvOperator` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
447 | WorkflowTrigger()
|
||||
448 | PythonOperator()
|
||||
449 | PythonVirtualenvOperator()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
450 | DagStateTrigger()
|
||||
451 | FileTrigger()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.operators.python.PythonVirtualenvOperator` instead.
|
||||
|
||||
AIR302.py:450:1: AIR302 `airflow.triggers.external_task.DagStateTrigger` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
448 | PythonOperator()
|
||||
449 | PythonVirtualenvOperator()
|
||||
450 | DagStateTrigger()
|
||||
| ^^^^^^^^^^^^^^^ AIR302
|
||||
451 | FileTrigger()
|
||||
452 | DateTimeTrigger()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.triggers.external_task.DagStateTrigger` instead.
|
||||
|
||||
AIR302.py:451:1: AIR302 `airflow.triggers.file.FileTrigger` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
449 | PythonVirtualenvOperator()
|
||||
450 | DagStateTrigger()
|
||||
451 | FileTrigger()
|
||||
| ^^^^^^^^^^^ AIR302
|
||||
452 | DateTimeTrigger()
|
||||
453 | TimeDeltaTrigger()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.triggers.file.FileTrigger` instead.
|
||||
|
||||
AIR302.py:452:1: AIR302 `airflow.triggers.temporal.DateTimeTrigger` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
450 | DagStateTrigger()
|
||||
451 | FileTrigger()
|
||||
452 | DateTimeTrigger()
|
||||
| ^^^^^^^^^^^^^^^ AIR302
|
||||
453 | TimeDeltaTrigger()
|
||||
454 | SubprocessResult()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.triggers.temporal.DateTimeTrigger` instead.
|
||||
|
||||
AIR302.py:453:1: AIR302 `airflow.triggers.temporal.TimeDeltaTrigger` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
451 | FileTrigger()
|
||||
452 | DateTimeTrigger()
|
||||
453 | TimeDeltaTrigger()
|
||||
| ^^^^^^^^^^^^^^^^ AIR302
|
||||
454 | SubprocessResult()
|
||||
455 | working_directory()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.triggers.temporal.TimeDeltaTrigger` instead.
|
||||
|
||||
AIR302.py:454:1: AIR302 `airflow.hooks.subprocess.SubprocessResult` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
452 | DateTimeTrigger()
|
||||
453 | TimeDeltaTrigger()
|
||||
454 | SubprocessResult()
|
||||
| ^^^^^^^^^^^^^^^^ AIR302
|
||||
455 | working_directory()
|
||||
456 | SubprocessHook()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.hooks.subprocess.SubprocessResult` instead.
|
||||
|
||||
AIR302.py:455:1: AIR302 `airflow.hooks.subprocess.working_directory` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
453 | TimeDeltaTrigger()
|
||||
454 | SubprocessResult()
|
||||
455 | working_directory()
|
||||
| ^^^^^^^^^^^^^^^^^ AIR302
|
||||
456 | SubprocessHook()
|
||||
457 | TimeDeltaSensor()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.hooks.subprocess.working_directory` instead.
|
||||
|
||||
AIR302.py:456:1: AIR302 `airflow.hooks.subprocess.SubprocessHook` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
454 | SubprocessResult()
|
||||
455 | working_directory()
|
||||
456 | SubprocessHook()
|
||||
| ^^^^^^^^^^^^^^ AIR302
|
||||
457 | TimeDeltaSensor()
|
||||
458 | TimeDeltaSensorAsync()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.hooks.subprocess.SubprocessHook` instead.
|
||||
|
||||
AIR302.py:457:1: AIR302 `airflow.sensors.time_delta.TimeDeltaSensor` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
455 | working_directory()
|
||||
456 | SubprocessHook()
|
||||
457 | TimeDeltaSensor()
|
||||
| ^^^^^^^^^^^^^^^ AIR302
|
||||
458 | TimeDeltaSensorAsync()
|
||||
459 | WaitSensor()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.sensors.time_delta.TimeDeltaSensor` instead.
|
||||
|
||||
AIR302.py:458:1: AIR302 `airflow.sensors.time_delta.TimeDeltaSensorAsync` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
456 | SubprocessHook()
|
||||
457 | TimeDeltaSensor()
|
||||
458 | TimeDeltaSensorAsync()
|
||||
| ^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
459 | WaitSensor()
|
||||
460 | TimeSensor()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.sensors.time_delta.TimeDeltaSensorAsync` instead.
|
||||
|
||||
AIR302.py:459:1: AIR302 `airflow.sensors.time_delta.WaitSensor` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
457 | TimeDeltaSensor()
|
||||
458 | TimeDeltaSensorAsync()
|
||||
459 | WaitSensor()
|
||||
| ^^^^^^^^^^ AIR302
|
||||
460 | TimeSensor()
|
||||
461 | TimeSensorAsync()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.sensors.time_delta.WaitSensor` instead.
|
||||
|
||||
AIR302.py:460:1: AIR302 `airflow.sensors.time_sensor.TimeSensor` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
458 | TimeDeltaSensorAsync()
|
||||
459 | WaitSensor()
|
||||
460 | TimeSensor()
|
||||
| ^^^^^^^^^^ AIR302
|
||||
461 | TimeSensorAsync()
|
||||
462 | BranchDateTimeOperator()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.sensors.time.TimeSensor` instead.
|
||||
|
||||
AIR302.py:461:1: AIR302 `airflow.sensors.time_sensor.TimeSensorAsync` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
459 | WaitSensor()
|
||||
460 | TimeSensor()
|
||||
461 | TimeSensorAsync()
|
||||
| ^^^^^^^^^^^^^^^ AIR302
|
||||
462 | BranchDateTimeOperator()
|
||||
463 | target_times_as_dates()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.sensors.time.TimeSensorAsync` instead.
|
||||
|
||||
AIR302.py:462:1: AIR302 `airflow.operators.datetime.BranchDateTimeOperator` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
460 | TimeSensor()
|
||||
461 | TimeSensorAsync()
|
||||
462 | BranchDateTimeOperator()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
463 | target_times_as_dates()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.operators.datetime.BranchDateTimeOperator` instead.
|
||||
|
||||
AIR302.py:463:1: AIR302 `airflow.operators.datetime.target_times_as_dates` is moved into `standard` provider in Airflow 3.0;
|
||||
|
|
||||
461 | TimeSensorAsync()
|
||||
462 | BranchDateTimeOperator()
|
||||
463 | target_times_as_dates()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ AIR302
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.operators.datetime.target_times_as_dates` instead.
|
||||
|
|
|
@ -0,0 +1,370 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/airflow/mod.rs
|
||||
---
|
||||
AIR312.py:32:1: AIR312 `airflow.hooks.filesystem.FSHook` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
30 | from airflow.triggers.temporal import DateTimeTrigger, TimeDeltaTrigger
|
||||
31 |
|
||||
32 | FSHook()
|
||||
| ^^^^^^ AIR312
|
||||
33 | PackageIndexHook()
|
||||
34 | SubprocessHook(), SubprocessResult(), working_directory()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.hooks.filesystem.FSHook` instead.
|
||||
|
||||
AIR312.py:33:1: AIR312 `airflow.hooks.package_index.PackageIndexHook` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
32 | FSHook()
|
||||
33 | PackageIndexHook()
|
||||
| ^^^^^^^^^^^^^^^^ AIR312
|
||||
34 | SubprocessHook(), SubprocessResult(), working_directory()
|
||||
35 | BashOperator()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.hooks.package_index.PackageIndexHook` instead.
|
||||
|
||||
AIR312.py:34:1: AIR312 `airflow.hooks.subprocess.SubprocessHook` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
32 | FSHook()
|
||||
33 | PackageIndexHook()
|
||||
34 | SubprocessHook(), SubprocessResult(), working_directory()
|
||||
| ^^^^^^^^^^^^^^ AIR312
|
||||
35 | BashOperator()
|
||||
36 | BranchDateTimeOperator(), target_times_as_dates()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.hooks.subprocess.SubprocessHook` instead.
|
||||
|
||||
AIR312.py:34:19: AIR312 `airflow.hooks.subprocess.SubprocessResult` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
32 | FSHook()
|
||||
33 | PackageIndexHook()
|
||||
34 | SubprocessHook(), SubprocessResult(), working_directory()
|
||||
| ^^^^^^^^^^^^^^^^ AIR312
|
||||
35 | BashOperator()
|
||||
36 | BranchDateTimeOperator(), target_times_as_dates()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.hooks.subprocess.SubprocessResult` instead.
|
||||
|
||||
AIR312.py:34:39: AIR312 `airflow.hooks.subprocess.working_directory` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
32 | FSHook()
|
||||
33 | PackageIndexHook()
|
||||
34 | SubprocessHook(), SubprocessResult(), working_directory()
|
||||
| ^^^^^^^^^^^^^^^^^ AIR312
|
||||
35 | BashOperator()
|
||||
36 | BranchDateTimeOperator(), target_times_as_dates()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.hooks.subprocess.working_directory` instead.
|
||||
|
||||
AIR312.py:35:1: AIR312 `airflow.operators.bash.BashOperator` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
33 | PackageIndexHook()
|
||||
34 | SubprocessHook(), SubprocessResult(), working_directory()
|
||||
35 | BashOperator()
|
||||
| ^^^^^^^^^^^^ AIR312
|
||||
36 | BranchDateTimeOperator(), target_times_as_dates()
|
||||
37 | TriggerDagRunLink(), TriggerDagRunOperator()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.operators.bash.BashOperator` instead.
|
||||
|
||||
AIR312.py:36:1: AIR312 `airflow.operators.datetime.BranchDateTimeOperator` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
34 | SubprocessHook(), SubprocessResult(), working_directory()
|
||||
35 | BashOperator()
|
||||
36 | BranchDateTimeOperator(), target_times_as_dates()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ AIR312
|
||||
37 | TriggerDagRunLink(), TriggerDagRunOperator()
|
||||
38 | EmptyOperator()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.operators.datetime.BranchDateTimeOperator` instead.
|
||||
|
||||
AIR312.py:36:27: AIR312 `airflow.operators.datetime.target_times_as_dates` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
34 | SubprocessHook(), SubprocessResult(), working_directory()
|
||||
35 | BashOperator()
|
||||
36 | BranchDateTimeOperator(), target_times_as_dates()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ AIR312
|
||||
37 | TriggerDagRunLink(), TriggerDagRunOperator()
|
||||
38 | EmptyOperator()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.operators.datetime.target_times_as_dates` instead.
|
||||
|
||||
AIR312.py:37:1: AIR312 `airflow.operators.trigger_dagrun.TriggerDagRunLink` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
35 | BashOperator()
|
||||
36 | BranchDateTimeOperator(), target_times_as_dates()
|
||||
37 | TriggerDagRunLink(), TriggerDagRunOperator()
|
||||
| ^^^^^^^^^^^^^^^^^ AIR312
|
||||
38 | EmptyOperator()
|
||||
39 | LatestOnlyOperator()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.2` and use `airflow.providers.standard.operators.trigger_dagrun.TriggerDagRunLink` instead.
|
||||
|
||||
AIR312.py:37:22: AIR312 `airflow.operators.trigger_dagrun.TriggerDagRunOperator` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
35 | BashOperator()
|
||||
36 | BranchDateTimeOperator(), target_times_as_dates()
|
||||
37 | TriggerDagRunLink(), TriggerDagRunOperator()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ AIR312
|
||||
38 | EmptyOperator()
|
||||
39 | LatestOnlyOperator()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.2` and use `airflow.providers.standard.operators.trigger_dagrun.TriggerDagRunOperator` instead.
|
||||
|
||||
AIR312.py:38:1: AIR312 `airflow.operators.empty.EmptyOperator` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
36 | BranchDateTimeOperator(), target_times_as_dates()
|
||||
37 | TriggerDagRunLink(), TriggerDagRunOperator()
|
||||
38 | EmptyOperator()
|
||||
| ^^^^^^^^^^^^^ AIR312
|
||||
39 | LatestOnlyOperator()
|
||||
40 | (
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.2` and use `airflow.providers.standard.operators.empty.EmptyOperator` instead.
|
||||
|
||||
AIR312.py:39:1: AIR312 `airflow.operators.latest_only.LatestOnlyOperator` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
37 | TriggerDagRunLink(), TriggerDagRunOperator()
|
||||
38 | EmptyOperator()
|
||||
39 | LatestOnlyOperator()
|
||||
| ^^^^^^^^^^^^^^^^^^ AIR312
|
||||
40 | (
|
||||
41 | BranchPythonOperator(),
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.operators.latest_only.LatestOnlyOperator` instead.
|
||||
|
||||
AIR312.py:41:5: AIR312 `airflow.operators.python.BranchPythonOperator` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
39 | LatestOnlyOperator()
|
||||
40 | (
|
||||
41 | BranchPythonOperator(),
|
||||
| ^^^^^^^^^^^^^^^^^^^^ AIR312
|
||||
42 | PythonOperator(),
|
||||
43 | PythonVirtualenvOperator(),
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.operators.python.BranchPythonOperator` instead.
|
||||
|
||||
AIR312.py:42:5: AIR312 `airflow.operators.python.PythonOperator` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
40 | (
|
||||
41 | BranchPythonOperator(),
|
||||
42 | PythonOperator(),
|
||||
| ^^^^^^^^^^^^^^ AIR312
|
||||
43 | PythonVirtualenvOperator(),
|
||||
44 | ShortCircuitOperator(),
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.operators.python.PythonOperator` instead.
|
||||
|
||||
AIR312.py:43:5: AIR312 `airflow.operators.python.PythonVirtualenvOperator` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
41 | BranchPythonOperator(),
|
||||
42 | PythonOperator(),
|
||||
43 | PythonVirtualenvOperator(),
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ AIR312
|
||||
44 | ShortCircuitOperator(),
|
||||
45 | )
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.operators.python.PythonVirtualenvOperator` instead.
|
||||
|
||||
AIR312.py:44:5: AIR312 `airflow.operators.python.ShortCircuitOperator` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
42 | PythonOperator(),
|
||||
43 | PythonVirtualenvOperator(),
|
||||
44 | ShortCircuitOperator(),
|
||||
| ^^^^^^^^^^^^^^^^^^^^ AIR312
|
||||
45 | )
|
||||
46 | BranchDayOfWeekOperator()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.operators.python.ShortCircuitOperator` instead.
|
||||
|
||||
AIR312.py:46:1: AIR312 `airflow.operators.weekday.BranchDayOfWeekOperator` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
44 | ShortCircuitOperator(),
|
||||
45 | )
|
||||
46 | BranchDayOfWeekOperator()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ AIR312
|
||||
47 | DateTimeSensor(), DateTimeSensorAsync()
|
||||
48 | ExternalTaskMarker(), ExternalTaskSensor(), ExternalTaskSensorLink()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.operators.weekday.BranchDayOfWeekOperator` instead.
|
||||
|
||||
AIR312.py:47:1: AIR312 `airflow.sensors.date_time.DateTimeSensor` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
45 | )
|
||||
46 | BranchDayOfWeekOperator()
|
||||
47 | DateTimeSensor(), DateTimeSensorAsync()
|
||||
| ^^^^^^^^^^^^^^ AIR312
|
||||
48 | ExternalTaskMarker(), ExternalTaskSensor(), ExternalTaskSensorLink()
|
||||
49 | FileSensor()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.sensors.date_time.DateTimeSensor` instead.
|
||||
|
||||
AIR312.py:47:19: AIR312 `airflow.sensors.date_time.DateTimeSensorAsync` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
45 | )
|
||||
46 | BranchDayOfWeekOperator()
|
||||
47 | DateTimeSensor(), DateTimeSensorAsync()
|
||||
| ^^^^^^^^^^^^^^^^^^^ AIR312
|
||||
48 | ExternalTaskMarker(), ExternalTaskSensor(), ExternalTaskSensorLink()
|
||||
49 | FileSensor()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.sensors.date_time.DateTimeSensorAsync` instead.
|
||||
|
||||
AIR312.py:48:1: AIR312 `airflow.sensors.external_task.ExternalTaskMarker` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
46 | BranchDayOfWeekOperator()
|
||||
47 | DateTimeSensor(), DateTimeSensorAsync()
|
||||
48 | ExternalTaskMarker(), ExternalTaskSensor(), ExternalTaskSensorLink()
|
||||
| ^^^^^^^^^^^^^^^^^^ AIR312
|
||||
49 | FileSensor()
|
||||
50 | TimeSensor(), TimeSensorAsync()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.sensors.external_task.ExternalTaskMarker` instead.
|
||||
|
||||
AIR312.py:48:23: AIR312 `airflow.sensors.external_task.ExternalTaskSensor` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
46 | BranchDayOfWeekOperator()
|
||||
47 | DateTimeSensor(), DateTimeSensorAsync()
|
||||
48 | ExternalTaskMarker(), ExternalTaskSensor(), ExternalTaskSensorLink()
|
||||
| ^^^^^^^^^^^^^^^^^^ AIR312
|
||||
49 | FileSensor()
|
||||
50 | TimeSensor(), TimeSensorAsync()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.sensors.external_task.ExternalTaskSensor` instead.
|
||||
|
||||
AIR312.py:48:45: AIR312 `airflow.sensors.external_task.ExternalTaskSensorLink` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
46 | BranchDayOfWeekOperator()
|
||||
47 | DateTimeSensor(), DateTimeSensorAsync()
|
||||
48 | ExternalTaskMarker(), ExternalTaskSensor(), ExternalTaskSensorLink()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ AIR312
|
||||
49 | FileSensor()
|
||||
50 | TimeSensor(), TimeSensorAsync()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.sensors.external_task.ExternalTaskSensorLink` instead.
|
||||
|
||||
AIR312.py:49:1: AIR312 `airflow.sensors.filesystem.FileSensor` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
47 | DateTimeSensor(), DateTimeSensorAsync()
|
||||
48 | ExternalTaskMarker(), ExternalTaskSensor(), ExternalTaskSensorLink()
|
||||
49 | FileSensor()
|
||||
| ^^^^^^^^^^ AIR312
|
||||
50 | TimeSensor(), TimeSensorAsync()
|
||||
51 | TimeDeltaSensor(), TimeDeltaSensorAsync(), WaitSensor()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.2` and use `airflow.providers.standard.sensors.filesystem.FileSensor` instead.
|
||||
|
||||
AIR312.py:50:1: AIR312 `airflow.sensors.time_sensor.TimeSensor` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
48 | ExternalTaskMarker(), ExternalTaskSensor(), ExternalTaskSensorLink()
|
||||
49 | FileSensor()
|
||||
50 | TimeSensor(), TimeSensorAsync()
|
||||
| ^^^^^^^^^^ AIR312
|
||||
51 | TimeDeltaSensor(), TimeDeltaSensorAsync(), WaitSensor()
|
||||
52 | DayOfWeekSensor()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.sensors.time.TimeSensor` instead.
|
||||
|
||||
AIR312.py:50:15: AIR312 `airflow.sensors.time_sensor.TimeSensorAsync` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
48 | ExternalTaskMarker(), ExternalTaskSensor(), ExternalTaskSensorLink()
|
||||
49 | FileSensor()
|
||||
50 | TimeSensor(), TimeSensorAsync()
|
||||
| ^^^^^^^^^^^^^^^ AIR312
|
||||
51 | TimeDeltaSensor(), TimeDeltaSensorAsync(), WaitSensor()
|
||||
52 | DayOfWeekSensor()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.sensors.time.TimeSensorAsync` instead.
|
||||
|
||||
AIR312.py:51:1: AIR312 `airflow.sensors.time_delta.TimeDeltaSensor` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
49 | FileSensor()
|
||||
50 | TimeSensor(), TimeSensorAsync()
|
||||
51 | TimeDeltaSensor(), TimeDeltaSensorAsync(), WaitSensor()
|
||||
| ^^^^^^^^^^^^^^^ AIR312
|
||||
52 | DayOfWeekSensor()
|
||||
53 | DagStateTrigger(), WorkflowTrigger()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.sensors.time_delta.TimeDeltaSensor` instead.
|
||||
|
||||
AIR312.py:51:20: AIR312 `airflow.sensors.time_delta.TimeDeltaSensorAsync` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
49 | FileSensor()
|
||||
50 | TimeSensor(), TimeSensorAsync()
|
||||
51 | TimeDeltaSensor(), TimeDeltaSensorAsync(), WaitSensor()
|
||||
| ^^^^^^^^^^^^^^^^^^^^ AIR312
|
||||
52 | DayOfWeekSensor()
|
||||
53 | DagStateTrigger(), WorkflowTrigger()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.sensors.time_delta.TimeDeltaSensorAsync` instead.
|
||||
|
||||
AIR312.py:51:44: AIR312 `airflow.sensors.time_delta.WaitSensor` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
49 | FileSensor()
|
||||
50 | TimeSensor(), TimeSensorAsync()
|
||||
51 | TimeDeltaSensor(), TimeDeltaSensorAsync(), WaitSensor()
|
||||
| ^^^^^^^^^^ AIR312
|
||||
52 | DayOfWeekSensor()
|
||||
53 | DagStateTrigger(), WorkflowTrigger()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.sensors.time_delta.WaitSensor` instead.
|
||||
|
||||
AIR312.py:52:1: AIR312 `airflow.sensors.weekday.DayOfWeekSensor` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
50 | TimeSensor(), TimeSensorAsync()
|
||||
51 | TimeDeltaSensor(), TimeDeltaSensorAsync(), WaitSensor()
|
||||
52 | DayOfWeekSensor()
|
||||
| ^^^^^^^^^^^^^^^ AIR312
|
||||
53 | DagStateTrigger(), WorkflowTrigger()
|
||||
54 | FileTrigger()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.1` and use `airflow.providers.standard.time.sensors.weekday.DayOfWeekSensor` instead.
|
||||
|
||||
AIR312.py:53:1: AIR312 `airflow.triggers.external_task.DagStateTrigger` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
51 | TimeDeltaSensor(), TimeDeltaSensorAsync(), WaitSensor()
|
||||
52 | DayOfWeekSensor()
|
||||
53 | DagStateTrigger(), WorkflowTrigger()
|
||||
| ^^^^^^^^^^^^^^^ AIR312
|
||||
54 | FileTrigger()
|
||||
55 | DateTimeTrigger(), TimeDeltaTrigger()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.triggers.external_task.DagStateTrigger` instead.
|
||||
|
||||
AIR312.py:53:20: AIR312 `airflow.triggers.external_task.WorkflowTrigger` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
51 | TimeDeltaSensor(), TimeDeltaSensorAsync(), WaitSensor()
|
||||
52 | DayOfWeekSensor()
|
||||
53 | DagStateTrigger(), WorkflowTrigger()
|
||||
| ^^^^^^^^^^^^^^^ AIR312
|
||||
54 | FileTrigger()
|
||||
55 | DateTimeTrigger(), TimeDeltaTrigger()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.triggers.external_task.WorkflowTrigger` instead.
|
||||
|
||||
AIR312.py:54:1: AIR312 `airflow.triggers.file.FileTrigger` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
52 | DayOfWeekSensor()
|
||||
53 | DagStateTrigger(), WorkflowTrigger()
|
||||
54 | FileTrigger()
|
||||
| ^^^^^^^^^^^ AIR312
|
||||
55 | DateTimeTrigger(), TimeDeltaTrigger()
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.triggers.file.FileTrigger` instead.
|
||||
|
||||
AIR312.py:55:1: AIR312 `airflow.triggers.temporal.DateTimeTrigger` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
53 | DagStateTrigger(), WorkflowTrigger()
|
||||
54 | FileTrigger()
|
||||
55 | DateTimeTrigger(), TimeDeltaTrigger()
|
||||
| ^^^^^^^^^^^^^^^ AIR312
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.triggers.temporal.DateTimeTrigger` instead.
|
||||
|
||||
AIR312.py:55:20: AIR312 `airflow.triggers.temporal.TimeDeltaTrigger` is deprecated and moved into `standard` provider in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
|
||||
|
|
||||
53 | DagStateTrigger(), WorkflowTrigger()
|
||||
54 | FileTrigger()
|
||||
55 | DateTimeTrigger(), TimeDeltaTrigger()
|
||||
| ^^^^^^^^^^^^^^^^ AIR312
|
||||
|
|
||||
= help: Install `apache-airflow-provider-standard>=0.0.3` and use `airflow.providers.standard.triggers.temporal.TimeDeltaTrigger` instead.
|
Loading…
Add table
Add a link
Reference in a new issue