[Core] Fix #33996: az network vnet create: Eagerly import requests during CLI startup to avoid Python 3.14 module-lock deadlock - #33997
Conversation
…ests 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 Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
This PR addresses an intermittent Python 3.14 _DeadlockError seen in auth flows (e.g., az network vnet create) by ensuring relevant auth/networking dependencies are imported early enough to avoid import-lock ordering cycles under multi-threaded execution.
Changes:
- Add eager imports in
azure.cli.core.auth.identityintended to pre-loadrequests(and MSAL) before credential creation can trigger lazy imports on worker threads. - Add a regression unit test that evicts relevant modules from
sys.modules, re-importsidentity, and asserts expected modules are preloaded.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/azure-cli-core/azure/cli/core/auth/identity.py | Adds eager imports to reduce risk of Python 3.14 module-lock deadlock during auth initialization. |
| src/azure-cli-core/azure/cli/core/tests/test_auth_eager_import.py | Adds regression coverage asserting eager import behavior after a clean re-import. |
Suppressed comments (1)
src/azure-cli-core/azure/cli/core/tests/test_auth_eager_import.py:70
- This file appears to use pylint-style disables elsewhere in the repo;
# noqa: F401may not suppress the unused-import warning in CI. Prefer# pylint: disable=unused-importon this import statement.
import azure.cli.core.auth.identity # noqa: F401
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| # 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 |
| """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 |
Live test skipped⏭️ Skipping the live test for this revision because the only test file(s) changed are These |
|
Core |
There was a problem hiding this comment.
Upstream CI
- azdev-style (7 retries, all failing on the same head
d8abdad): run — pylint fails with:This is PR-related: pylint does not honor thesrc/azure-cli-core/azure/cli/core/auth/identity.py:16:0: W0611: Unused import msal (unused-import) src/azure-cli-core/azure/cli/core/auth/identity.py:17:0: W0611: Unused import requests (unused-import)# noqa: F401suppression used on the new eagerimport msal/import requestslines (that comment only suppresses flake8). Next action: replace# noqa: F401with# pylint: disable=unused-import # noqa: F401(or add a matching# pylint: disable=unused-importline) on both new import lines insrc/azure-cli-core/azure/cli/core/auth/identity.py, then re-runazdev stylelocally (azdev style azure-cli-core) to confirm pylint passes before re-pushing. - Three checks (
Azure.azure-cli Breaking Change Test,Azure.azure-cli Full Test,Azure.azure-cli) have been queued for over 3 hours with no re-triggerable check suite found; treating them as abandoned rather than blocking this review. Recommend re-queuing them once the pylint fix above is pushed.
Test validation
- Live test: skipped — the PR only changes
azure-cli-coreunit tests, which are not runnable byazdev test --live. - Regression coverage: not applicable; the change is accompanied by a focused new unit test (
test_auth_eager_import.py) that evicts and re-imports the module to assertrequests,requests.structuresandmsalland insys.modules.
Risk assessment
- Scope: single focused change to
identity.pyplus a matching regression test; no unrelated files touched. - Recommended review owner: Core squad (
azure-cli-core/ auth).
There was a problem hiding this comment.
Upstream CI
- azdev-style (pylint) — failing, PR-related. The style/pylint job fails with:
This is caused directly by this PR's eager-import change in
src/azure-cli-core/azure/cli/core/auth/identity.py:16:0: W0611: Unused import msal (unused-import) src/azure-cli-core/azure/cli/core/auth/identity.py:17:0: W0611: Unused import requests (unused-import)identity.py(adding top-levelimport msal/import requeststo force module loading at CLI startup, per the PR description). Pylint flags them as unused because the names aren't referenced elsewhere in the module.- Next action: Keep the eager-import behavior but silence the specific warning, e.g. add
# pylint: disable=unused-importon those two import lines (or reference the modules, e.g. viaimportlib.import_module("msal")/importlib.import_module("requests")if a no-op reference is preferred), then re-runazdev stylelocally before pushing. - Verify: Re-run the
azdev-stylecheck on the new head; confirmERROR: Pylint: FAILEDno longer appears andYour code has been rated at 10.00/10remains true.
- Next action: Keep the eager-import behavior but silence the specific warning, e.g. add
Test validation
- Live test: Skipped — no runnable changed test files (only
azure-cli-coreunit tests changed, not covered byazdev test --live). - Regression coverage: Not applicable to the changed files.
Risk assessment
0/100 · Low · Low confidence
The Low rating reflects the detected change scope with no elevated security, reliability, customer, operational, dependency, sovereign-cloud, generated-output, or cross-component signal.
- Change scope: 2 changed files, 88 changed lines (
+88/-0), including 0 production files. - Affected components: No production component was identified.
- Risk drivers: No elevated risk signal was detected.
- Regression evidence: No production-code regression-test signal applies.
- Confidence: Low because no production changed-line evidence was available.
- Required review: No additional owning-squad review signal was detected.
|
Started a Copilot task using |
There was a problem hiding this comment.
Upstream CI
azdev-style
- Result: failure
- Relevance: Uncertain
- Evidence: The check completed without a concise diagnostic.
- Suggested fix: Open the linked log and confirm whether the first actionable error touches the PR diff before changing code.
- Verify: Re-run
azdev-styleand confirm it passes on the new head.
azdev-style
- Result: failure
- Relevance: Uncertain
- Evidence: The check completed without a concise diagnostic.
- Suggested fix: Open the linked log and confirm whether the first actionable error touches the PR diff before changing code.
- Verify: Re-run
azdev-styleand confirm it passes on the new head.
azdev-style
- Result: failure
- Relevance: Uncertain
- Evidence: The check completed without a concise diagnostic.
- Suggested fix: Open the linked log and confirm whether the first actionable error touches the PR diff before changing code.
- Verify: Re-run
azdev-styleand confirm it passes on the new head.
azdev-style
- Result: failure
- Relevance: Uncertain
- Evidence: The check completed without a concise diagnostic.
- Suggested fix: Open the linked log and confirm whether the first actionable error touches the PR diff before changing code.
- Verify: Re-run
azdev-styleand confirm it passes on the new head.
azdev-style
- Result: failure
- Relevance: Uncertain
- Evidence: The check completed without a concise diagnostic.
- Suggested fix: Open the linked log and confirm whether the first actionable error touches the PR diff before changing code.
- Verify: Re-run
azdev-styleand confirm it passes on the new head.
azdev-style
- Result: failure
- Relevance: Uncertain
- Evidence: The check completed without a concise diagnostic.
- Suggested fix: Open the linked log and confirm whether the first actionable error touches the PR diff before changing code.
- Verify: Re-run
azdev-styleand confirm it passes on the new head.
azdev-style
- Result: failure
- Relevance: Uncertain
- Evidence: The check completed without a concise diagnostic.
- Suggested fix: Open the linked log and confirm whether the first actionable error touches the PR diff before changing code.
- Verify: Re-run
azdev-styleand confirm it passes on the new head.
azdev-style
- Result: failure
- Relevance: Uncertain
- Evidence: The check completed without a concise diagnostic.
- Suggested fix: Open the linked log and confirm whether the first actionable error touches the PR diff before changing code.
- Verify: Re-run
azdev-styleand confirm it passes on the new head.
azdev-style
- Result: failure
- Relevance: Uncertain
- Evidence: The check completed without a concise diagnostic.
- Suggested fix: Open the linked log and confirm whether the first actionable error touches the PR diff before changing code.
- Verify: Re-run
azdev-styleand confirm it passes on the new head.
azdev-style
- Result: failure
- Relevance: Uncertain
- Evidence: The check completed without a concise diagnostic.
- Suggested fix: Open the linked log and confirm whether the first actionable error touches the PR diff before changing code.
- Verify: Re-run
azdev-styleand confirm it passes on the new head.
Test validation
- Live test: Skipped: live tests are disabled for this repository; upstream CI is authoritative.
- Regression coverage: Not applicable to the changed files.
Risk assessment
0/100 · Low · Low confidence
The Low rating reflects the detected change scope with no elevated security, reliability, customer, operational, dependency, sovereign-cloud, generated-output, or cross-component signal.
- Change scope: 2 changed files, 88 changed lines (
+88/-0), including 0 production files. - Affected components: No production component was identified.
- Risk drivers: No elevated risk signal was detected.
- Regression evidence: No production-code regression-test signal applies.
- Confidence: Low because no production changed-line evidence was available.
- Required review: No additional owning-squad review signal was detected.
|
Started a Copilot task using |
|
🔔 Routing this PR to @Azure/act-quality-productivity-squad. |
|
🔔 Routing this PR to @Azure/act-platform-engineering-squad. |
There was a problem hiding this comment.
CI Failure: azdev-style — Unused Imports in identity.py
Upstream CI
azdev-style
- Result: failure
- Relevance: PR-related
- Evidence (from run log):
ERROR: ************* Module azure.cli.core.auth.identity src/azure-cli-core/azure/cli/core/auth/identity.py:16:0: W0611: Unused import msal (unused-import) src/azure-cli-core/azure/cli/core/auth/identity.py:17:0: W0611: Unused import requests (unused-import) ERROR: Pylint: FAILED - Cause: The PR adds
import msalandimport requestsat module level inidentity.pyto perform eager loading at CLI startup and avoid a Python 3.14 module-lock deadlock. Pylint flags both as unused because they are never referenced in that module. - Required fix: Suppress the unused-import warnings for these intentional eager-import lines. Add
# pylint: disable=unused-import(or inline# noqa: F401) to each import line, or add a brief comment explaining the eager-loading intent so the suppression is self-documenting. For example:import msal # pylint: disable=unused-import # eager load to avoid Python 3.14 module-lock deadlock import requests # pylint: disable=unused-import # eager load to avoid Python 3.14 module-lock deadlock
- Verify: Re-run
azdev stylelocally (azdev style -m azure-cli-core) and confirm it passes with exit code 0.
Test validation
- Live test: Skipped: no runnable changed test files were found.
- Regression coverage: Not applicable to the changed files.
Risk assessment
0/100 · Low · Low confidence
The Low rating reflects the detected change scope with no elevated security, reliability, customer, operational, dependency, sovereign-cloud, generated-output, or cross-component signal.
- Change scope: 2 changed files, 88 changed lines (
+88/-0), including 0 production files. - Affected components: No production component was identified.
- Risk drivers: No elevated risk signal was detected.
- Regression evidence: No production-code regression-test signal applies.
- Confidence: Low because no production changed-line evidence was available.
- Required review: No additional owning-squad review signal was detected.
|
Started a Copilot task using |
… identity.py Co-authored-by: a0x1ab <59631311+a0x1ab@users.noreply.github.com>
Live test skipped⏭️ Skipping the live test for this revision because the only test file(s) changed are These |
There was a problem hiding this comment.
Automated review handoff
This PR has reached the automated Copilot fix-iteration cap (3 attempts) and is still showing a failing check, so it is being handed off for human review rather than re-triggering another automated attempt.
Outstanding CI result
Azure.azure-cli
- Result: failure
- Failure details:
- Verify latest index assets — classified Not PR-related
- Evidence: The job running on agent pool-ubuntu-2204 21 ran longer than the maximum time of 20 minutes.
- Next action: Re-run the timed-out job. If it times out again at the same setup/checkout step, escalate to the pipeline owner rather than changing PR source — the failure is a job timeout unrelated to the change (an eager
import requests/msaladdition plus a new unit test inazure-cli-core). - Verify: Re-run
Verify latest index assetsand confirm it completes within the 20-minute limit.
- Verify latest index assets — classified Not PR-related
Test validation
- Live test: Skipped — no runnable changed test files were found (only
azure-cli-coreunit tests changed). - Regression coverage: Not applicable to the changed files.
Review-skill findings
No deterministic or evidence-confirmed semantic findings.
Risk assessment
0/100 · Low · Low confidence
The Low rating reflects the detected change scope with no elevated security, reliability, customer, operational, dependency, sovereign-cloud, generated-output, or cross-component signal.
- Change scope: 2 changed files, 88 changed lines (
+88/-0), including 0 production files. - Affected components: No production component was identified.
- Risk drivers: No elevated risk signal was detected.
- Regression evidence: No production-code regression-test signal applies.
- Confidence: Low because no production changed-line evidence was available.
- Required review: No additional owning-squad review signal was detected.
🤖 PR Validation — ️✔️ All clear
Description
Fixes #33996.
Related command
az network vnet create(and any command that constructs an MSAL credential)Description
Python 3.14 detects import-lock ordering cycles and raises
_DeadlockErrorinstead of blocking forever. Whenmsallazily importsrequestsfrom a background/worker thread while the main thread is mid-import of a transitively-imported submodule (e.g.requests.structures), the per-module lock ordering creates a detectable cycle, causing intermittent failures like:Fix: eagerly
import msalandimport requestsat module-load time inazure/cli/core/auth/identity.py. This guarantees both packages and all their submodules are fully initialised insys.moduleson the main thread before any credential-creation code runs on a worker thread, eliminating the race entirely.Regression test added in
tests/test_auth_eager_import.py: evictsrequests,msal, andazure.cli.core.authfromsys.modulesinsetUp/tearDown, then re-importsidentityand assertsrequests,requests.structures, andmsalare all present — ensuring the eager imports cannot be silently removed.Testing Guide
cd src/azure-cli-core python -m unittest azure.cli.core.tests.test_auth_eager_import -vHistory Notes
[Core]
az network vnet create: Fix intermittent Python 3.14_DeadlockErroronrequests.structuresby eagerly importingrequestsandmsalat CLI startup