diff --git a/airflow/cli/commands/task_command.py b/airflow/cli/commands/task_command.py index 0cbf08e91d9f6..d6bac9fc7fc4e 100644 --- a/airflow/cli/commands/task_command.py +++ b/airflow/cli/commands/task_command.py @@ -31,7 +31,6 @@ from pendulum.parsing.exceptions import ParserError from sqlalchemy import select from sqlalchemy.orm.exc import NoResultFound -from typing_extensions import Literal from airflow import settings from airflow.cli.simple_table import AirflowConsole @@ -50,6 +49,7 @@ from airflow.settings import IS_K8S_EXECUTOR_POD from airflow.ti_deps.dep_context import DepContext from airflow.ti_deps.dependencies_deps import SCHEDULER_QUEUED_DEPS +from airflow.typing_compat import Literal from airflow.utils import cli as cli_utils from airflow.utils.cli import ( get_dag, diff --git a/airflow/models/dag.py b/airflow/models/dag.py index 5979c51c518fa..930e6b2cd6e63 100644 --- a/airflow/models/dag.py +++ b/airflow/models/dag.py @@ -131,13 +131,13 @@ from pendulum.tz.timezone import Timezone from sqlalchemy.orm.query import Query from sqlalchemy.orm.session import Session - from typing_extensions import Literal from airflow.datasets import Dataset from airflow.decorators import TaskDecoratorCollection from airflow.models.dagbag import DagBag from airflow.models.operator import Operator from airflow.models.slamiss import SlaMiss + from airflow.typing_compat import Literal from airflow.utils.task_group import TaskGroup log = logging.getLogger(__name__) diff --git a/airflow/models/dagrun.py b/airflow/models/dagrun.py index c528b6114bff5..43ed97e518835 100644 --- a/airflow/models/dagrun.py +++ b/airflow/models/dagrun.py @@ -72,10 +72,10 @@ from datetime import datetime from sqlalchemy.orm import Query, Session - from typing_extensions import Literal from airflow.models.dag import DAG from airflow.models.operator import Operator + from airflow.typing_compat import Literal from airflow.utils.types import ArgNotSet CreatedTasks = TypeVar("CreatedTasks", Iterator["dict[str, Any]"], Iterator[TI]) diff --git a/airflow/models/mappedoperator.py b/airflow/models/mappedoperator.py index 09785aaaf52db..37882dcd78dfb 100644 --- a/airflow/models/mappedoperator.py +++ b/airflow/models/mappedoperator.py @@ -25,7 +25,6 @@ from typing import TYPE_CHECKING, Any, ClassVar, Collection, Iterable, Iterator, Mapping, Sequence, Union import attr -from typing_extensions import Literal from airflow import settings from airflow.compat.functools import cache @@ -52,6 +51,7 @@ from airflow.models.pool import Pool from airflow.serialization.enums import DagAttributeTypes from airflow.ti_deps.deps.mapped_task_expanded import MappedTaskIsExpanded +from airflow.typing_compat import Literal from airflow.utils.context import context_update_for_unmapped from airflow.utils.helpers import is_container, prevent_duplicates from airflow.utils.types import NOTSET diff --git a/airflow/models/taskinstance.py b/airflow/models/taskinstance.py index b28d59bee088e..ff1b190a5eab8 100644 --- a/airflow/models/taskinstance.py +++ b/airflow/models/taskinstance.py @@ -135,7 +135,6 @@ from sqlalchemy.orm.session import Session from sqlalchemy.sql.elements import BooleanClauseList from sqlalchemy.sql.expression import ColumnOperators - from typing_extensions import Literal from airflow.models.abstractoperator import TaskStateChangeCallback from airflow.models.baseoperator import BaseOperator @@ -144,7 +143,7 @@ from airflow.models.dataset import DatasetEvent from airflow.models.operator import Operator from airflow.timetables.base import DataInterval - from airflow.typing_compat import TypeGuard + from airflow.typing_compat import Literal, TypeGuard from airflow.utils.task_group import TaskGroup # This is a workaround because mypy doesn't work with hybrid_property diff --git a/airflow/providers_manager.py b/airflow/providers_manager.py index 002747c33255d..48de7776b7379 100644 --- a/airflow/providers_manager.py +++ b/airflow/providers_manager.py @@ -33,11 +33,11 @@ from typing import TYPE_CHECKING, Any, Callable, MutableMapping, NamedTuple, TypeVar, cast from packaging.utils import canonicalize_name -from typing_extensions import Literal from airflow.exceptions import AirflowOptionalProviderFeatureException from airflow.hooks.filesystem import FSHook from airflow.hooks.package_index import PackageIndexHook +from airflow.typing_compat import Literal from airflow.utils import yaml from airflow.utils.entry_points import entry_points_with_dist from airflow.utils.log.logging_mixin import LoggingMixin diff --git a/airflow/typing_compat.py b/airflow/typing_compat.py index 95ef4595522ed..bbe688cc0b6a0 100644 --- a/airflow/typing_compat.py +++ b/airflow/typing_compat.py @@ -31,8 +31,14 @@ from typing import Protocol, TypedDict, runtime_checkable # Literal from typing module has various issues in different Python versions, see: -# https://typing-extensions.readthedocs.io/en/latest/#Literal -from typing_extensions import Literal +# - https://typing-extensions.readthedocs.io/en/latest/#Literal +# - bpo-45679: https://github.com/python/cpython/pull/29334 +# - bpo-42345: https://github.com/python/cpython/pull/23294 +# - bpo-42345: https://github.com/python/cpython/pull/23383 +if sys.version_info >= (3, 10, 1) or (3, 9, 8) <= sys.version_info < (3, 10): + from typing import Literal +else: + from typing_extensions import Literal # type: ignore[assignment] if sys.version_info >= (3, 10): from typing import ParamSpec, TypeGuard diff --git a/airflow/utils/dates.py b/airflow/utils/dates.py index bcf8f0a183c3c..9351c64e2a574 100644 --- a/airflow/utils/dates.py +++ b/airflow/utils/dates.py @@ -23,9 +23,9 @@ from croniter import croniter from dateutil.relativedelta import relativedelta # for doctest -from typing_extensions import Literal from airflow.exceptions import RemovedInAirflow3Warning +from airflow.typing_compat import Literal from airflow.utils import timezone cron_presets: dict[str, str] = {