Repository: apache/airflow
File: airflow-core/src/airflow/api_fastapi/main.py (Python)

Code before:
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

from __future__ import annotations

import os

# Mark this as a server context before any airflow imports
# This ensures plugins loaded at import time get the correct secrets backend chain
os.environ["_AIRFLOW_PROCESS_CONTEXT"] = "server"

# Defensive: Disable uvloop if PYTHONASYNCIODEBUG=1 is set (see Airflow issue #61214)
if os.environ.get("PYTHONASYNCIODEBUG") == "1":
    import asyncio
    import warnings

    # Explicitly set the default event loop policy to prevent uvloop from being used
    asyncio.set_event_loop_policy(asyncio.DefaultEventLoopPolicy())

    warnings.warn(
        "PYTHONASYNCIODEBUG=1 detected: uvloop is not compatible with asyncio debug mode on Python 3.13+. "
        "Using default asyncio event loop.",
        RuntimeWarning,
        stacklevel=2,
    )

from airflow.api_fastapi.app import cached_app

# There is no way to pass the apps to this file from Airflow CLI
# because fastapi dev command does not accept any additional arguments
# so environment variable is being used to pass it
app = cached_app(apps=os.environ.get("AIRFLOW_API_APPS", "all"))


Review comment (bug):
I'm not sure whether `asyncio.set_event_loop_policy(asyncio.DefaultEventLoopPolicy())` will prevent uvloop from being used.  
https://docs.python.org/3/library/asyncio-policy.html#asyncio.DefaultEventLoopPolicy

It seems we don't even have the ability to control uvloop, and this might be out of scope for Airflow. Since the dependency chain is fastapi -> uvicorn -> uvloop, even bugs in uvloop will also be out of scope for uvicorn, for example: https://github.com/Kludex/uvicorn/issues/2464#issuecomment-2365198633.

So I think the only thing we can do is add a warning, which should be enough for users.

Code after:
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

from __future__ import annotations

import os
import sys

# Mark this as a server context before any airflow imports
# This ensures plugins loaded at import time get the correct secrets backend chain
os.environ["_AIRFLOW_PROCESS_CONTEXT"] = "server"

# Warn if PYTHONASYNCIODEBUG or PYTHONDEVMODE is set on Python 3.12+ (see Airflow issue #61214)
if sys.version_info >= (3, 12) and (
    os.environ.get("PYTHONASYNCIODEBUG") == "1" or os.environ.get("PYTHONDEVMODE") == "1"
):
    import warnings

    warnings.warn(
        "PYTHONASYNCIODEBUG or PYTHONDEVMODE detected on Python 3.12+: "
        "The API server may crash due to uvloop incompatibility with asyncio debug mode. "
        "See https://github.com/apache/airflow/issues/61214 for details.",
        RuntimeWarning,
        stacklevel=2,
    )

from airflow.api_fastapi.app import cached_app

# There is no way to pass the apps to this file from Airflow CLI
# because fastapi dev command does not accept any additional arguments
# so environment variable is being used to pass it
app = cached_app(apps=os.environ.get("AIRFLOW_API_APPS", "all"))