This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 79286d6398 Resolve `B028` (no-explicit-stacklevel) in core (#39123)
79286d6398 is described below

commit 79286d6398e8e964a467de7f1e9fc10520bba00a
Author: Andrey Anshin <[email protected]>
AuthorDate: Sat Apr 20 11:21:22 2024 +0400

    Resolve `B028` (no-explicit-stacklevel) in core (#39123)
    
    * Resolve `B028` (no-explicit-stacklevel) in core
    
    * Update airflow/cli/commands/connection_command.py
    
    Co-authored-by: Tzu-ping Chung <[email protected]>
    
    ---------
    
    Co-authored-by: Tzu-ping Chung <[email protected]>
---
 airflow/__init__.py                                |  1 +
 .../endpoints/forward_to_fab_endpoint.py           |  1 +
 airflow/cli/commands/connection_command.py         | 12 +++++++---
 airflow/cli/commands/dag_command.py                |  2 ++
 airflow/cli/commands/db_command.py                 |  3 ++-
 airflow/configuration.py                           |  8 +++++--
 airflow/decorators/task_group.py                   |  2 +-
 airflow/jobs/scheduler_job_runner.py               |  3 +++
 airflow/jobs/triggerer_job_runner.py               | 10 +++++++--
 .../pre_7_4_0_compatibility/pod_generator.py       | 12 +++++++---
 airflow/logging_config.py                          |  1 +
 airflow/metrics/otel_logger.py                     |  4 +++-
 airflow/metrics/validators.py                      |  3 +--
 airflow/models/baseoperator.py                     |  4 +++-
 airflow/models/connection.py                       |  3 ++-
 airflow/models/mappedoperator.py                   |  2 +-
 airflow/models/param.py                            |  3 +++
 airflow/models/xcom.py                             |  1 +
 airflow/providers_manager.py                       |  1 +
 airflow/serialization/serialized_objects.py        |  1 +
 airflow/settings.py                                |  1 +
 airflow/utils/context.py                           |  7 ++++--
 airflow/utils/dot_renderer.py                      |  6 ++++-
 airflow/www/app.py                                 |  1 +
 airflow/www/extensions/init_views.py               |  1 +
 pyproject.toml                                     | 26 +---------------------
 26 files changed, 73 insertions(+), 46 deletions(-)

diff --git a/airflow/__init__.py b/airflow/__init__.py
index 2df5571707..65bf6ef5f6 100644
--- a/airflow/__init__.py
+++ b/airflow/__init__.py
@@ -82,6 +82,7 @@ def __getattr__(name: str):
                 f"Python version constraint {name!r} is deprecated and will be 
removed in the future. "
                 f"Please get version info from the 'sys.version_info'.",
                 DeprecationWarning,
+                stacklevel=2,
             )
             return sys.version_info >= (3, int(py_minor))
 
diff --git a/airflow/api_connexion/endpoints/forward_to_fab_endpoint.py 
b/airflow/api_connexion/endpoints/forward_to_fab_endpoint.py
index 6f4b417f83..9785a5b053 100644
--- a/airflow/api_connexion/endpoints/forward_to_fab_endpoint.py
+++ b/airflow/api_connexion/endpoints/forward_to_fab_endpoint.py
@@ -49,6 +49,7 @@ def _require_fab(func: Callable) -> Callable:
                 "This API endpoint is deprecated. "
                 "Please use the API under /auth/fab/v1 instead for this 
operation.",
                 DeprecationWarning,
+                stacklevel=1,  # This decorator wrapped multiple times, better 
point to this file
             )
             return func(*args, **kwargs)
 
diff --git a/airflow/cli/commands/connection_command.py 
b/airflow/cli/commands/connection_command.py
index 2bc1076f2b..c76a648887 100644
--- a/airflow/cli/commands/connection_command.py
+++ b/airflow/cli/commands/connection_command.py
@@ -162,7 +162,9 @@ def connections_export(args):
     """Export all connections to a file."""
     file_formats = [".yaml", ".json", ".env"]
     if args.format:
