microsoft / microsoft/simplechat
Break circular Python imports and replace import-order workarounds
@paullizer is already working on this.
Since Sep 7, 2026.
- Dominant language
- Python
- Stars
- 153
- Forks
- 116
- Avg merge
- 7h 7m
- Merged PRs (30d)
- 122
Description
Summary
Remove circular Python dependencies and the import-order workarounds they require through small, behavior-preserving refactoring steps. Keep legitimate optional/performance-driven lazy imports rather than mechanically moving every import to module scope.
Scope
- Establish a reproducible import-dependency inventory and regression guard, distinguishing module-scope, function-local, conditional, and dynamic imports.
- Break the settings/document-analysis cycle by separating pure defaults, constants, and input normalization from service implementations.
- Untangle settings/authentication and cache/logging/Key Vault dependencies without changing authorization, settings refresh, Redis fallback, or secret handling.
- Separate configuration from Cosmos/client/media initialization; make initialization explicit at the web and scheduler entrypoints while preserving their existing invocation contracts.
- Move shared business logic out of route modules so chat/orchestration/workflow and Control Center services do not import HTTP route implementations. Address the related visual-export and MCP factory/runtime cycles in separate slices.
- Replace wildcard imports and dual-path import fallbacks in migrated boundaries with explicit dependencies; avoid an unrelated repository-wide formatting or package-layout rewrite.
- Add isolated regression coverage, document the dependency rules, and update the application version when implementation lands.
Acceptance Criteria
- The current module-scope cycle is removed and the application-module import graph remains free of module-scope cycles.
- Existing deferred cycles are reduced by moving shared responsibilities to lower-level modules, not merely hidden behind additional local imports or importlib calls; any retained cycle has an explicit justification and tracked follow-up.
- Migrated service modules do not import route modules, and foundational configuration/contract imports do not create Azure resources or start background work.
- Cold imports in supported orders and explicit initialization are covered without live Azure calls; repeated initialization does not duplicate clients, handlers, or background loops.
- Existing web/scheduler entrypoints, settings behavior, route/Blueprint security policies, document permissions, optional features, and shared-cache behavior are preserved.
- Dependency checks detect new or reintroduced edges, including cycle regressions inside an existing connected component; scoped exceptions cannot grow silently.
- Functional-test headers and fix documentation reference the implementation version from application/single_app/config.py.
Notes
Initial read-only inventory at application version 0.261.101 covered 298 named Python modules under application/single_app. The explicit-import graph has one module-scope cyclic component containing nine modules. One representative path is:
functions_settings -> functions_document_actions -> functions_document_analysis -> functions_search -> functions_content -> functions_settings
Including function-local imports exposes three cyclic components involving 117 modules, including one 111-module component. There are 217 wildcard import statements across 60 modules; 56 modules use from config import *. These are static dependency findings, not a claim that every cycle currently causes a startup failure. Dynamic imports and implicit package initialization need to be included in the implementation baseline.
Existing guardrails include functional_tests/test_codeql_import_cycle_lazy_imports.py and functional_tests/route_tests/. The plan must preserve those regression contracts while replacing source-shape workarounds with behavior and dependency-boundary coverage.
Requested triage: P2, L, assigned to paullizer. Planning only at issue creation; application code has not been changed.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.