Python Code Review with LGTM
AI code review for Python: LGTM catches mutable-default-argument bugs, missing await on coroutines, missing type hints on public APIs, unsafe subprocess, and SQL injection — with full repo context.
How LGTM reviews Python PRs
Tree-sitter parses every .py file in the repo at index time, extracting module-level functions, classes, methods, decorated handlers, and imports. The indexer respects __init__.py re-exports and follows the import graph so the 'who calls this?' lookup works across packages.
Per-PR review: the diff plus the 5-15 highest PageRank-ranked symbols (called functions, referenced types, imported modules) get attached to each agent's prompt. The Bugs agent for Python looks specifically at: mutable default args, missing `await`, exception swallowing (bare `except:`), unclosed file handles, integer division surprises (`/` vs `//`), and missing type hints on public APIs in repos that use them elsewhere.
Python's flexibility means a lot of patterns are 'maybe a bug' depending on intent. The agent flags with calibrated confidence — high confidence for unambiguous bugs (mutable defaults, missing await), lower confidence for stylistic concerns that get rolled into the summary rather than inline.
Common Python bugs LGTM catches
Mutable default arguments. `def append_item(item, items=[]):` — items is shared across all calls. Classic, hard to spot in review, the Bugs agent catches every instance.
Missing await on async calls. `async def save(): db.write(data)` — the coroutine is never awaited and runs as fire-and-forget. The agent detects async function definitions and verifies their bodies await coroutines they call.
Bare exception clauses. `except:` or `except Exception:` swallowing too much. The Security agent flags these as masking real failures including keyboard interrupts.
SQL injection via string formatting. `cursor.execute(f"SELECT * FROM users WHERE id={user_id}")` — even with int casts the pattern is risky. Recommends parameterized queries.
subprocess shell=True with user input. `subprocess.run(cmd, shell=True)` where cmd contains user-supplied content — flagged as command injection risk.
Type hints inconsistency. Repo uses type hints in 80% of files; a new PR adds untyped public API. The Best-Practices agent surfaces this only when the convention is already established elsewhere — not on repos without hints.
Tree-sitter coverage for Python
Python's tree-sitter grammar is solid for Python 3 (3.6+). Type hints (PEP 484, PEP 526), f-strings, async/await, dataclasses, match statements (3.10+), walrus operator — all parse cleanly.
Python 2 is supported but the symbol extractor is tuned for Python 3 patterns. If you're still on 2.x (heroic at this point), reviews work but the type-hint-aware checks won't apply.
Notebooks (.ipynb) are NOT indexed — they're JSON wrapping Python, not Python files. If you do notebook-heavy work, the review applies to non-notebook code only. Adding notebook support is on the roadmap.
Setup notes for Python projects
Install the LGTM GitHub App on the repo. Index time: 20-60 seconds for typical Django/FastAPI projects, longer for monorepos.
Virtual env / package manager: LGTM doesn't run your code, doesn't execute pytest, doesn't need access to your venv. The review is fully static — tree-sitter parsing + LLM reasoning over the parsed structure. Pip / Poetry / uv / conda — all treated the same.
Django specifics: signals.py, admin.py, models.py get indexed with awareness of Django patterns. Migrations are auto-excluded from review (they're auto-generated). Models with `Meta` classes, querysets, and serializers all parse cleanly.
FastAPI / Flask specifics: route decorators surface as symbols. The agents reason about request/response handling, dependency injection, and Pydantic schemas.
Example bugs LGTM catches
# ❌ Bug: items is shared across calls
def add_user(name, items=[]):
items.append(name)
return items
print(add_user('alice')) # ['alice']
print(add_user('bob')) # ['alice', 'bob'] <-- !!
# LGTM finding:
# "Mutable default argument 'items=[]' is created once at
# function definition, shared across all calls. Replace
# with 'items=None' and 'if items is None: items = []'."# ❌ Bug: coroutine runs fire-and-forget
async def save_user(user):
db.write(user) # <-- not awaited
await save_user(alice) # returns immediately, write may not complete
# LGTM finding:
# "db.write(user) returns a coroutine. Missing 'await'.
# This coroutine will never run unless awaited."See LGTM's code review pipeline
Python-aware · BYOK · static-only · no code execution
Go to the product pagePython review FAQs
Does LGTM review Jupyter notebooks?
Not yet. Notebooks (.ipynb) are JSON wrapping Python, not Python files. Tree-sitter parses .py only. Notebook support is on the roadmap; for now, reviews apply to the non-notebook code in your repo.
What about Python 2?
Tree-sitter parses 2.x syntax fine, but our agents are tuned for Python 3 patterns. Reviews work; type-hint checks won't apply. If you're maintaining a 2.x codebase, the review value is somewhat reduced but still meaningful.
Does LGTM run pytest or any execution?
No. Reviews are fully static — tree-sitter parses, agents reason about the parsed structure. No code execution, no test running, no venv access. Faster and safer than CI-integrated review tools.
Django + DRF + FastAPI — all supported equally?
Yes. Each framework's idioms (Django models, DRF serializers, FastAPI routes + Pydantic schemas) get parsed correctly. The agents have light awareness of framework patterns — e.g., Django QuerySet.filter() is recognised as ORM rather than method call.
Cost per Python PR review?
About $0.05-$0.12 for a 300-line PR on GPT-4o (via your BYOK key). Switch to Haiku or Mini and it drops to ~$0.01. LGTM's flat fee (₹399/mo Pro or free 20/mo) covers orchestration; tokens are your provider cost.
Related across LGTM
AI code review explained
What multi-agent AI review means for Python codebases.
LLM pipeline explained
End-to-end webhook → agents → review for Python PRs.
Pre-push CLI review
Catch Python bugs locally with the lgtm CLI before push.
BYOK on Anthropic
Claude Opus for Python security; Sonnet / Haiku for cheaper agents.
Other languages
TypeScript
AI code review for TypeScript: LGTM catches type-narrowing bugs, unsafe assertions, async race conditions, React stale-closure bugs, and unused exports — across the diff and the wider repo context.
Go
AI code review for Go: LGTM catches ignored errors, shadowed variables in if-bodies, goroutine leaks, missing context.Context plumbing, unsafe nil-pointer derefs, and missing defer cleanup.
Ruby
AI code review for Ruby: LGTM catches N+1 query patterns, dangerous send + eval calls, missing strong-params on Rails controllers, monkey-patch surprises, and unsafe deserialization.
JavaScript
AI code review for JavaScript: LGTM catches == vs === bugs, missing await on Promises, unhandled rejections, and event-listener cleanup leaks.