-        warnings.warn("Option `--format` is deprecated.  Use `--file-format` 
instead.", DeprecationWarning)
+        warnings.warn(
+            "Option `--format` is deprecated. Use `--file-format` instead.", 
DeprecationWarning, stacklevel=3
+        )
     if args.format and args.file_format:
         raise SystemExit("Option `--format` is deprecated.  Use 
`--file-format` instead.")
     default_format = ".json"
@@ -223,10 +225,14 @@ def connections_add(args):
         raise SystemExit("Cannot supply both conn-uri and conn-json")
 
     if has_type and args.conn_type not in _get_connection_types():
-        warnings.warn(f"The type provided to --conn-type is invalid: 
{args.conn_type}")
+        warnings.warn(
+            f"The type provided to --conn-type is invalid: {args.conn_type}", 
UserWarning, stacklevel=4
+        )
         warnings.warn(
             f"Supported --conn-types are:{_get_connection_types()}."
-            "Hence overriding the conn-type with generic"
+            "Hence overriding the conn-type with generic",
+            UserWarning,
+            stacklevel=4,
         )
         args.conn_type = "generic"
 
diff --git a/airflow/cli/commands/dag_command.py 
b/airflow/cli/commands/dag_command.py
index 7f64f9006d..3a91072cdf 100644
--- a/airflow/cli/commands/dag_command.py
+++ b/airflow/cli/commands/dag_command.py
@@ -137,6 +137,7 @@ def dag_backfill(args, dag: list[DAG] | DAG | None = None) 
-> None:
         warnings.warn(
             "--ignore-first-depends-on-past is deprecated as the value is 
always set to True",
             category=RemovedInAirflow3Warning,
+            stacklevel=4,
         )
     args.ignore_first_depends_on_past = True
 
@@ -144,6 +145,7 @@ def dag_backfill(args, dag: list[DAG] | DAG | None = None) 
-> None:
         warnings.warn(
             "--treat-dag-as-regex is deprecated, use --treat-dag-id-as-regex 
instead",
             category=RemovedInAirflow3Warning,
+            stacklevel=4,
         )
         args.treat_dag_id_as_regex = args.treat_dag_as_regex
 
diff --git a/airflow/cli/commands/db_command.py 
b/airflow/cli/commands/db_command.py
index 8cdc2191db..b7ae3ee7f3 100644
--- a/airflow/cli/commands/db_command.py
+++ b/airflow/cli/commands/db_command.py
@@ -50,6 +50,7 @@ def initdb(args):
         "`db init` is deprecated.  Use `db migrate` instead to migrate the db 
and/or "
         "airflow connections create-default-connections to create the default 
connections",
         DeprecationWarning,
+        stacklevel=2,
     )
     print(f"DB: {settings.engine.url!r}")
     db.initdb()
@@ -67,7 +68,7 @@ def resetdb(args):
 
 def upgradedb(args):
     """Upgrades the metadata database."""
-    warnings.warn("`db upgrade` is deprecated. Use `db migrate` instead.", 
DeprecationWarning)
+    warnings.warn("`db upgrade` is deprecated. Use `db migrate` instead.", 
DeprecationWarning, stacklevel=2)
     migratedb(args)
 
 
diff --git a/airflow/configuration.py b/airflow/configuration.py
index 7c1cac1576..37a12ee070 100644
--- a/airflow/configuration.py
+++ b/airflow/configuration.py
@@ -763,6 +763,7 @@ class AirflowConfigParser(ConfigParser):
                 "in the running config, which is needed by the UI. Please 
update your config before "
                 "Apache Airflow 3.0.",
                 FutureWarning,
+                stacklevel=1,
             )
 
     def _upgrade_postgres_metastore_conn(self):
@@ -783,6 +784,7 @@ class AirflowConfigParser(ConfigParser):
                 "As of SQLAlchemy 1.4 (adopted in Airflow 2.3) this is no 
longer supported.  You must "
                 f"change to `{good_scheme}` before the next Airflow release.",
                 FutureWarning,
+                stacklevel=1,
             )
             self.upgraded_values[(section, key)] = old_value
             new_value = re2.sub("^" + re2.escape(f"{parsed.scheme}://"), 
f"{good_scheme}://", old_value)
@@ -841,6 +843,7 @@ class AirflowConfigParser(ConfigParser):
             f"This value has been changed to {new_value!r} in the running 
config, but "
             f"please update your config before Apache Airflow {version}.",
             FutureWarning,
