Python’s reputation for readability doesn’t immunize it from structural problems. Across 12 open-source Python repositories, every single one contained functions with complex branching—the only antipattern to achieve 100% prevalence in this dataset. The average top risk score of 18.9 indicates these aren’t edge cases buried in utility code; they’re active liabilities in otherwise well-maintained projects.
Methodology
I used the hotspots CLI to analyze 12 trending Python repositories, calculating activity risk scores that combine structural complexity (cyclomatic complexity × nesting depth × fan-out) with recent commit frequency from git history. This surfaces functions that are both architecturally problematic and actively changing—the combination most likely to introduce bugs. Repositories were selected from actively maintained open-source projects with meaningful commit histories.
The Most Common Antipatterns
Complex branching appeared in all 12 repositories. This pattern flags functions with cyclomatic complexity exceeding 15—enough conditional paths that comprehensive testing becomes impractical without deliberate effort. Python’s lack of switch statements historically pushed developers toward if-elif chains, and while match statements arrived in 3.10, the pattern persists in codebases supporting older versions or written by developers accustomed to the old style.
Exit-heavy functions showed up in 11 of 12 repos. Multiple return points scatter a function’s responsibility across its body, making it harder to reason about postconditions. Python’s early-return idiom for guard clauses is generally fine, but the prevalence here suggests something more systemic—functions that grew organically and accumulated exit points without refactoring.
God functions also appeared in 11 of 12 repos, as did long functions and deeply nested code. The god function pattern is particularly telling: it requires simultaneous high complexity, high fan-out, and excessive length. When a function coordinates many other components while also containing dense branching logic, it becomes a single point of failure for understanding and modification.
The Highest-Risk Repositories
exo-explore/exo leads with a risk score of 21.1. The distributed inference framework for running LLMs across consumer hardware contains god functions alongside complex branching—orchestration code that coordinates subsystems while handling significant conditional logic. Distributed systems tooling commonly produces this signature.
NanmiCoder/MediaCrawler scores 20.5, with exit-heavy functions as the primary driver. Crawlers handle many error conditions and edge cases, but the combination with complex branching suggests the error handling has grown entangled with business logic rather than being isolated at boundaries.
zhayujie/CowAgent at 20.3 and HKUDS/nanobot at 19.6 both show patterns consistent with AI/ML tooling: complex orchestration code integrating multiple models or data sources, often written during rapid experimentation and not yet refactored for maintainability.
D4Vinci/Scrapling rounds out the top five at 18.6. The web scraping library shows complex branching and exit-heavy patterns—expected for code that must handle the structural variability of HTML across thousands of sites, but concentrated enough to signal refactoring opportunities in the parser core.
What This Means for Python Developers
The 100% prevalence of complex branching isn’t a Python language flaw—it’s a signal about how Python projects evolve. The language’s permissiveness around structure means that refactoring discipline must come from developers and teams rather than compiler enforcement. Functions that start simple accumulate conditionals as requirements expand, and without explicit complexity budgets, they cross the threshold where testing becomes guesswork.
The concentration of antipatterns in AI/ML-adjacent repositories reflects a broader trend: these domains move fast, prioritize experimentation, and often treat code as disposable. That’s reasonable during prototyping, but these are published, starred repositories that others depend on. The risk scores indicate where technical debt has accumulated to the point where the next feature or bugfix carries meaningful regression risk.
Analyze Your Own Repository
Run the same analysis on your codebase. Install the CLI with brew install Stephen-Collins-tech/tap/hotspots on macOS or cargo install hotspots-cli on any platform, then run hotspots analyze . from your repository root. The tool will identify your highest-risk functions and the specific patterns driving their scores.