1# Licensed to the Apache Software Foundation (ASF) under one
2# or more contributor license agreements. See the NOTICE file
3# distributed with this work for additional information
4# regarding copyright ownership. The ASF licenses this file
5# to you under the Apache License, Version 2.0 (the
6# "License"); you may not use this file except in compliance
7# with the License. You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing,
12# software distributed under the License is distributed on an
13# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14# KIND, either express or implied. See the License for the
15# specific language governing permissions and limitations
16# under the License.
17from __future__ import annotations
18
19from functools import wraps
20from typing import Callable, TypeVar
21
22from airflow.typing_compat import ParamSpec
23
24PS = ParamSpec("PS")
25RT = TypeVar("RT")
26
27
28def providers_configuration_loaded(func: Callable[PS, RT]) -> Callable[PS, RT]:
29 """
30 Make sure that providers configuration is loaded before actually calling the decorated function.
31
32 ProvidersManager initialization of configuration is relatively inexpensive - it walks through
33 all providers's entrypoints, retrieve the provider_info and loads config yaml parts of the get_info.
34 Unlike initialization of hooks and operators it does not import any of the provider's code, so it can
35 be run quickly by all commands that need to access providers configuration. We cannot even import
36 ProvidersManager while importing any of the commands, so we need to locally import it here.
37
38 We cannot initialize the configuration in settings/conf because of the way how conf/settings are used
39 internally - they are loaded while importing airflow, and we need to access airflow version conf in the
40 ProvidesManager initialization, so instead we opt for decorating all the methods that need it with this
41 decorator.
42
43 The decorator should be placed below @suppress_logs_and_warning but above @provide_session in order to
44 avoid spoiling the output of formatted options with some warnings ar infos, and to be prepared that
45 session creation might need some configuration defaults from the providers configuration.
46
47 :param func: function to makes sure that providers configuration is loaded before actually calling
48 """
49
50 @wraps(func)
51 def wrapped_function(*args, **kwargs) -> RT:
52 from airflow.providers_manager import ProvidersManager
53
54 ProvidersManager().initialize_providers_configuration()
55 return func(*args, **kwargs)
56
57 return wrapped_function