+            stacklevel=3,
         )
 
     def _env_var_name(self, section: str, key: str) -> str:
@@ -2041,18 +2044,19 @@ def 
load_standard_airflow_configuration(airflow_config_parser: AirflowConfigPars
             "environment variable and remove the config file entry."
         )
         if "AIRFLOW_HOME" in os.environ:
-            warnings.warn(msg, category=DeprecationWarning)
+            warnings.warn(msg, category=DeprecationWarning, stacklevel=1)
         elif airflow_config_parser.get("core", "airflow_home") == AIRFLOW_HOME:
             warnings.warn(
                 "Specifying airflow_home in the config file is deprecated. As 
you "
                 "have left it at the default value you should remove the 
setting "
                 "from your airflow.cfg and suffer no change in behaviour.",
                 category=DeprecationWarning,
+                stacklevel=1,
             )
         else:
             # there
             AIRFLOW_HOME = airflow_config_parser.get("core", "airflow_home")  
# type: ignore[assignment]
-            warnings.warn(msg, category=DeprecationWarning)
+            warnings.warn(msg, category=DeprecationWarning, stacklevel=1)
 
 
 def initialize_config() -> AirflowConfigParser:
diff --git a/airflow/decorators/task_group.py b/airflow/decorators/task_group.py
index d347f9e6eb..e76549d386 100644
--- a/airflow/decorators/task_group.py
+++ b/airflow/decorators/task_group.py
@@ -79,7 +79,7 @@ class _TaskGroupFactory(ExpandableFactory, Generic[FParams, 
FReturn]):
                 group_id = repr(self.tg_kwargs["group_id"])
             except KeyError:
                 group_id = f"at {hex(id(self))}"
-            warnings.warn(f"Partial task group {group_id} was never mapped!")
+            warnings.warn(f"Partial task group {group_id} was never mapped!", 
stacklevel=1)
 
     def __call__(self, *args: FParams.args, **kwargs: FParams.kwargs) -> 
