From d8abdad5a11f3e2aed952b109849d7fe6ba35d49 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 27 Aug 2026 14:48:25 +0930 Subject: [PATCH 1/2] [Core] Fix #33996: `az network vnet create`: Eagerly import requests during CLI startup to avoid Python 3.14 module-lock deadlock * Initial plan * [Core] Eagerly import requests/msal in auth/identity.py to avoid Python 3.14 deadlock Co-authored-by: a0x1ab <59631311+a0x1ab@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: a0x1ab <59631311+a0x1ab@users.noreply.github.com> --- .../azure/cli/core/auth/identity.py | 8 ++ .../cli/core/tests/test_auth_eager_import.py | 80 +++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 src/azure-cli-core/azure/cli/core/tests/test_auth_eager_import.py diff --git a/src/azure-cli-core/azure/cli/core/auth/identity.py b/src/azure-cli-core/azure/cli/core/auth/identity.py index 91629e89441..6b48ae8c564 100644 --- a/src/azure-cli-core/azure/cli/core/auth/identity.py +++ b/src/azure-cli-core/azure/cli/core/auth/identity.py @@ -8,6 +8,14 @@ import re import sys +# Eagerly import requests and msal here, on the main thread, so that their +# submodules (e.g. requests.structures) are fully initialised in sys.modules +# before any background thread can trigger a lazy import. Python 3.14 +# detects import-lock ordering cycles and raises _DeadlockError when two +# threads race to initialise the same module; pre-loading avoids the race. +import msal # noqa: F401 +import requests # noqa: F401 + from azure.cli.core._environment import get_config_dir from knack.log import get_logger from knack.util import CLIError diff --git a/src/azure-cli-core/azure/cli/core/tests/test_auth_eager_import.py b/src/azure-cli-core/azure/cli/core/tests/test_auth_eager_import.py new file mode 100644 index 00000000000..f2a1f4ebb31 --- /dev/null +++ b/src/azure-cli-core/azure/cli/core/tests/test_auth_eager_import.py @@ -0,0 +1,80 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- +"""Regression test: azure.cli.core.auth.identity must eagerly import requests and msal. + +Python 3.14 raises _DeadlockError when two threads race to initialise a module +whose import-lock ordering creates a cycle (e.g. requests.structures). The fix +is to pre-load requests (and msal) on the main thread before any background +thread can trigger the same import lazily. This test guards against the eager +import being removed in the future. +""" + +import sys +import unittest + +# Modules that azure.cli.core.auth.identity must eagerly pre-load. +_EAGER_MODULES = ('requests', 'requests.structures', 'msal') + +# All modules that must be evicted from sys.modules to make the test +# independent of import order within the test session. +_EVICT_PREFIXES = ( + 'azure.cli.core.auth', + 'requests', + 'msal', +) + + +def _evict_modules(): + """Remove all cached copies of identity and the packages it should eagerly load.""" + for key in list(sys.modules): + for prefix in _EVICT_PREFIXES: + if key == prefix or key.startswith(prefix + '.'): + del sys.modules[key] + break + + +class TestEagerImport(unittest.TestCase): + + def setUp(self): + # Evict modules so the import inside each test re-executes the module + # body, which is the only way to reliably detect a missing eager import. + _evict_modules() + + def tearDown(self): + # Leave sys.modules clean so other tests are not affected. + _evict_modules() + + def test_requests_in_sys_modules_after_identity_import(self): + """After importing azure.cli.core.auth.identity, requests must already be + present in sys.modules so that no background thread can trigger a lazy + import that would race with Python 3.14 per-module import locks.""" + import azure.cli.core.auth.identity # noqa: F401 + + self.assertIn( + 'requests', + sys.modules, + "requests must be eagerly imported by azure.cli.core.auth.identity " + "to prevent Python 3.14 module-lock deadlocks in background threads.", + ) + self.assertIn( + 'requests.structures', + sys.modules, + "requests.structures must be present in sys.modules after importing " + "azure.cli.core.auth.identity.", + ) + + def test_msal_in_sys_modules_after_identity_import(self): + """msal must be eagerly imported by azure.cli.core.auth.identity.""" + import azure.cli.core.auth.identity # noqa: F401 + + self.assertIn( + 'msal', + sys.modules, + "msal must be eagerly imported by azure.cli.core.auth.identity.", + ) + + +if __name__ == '__main__': + unittest.main() From e2ae3aa2059f5164e107d7f183057e847df5ad91 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 27 Aug 2026 17:36:24 +0000 Subject: [PATCH 2/2] fix: suppress pylint unused-import warnings for eager-load imports in identity.py Co-authored-by: a0x1ab <59631311+a0x1ab@users.noreply.github.com> --- src/azure-cli-core/azure/cli/core/auth/identity.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/azure-cli-core/azure/cli/core/auth/identity.py b/src/azure-cli-core/azure/cli/core/auth/identity.py index 6b48ae8c564..4e42f40b5de 100644 --- a/src/azure-cli-core/azure/cli/core/auth/identity.py +++ b/src/azure-cli-core/azure/cli/core/auth/identity.py @@ -13,8 +13,8 @@ # before any background thread can trigger a lazy import. Python 3.14 # detects import-lock ordering cycles and raises _DeadlockError when two # threads race to initialise the same module; pre-loading avoids the race. -import msal # noqa: F401 -import requests # noqa: F401 +import msal # noqa: F401 # pylint: disable=unused-import +import requests # noqa: F401 # pylint: disable=unused-import from azure.cli.core._environment import get_config_dir from knack.log import get_logger