DAGNode:
         """Instantiate the task group.
diff --git a/airflow/jobs/scheduler_job_runner.py 
b/airflow/jobs/scheduler_job_runner.py
index 6fab97750b..2dfe2267a5 100644
--- a/airflow/jobs/scheduler_job_runner.py
+++ b/airflow/jobs/scheduler_job_runner.py
@@ -196,6 +196,7 @@ class SchedulerJobRunner(BaseJobRunner, LoggingMixin):
                 "The '[celery] stalled_task_timeout' config option is 
deprecated. "
                 "Please update your config to use '[scheduler] 
task_queued_timeout' instead.",
                 DeprecationWarning,
+                stacklevel=2,
             )
         task_adoption_timeout = conf.getfloat("celery", 
"task_adoption_timeout", fallback=0)
         if task_adoption_timeout:
@@ -204,6 +205,7 @@ class SchedulerJobRunner(BaseJobRunner, LoggingMixin):
                 "The '[celery] task_adoption_timeout' config option is 
deprecated. "
                 "Please update your config to use '[scheduler] 
task_queued_timeout' instead.",
                 DeprecationWarning,
+                stacklevel=2,
             )
         worker_pods_pending_timeout = conf.getfloat(
             "kubernetes_executor", "worker_pods_pending_timeout", fallback=0
@@ -214,6 +216,7 @@ class SchedulerJobRunner(BaseJobRunner, LoggingMixin):
                 "The '[kubernetes_executor] worker_pods_pending_timeout' 
config option is deprecated. "
                 "Please update your config to use '[scheduler] 
task_queued_timeout' instead.",
                 DeprecationWarning,
+                stacklevel=2,
             )
         task_queued_timeout = conf.getfloat("scheduler", "task_queued_timeout")
         self._task_queued_timeout = max(
diff --git a/airflow/jobs/triggerer_job_runner.py 
b/airflow/jobs/triggerer_job_runner.py
index bb151b32cc..8237e1e493 100644
--- a/airflow/jobs/triggerer_job_runner.py
+++ b/airflow/jobs/triggerer_job_runner.py
@@ -131,7 +131,9 @@ def configure_trigger_log_handler():
                     f"Handler {h.__class__.__name__} does not support "
                     "individual trigger logging. Please check the release 
notes "
                     "for your provider to see if a newer version supports "
-                    "individual trigger logging."
+                    "individual trigger logging.",
+                    category=UserWarning,
+                    stacklevel=3,
                 )
             if supports_triggerer(h):
                 return h
@@ -148,7 +150,11 @@ def configure_trigger_log_handler():
             if h:
                 logger.debug("Using logging configuration from `airflow.task`")
         if not h:
-            warnings.warn("Could not find log handler suitable for individual 
trigger logging.")
+            warnings.warn(
+                "Could not find log handler suitable for individual trigger 
logging.",
+                category=UserWarning,
+                stacklevel=3,
+            )
             return None
         return h
 
diff --git a/airflow/kubernetes/pre_7_4_0_compatibility/pod_generator.py 
b/airflow/kubernetes/pre_7_4_0_compatibility/pod_generator.py
index ea4ae63b2e..c665f912ef 100644
--- a/airflow/kubernetes/pre_7_4_0_compatibility/pod_generator.py
+++ b/airflow/kubernetes/pre_7_4_0_compatibility/pod_generator.py
@@ -170,7 +170,7 @@ class PodGenerator:
 
     def gen_pod(self) -> k8s.V1Pod:
         """Generate pod."""
-        warnings.warn("This function is deprecated. ", 
RemovedInAirflow3Warning)
+        warnings.warn("This function is deprecated. ", 
RemovedInAirflow3Warning, stacklevel=2)
         result = self.ud_pod
 
         result.metadata.name = add_pod_suffix(pod_name=result.metadata.name)
@@ -185,7 +185,9 @@ class PodGenerator:
         """Add sidecar."""
         warnings.warn(
             "This function is deprecated. "
-            "Please use 
airflow.providers.cncf.kubernetes.utils.xcom_sidecar.add_xcom_sidecar instead"
+            "Please use 
airflow.providers.cncf.kubernetes.utils.xcom_sidecar.add_xcom_sidecar instead",
+            RemovedInAirflow3Warning,
+            stacklevel=2,
         )
         pod_cp = copy.deepcopy(pod)
         pod_cp.spec.volumes = pod.spec.volumes or []
@@ -223,6 +225,7 @@ class PodGenerator:
                 'please use a `kubernetes.client.models.V1Pod` class with a 
"pod_override" key'
                 " instead. ",
                 category=RemovedInAirflow3Warning,
+                stacklevel=2,
             )
             return PodGenerator.from_legacy_obj(obj)
         else:
@@ -401,7 +404,9 @@ class PodGenerator:
         """
         if len(pod_id) > 253:
             warnings.warn(
-                "pod_id supplied is longer than 253 characters; truncating and 
adding unique suffix."
+                "pod_id supplied is longer than 253 characters; truncating and 
adding unique suffix.",
+                category=UserWarning,
+                stacklevel=2,
             )
             pod_id = add_pod_suffix(pod_name=pod_id, max_len=253)
         try:
@@ -599,6 +604,7 @@ class PodGenerator:
         warnings.warn(
             "This function is deprecated. Use `add_pod_suffix` in 
`kubernetes_helper_functions`.",
             RemovedInAirflow3Warning,
+            stacklevel=2,
         )
 
         if not pod_id:
diff --git a/airflow/logging_config.py b/airflow/logging_config.py
index f3791caeba..f0497c5740 100644
--- a/airflow/logging_config.py
+++ b/airflow/logging_config.py
@@ -96,6 +96,7 @@ def validate_logging_config(logging_config):
                 "but no handler with this name was found. Please update your 
config to use task. "
                 "Running config has been adjusted to match",
                 DeprecationWarning,
+                stacklevel=2,
             )
             conf.set("logging", "task_log_reader", "task")
         else:
diff --git a/airflow/metrics/otel_logger.py b/airflow/metrics/otel_logger.py
index c8a3f0181c..5dac960c16 100644
--- a/airflow/metrics/otel_logger.py
+++ b/airflow/metrics/otel_logger.py
@@ -126,7 +126,9 @@ def _get_otel_safe_name(name: str) -> str:
     if name != otel_safe_name:
         warnings.warn(
             f"Metric name `{name}` exceeds OpenTelemetry's name length limit 
of "
-            f"{OTEL_NAME_MAX_LENGTH} characters and will be truncated to 
`{otel_safe_name}`."
+            f"{OTEL_NAME_MAX_LENGTH} characters and will be truncated to 
`{otel_safe_name}`.",
+            category=UserWarning,
+            stacklevel=2,
         )
     return otel_safe_name
 
diff --git a/airflow/metrics/validators.py b/airflow/metrics/validators.py
index 9fbfa6600d..111ad9b87d 100644
--- a/airflow/metrics/validators.py
+++ b/airflow/metrics/validators.py
@@ -41,8 +41,6 @@ class MetricNameLengthExemptionWarning(Warning):
     Using a custom Warning class allows us to easily test that it is used.
     """
 
-    ...
-
 
 # Only characters in the character set are considered valid
 # for the stat_name if stat_name_default_handler is used.
@@ -198,6 +196,7 @@ def stat_name_otel_handler(
             f"This stat name will be deprecated in the future and replaced 
with "
             f"a shorter name combined with Attributes/Tags.",
             MetricNameLengthExemptionWarning,
+            stacklevel=2,
         )
 
     return proposed_stat_name
diff --git a/airflow/models/baseoperator.py b/airflow/models/baseoperator.py
index 5b6626af37..0fe9bdf380 100644
--- a/airflow/models/baseoperator.py
+++ b/airflow/models/baseoperator.py
@@ -936,7 +936,9 @@ class BaseOperator(AbstractOperator, 
metaclass=BaseOperatorMeta):
         if executor:
             warnings.warn(
                 "Specifying executors for operators is not yet"
-                f"supported, the value {executor!r} will have no effect"
+                f"supported, the value {executor!r} will have no effect",
+                category=UserWarning,
+                stacklevel=2,
             )
         self.executor = executor
         self.executor_config = executor_config or {}
diff --git a/airflow/models/connection.py b/airflow/models/connection.py
index b9b4975f89..6e1435ebfa 100644
--- a/airflow/models/connection.py
+++ b/airflow/models/connection.py
@@ -50,7 +50,7 @@ CONN_ID_MAX_LEN: int = 250
 
 def parse_netloc_to_hostname(*args, **kwargs):
     """Do not use, this method is deprecated."""
-    warnings.warn("This method is deprecated.", RemovedInAirflow3Warning)
+    warnings.warn("This method is deprecated.", RemovedInAirflow3Warning, 
stacklevel=2)
     return _parse_netloc_to_hostname(*args, **kwargs)
 
 
@@ -219,6 +219,7 @@ class Connection(Base, LoggingMixin):
         warnings.warn(
             "This method is deprecated. Please use uri parameter in 
constructor.",
             RemovedInAirflow3Warning,
+            stacklevel=2,
         )
         self._parse_from_uri(**uri)
 
diff --git a/airflow/models/mappedoperator.py b/airflow/models/mappedoperator.py
index c02f7470ed..edb19aada6 100644
--- a/airflow/models/mappedoperator.py
+++ b/airflow/models/mappedoperator.py
@@ -171,7 +171,7 @@ class OperatorPartial:
                 task_id = repr(self.kwargs["task_id"])
             except KeyError:
                 task_id = f"at {hex(id(self))}"
-            warnings.warn(f"Task {task_id} was never mapped!")
+            warnings.warn(f"Task {task_id} was never mapped!", 
category=UserWarning, stacklevel=1)
 
     def expand(self, **mapped_kwargs: OperatorExpandArgument) -> 
MappedOperator:
         if not mapped_kwargs:
diff --git a/airflow/models/param.py b/airflow/models/param.py
index d87b3721bb..a750ffb583 100644
--- a/airflow/models/param.py
+++ b/airflow/models/param.py
@@ -76,6 +76,7 @@ class Param:
                 "The use of non-json-serializable params is deprecated and 
will be removed in "
                 "a future release",
                 RemovedInAirflow3Warning,
+                stacklevel=1,
             )
 
     @staticmethod
@@ -91,11 +92,13 @@ class Param:
             f"The use of non-RFC3339 datetime: {value!r} is deprecated "
             "and will be removed in a future release",
             RemovedInAirflow3Warning,
+            stacklevel=1,
         )
         if timezone.is_naive(iso8601_value):
             warnings.warn(
                 "The use naive datetime is deprecated and will be removed in a 
future release",
                 RemovedInAirflow3Warning,
+                stacklevel=1,
             )
         return value
 
diff --git a/airflow/models/xcom.py b/airflow/models/xcom.py
index f9afda123c..7a6695c1b3 100644
--- a/airflow/models/xcom.py
+++ b/airflow/models/xcom.py
@@ -842,6 +842,7 @@ def _patch_outdated_serializer(clazz: type[BaseXCom], 
params: Iterable[str]) ->
             f"must be updated to accept all params in `BaseXCom.set` except 
`session`. Support will be "
             f"removed in a future release.",
             RemovedInAirflow3Warning,
+            stacklevel=1,
         )
         return old_serializer(**kwargs)
 
diff --git a/airflow/providers_manager.py b/airflow/providers_manager.py
index 1070db501d..cf78673c05 100644
--- a/airflow/providers_manager.py
+++ b/airflow/providers_manager.py
@@ -828,6 +828,7 @@ class ProvidersManager(LoggingMixin, metaclass=Singleton):
                     "of 'connection-types' in Airflow 2.2. Use **both** in 
case you want to "
                     "have backwards compatibility with Airflow < 2.2",
                     DeprecationWarning,
+                    stacklevel=1,
                 )
         for already_registered_connection_type in 
already_registered_warning_connection_types:
             log.warning(
diff --git a/airflow/serialization/serialized_objects.py 
b/airflow/serialization/serialized_objects.py
index 9f8664477b..bbe5553489 100644
--- a/airflow/serialization/serialized_objects.py
+++ b/airflow/serialization/serialized_objects.py
@@ -1261,6 +1261,7 @@ class SerializedBaseOperator(BaseOperator, 
BaseSerialization):
                     "Use of a custom dependency detector is deprecated. "
                     "Support will be removed in a future release.",
                     RemovedInAirflow3Warning,
+                    stacklevel=1,
                 )
                 dep = 
custom_dependency_detector_cls().detect_task_dependencies(op)
                 if type(dep) is DagDependency:
diff --git a/airflow/settings.py b/airflow/settings.py
index fa859fdf42..7b8a222444 100644
--- a/airflow/settings.py
+++ b/airflow/settings.py
@@ -493,6 +493,7 @@ def get_session_lifetime_config():
             "session lifetime in minutes. The `force_log_out_after` option has 
been removed "
             "from `[webserver]` section. Please update your configuration.",
             category=RemovedInAirflow3Warning,
+            stacklevel=2,
         )
         if session_lifetime_days:
             session_lifetime_minutes = minutes_per_day * 
int(session_lifetime_days)
diff --git a/airflow/utils/context.py b/airflow/utils/context.py
index 78536bc972..72f3e3787e 100644
--- a/airflow/utils/context.py
+++ b/airflow/utils/context.py
@@ -237,7 +237,10 @@ class Context(MutableMapping[str, Any]):
 
     def __getitem__(self, key: str) -> Any:
         with contextlib.suppress(KeyError):
-            warnings.warn(_create_deprecation_warning(key, 
self._deprecation_replacements[key]))
+            warnings.warn(
+                _create_deprecation_warning(key, 
self._deprecation_replacements[key]),
+                stacklevel=2,
+            )
         with contextlib.suppress(KeyError):
             return self._context[key]
         raise KeyError(key)
@@ -345,7 +348,7 @@ def lazy_mapping_from_context(source: Context) -> 
Mapping[str, Any]:
 
     def _deprecated_proxy_factory(k: str, v: Any) -> Any:
         replacements = source._deprecation_replacements[k]
-        warnings.warn(_create_deprecation_warning(k, replacements))
+        warnings.warn(_create_deprecation_warning(k, replacements), 
stacklevel=2)
         return v
 
     def _create_value(k: str, v: Any) -> Any:
diff --git a/airflow/utils/dot_renderer.py b/airflow/utils/dot_renderer.py
index 6e20609067..4cc3be5ddf 100644
--- a/airflow/utils/dot_renderer.py
+++ b/airflow/utils/dot_renderer.py
@@ -26,7 +26,11 @@ from typing import TYPE_CHECKING, Any
 try:
     import graphviz
 except ImportError:
-    warnings.warn("Could not import graphviz. Rendering graph to the graphical 
format will not be possible.")
+    warnings.warn(
+        "Could not import graphviz. Rendering graph to the graphical format 
will not be possible.",
+        UserWarning,
+        stacklevel=2,
+    )
     graphviz = None
 
 from airflow.exceptions import AirflowException
diff --git a/airflow/www/app.py b/airflow/www/app.py
index 17a4c681dd..50e1ba2629 100644
--- a/airflow/www/app.py
+++ b/airflow/www/app.py
@@ -116,6 +116,7 @@ def create_app(config=None, testing=False):
             "Old deprecated value found for `cookie_samesite` option in 
`[webserver]` section. "
             "Using `Lax` instead. Change the value to `Lax` in airflow.cfg to 
remove this warning.",
             RemovedInAirflow3Warning,
+            stacklevel=2,
         )
         cookie_samesite_config = "Lax"
     flask_app.config["SESSION_COOKIE_SAMESITE"] = cookie_samesite_config
diff --git a/airflow/www/extensions/init_views.py 
b/airflow/www/extensions/init_views.py
index 01a726bd69..bf6cdfdcfe 100644
--- a/airflow/www/extensions/init_views.py
+++ b/airflow/www/extensions/init_views.py
@@ -317,6 +317,7 @@ def init_api_experimental(app):
         "Please note that the experimental API do not have access control. "
         "The authenticated user has full access.",
         RemovedInAirflow3Warning,
+        stacklevel=2,
     )
     base_paths.append("/api/experimental")
     app.register_blueprint(endpoints.api_experimental, 
url_prefix="/api/experimental")
diff --git a/pyproject.toml b/pyproject.toml
index c8c64b0847..1270bc9e2d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -326,7 +326,7 @@ required-imports = ["from __future__ import annotations"]
 combine-as-imports = true
 
 [tool.ruff.lint.per-file-ignores]
-"airflow/__init__.py" = ["F401", "B028"]
+"airflow/__init__.py" = ["F401"]
 "airflow/models/__init__.py" = ["F401", "TCH004"]
 "airflow/models/sqla_models.py" = ["F401"]
 
@@ -386,30 +386,6 @@ combine-as-imports = true
 "tests/providers/snowflake/operators/test_snowflake_sql.py" = ["E402"]
 
 # All the modules which do not follow B028 yet: 
https://docs.astral.sh/ruff/rules/no-explicit-stacklevel/
-"airflow/api_connexion/endpoints/forward_to_fab_endpoint.py" = ["B028"]
-"airflow/cli/commands/connection_command.py" = ["B028"]
-"airflow/cli/commands/dag_command.py" = ["B028"]
-"airflow/cli/commands/db_command.py" = ["B028"]
-"airflow/configuration.py" = ["B028"]
-"airflow/decorators/task_group.py" = ["B028"]
-"airflow/jobs/scheduler_job_runner.py" = ["B028"]
-"airflow/jobs/triggerer_job_runner.py" = ["B028"]
-"airflow/kubernetes/pre_7_4_0_compatibility/pod_generator.py" = ["B028"]
-"airflow/logging_config.py" = ["B028"]
-"airflow/metrics/otel_logger.py" = ["B028"]
-"airflow/metrics/validators.py" = ["B028"]
-"airflow/models/baseoperator.py" = ["B028"]
-"airflow/models/connection.py" = ["B028"]
-"airflow/models/mappedoperator.py" = ["B028"]
-"airflow/models/param.py" = ["B028"]
-"airflow/models/xcom.py" = ["B028"]
-"airflow/providers_manager.py" = ["B028"]
-"airflow/serialization/serialized_objects.py" = ["B028"]
-"airflow/settings.py" = ["B028"]
-"airflow/utils/context.py" = ["B028"]
-"airflow/utils/dot_renderer.py" = ["B028"]
-"airflow/www/app.py" = ["B028"]
-"airflow/www/extensions/init_views.py" = ["B028"]
 "airflow/providers/jdbc/hooks/jdbc.py" = ["B028"]
 "airflow/providers/microsoft/azure/hooks/synapse.py" = ["B028"]
 "helm_tests/airflow_aux/test_basic_helm_chart.py" = ["B028"]

Reply via email to