Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.3.0] - 2026-06-27

### Added
- **`--analysis-level {1,2}`** (reintroduced): 1 is symbol table + Jedi call graph, 2 adds the PyCG call graph.
- **Coupling-aware PyCG sharding** (`--pycg-shard`) so level 2 scales to large apps. Shards are chosen by Jedi module coupling (strongly-connected-component condensation, so import cycles never split, plus Louvain community detection) instead of a flat file count, so few call edges are severed between shards. PyCG runs on each shard inside a symlink mini-project that bounds it to that shard's files. Ray-parallel.
- **Iterative decomposition of runaway shards.** PyCG's fixpoint can diverge on heavy metaclass / mixin code. A shard that hits the wall-clock timeout is re-sharded at half the budget and re-run, down to a floor (10 files). The residue that still diverges, or an atomic cycle that will not split, falls back to Jedi-only coverage. On the Odoo benchmark (1028 modules) this recovered 22210 PyCG edges versus 17149 for the best uniform ceiling, losing only 20 of 1028 files instead of a whole shard.
- **New flags**: `--pycg-shard-strategy {jedi,package}` (default `jedi`), `--pycg-shard-ceiling` (default 100, the starting per-shard budget), `--pycg-shard-timeout` (default 120, per-shard wall clock), `--pycg-max-iter` (default 50, caps PyCG fixpoint passes so a divergent shard returns a partial graph instead of hanging).

### Changed
- **BREAKING: CodeQL is replaced by PyCG as the level 2 call graph backend.** `--codeql/--no-codeql` is removed in favor of `--analysis-level`. Edge `provenance` literal `codeql` becomes `pycg`. New dependency: `pycg` (Apache 2.0). The `codeanalyzer.semantic_analysis.codeql` package is removed.

### Fixed
- The shard planner keys its module graph by file path. `PyModule.module_name` is only the file stem (every `__init__.py`, `models.py`, ...), so keying by name collided and silently dropped files from shards.
- PyCG no longer follows imports into an in-tree dependency venv (e.g. `.codeanalyzer/`) during the whole-project level 2 run: it runs in a symlink mini-project whose root holds project source only, so dependencies resolve outside the bound and stay ghost nodes.
- `_uv_bin` uses only the vendored `uv` from the `uv` PyPI dependency and no longer falls back to a `uv` on `PATH`, so the analyzer always uses the pinned binary. Returns `None` only if the package is missing, in which case callers fall back to pip.

## [0.2.1] - 2026-06-22

### Added
Expand Down
11 changes: 6 additions & 5 deletions codeanalyzer/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,15 +238,16 @@ def _get_base_interpreter() -> Path:

@staticmethod
def _uv_bin() -> Optional[str]:
"""Path to a uv binary: the one bundled with the ``uv`` PyPI package (a
dependency, so normally always present -- including inside a Docker image),
else a uv on PATH, else ``None`` (callers fall back to pip)."""
"""Path to the uv binary bundled with the ``uv`` PyPI package (a declared
dependency, so always present in our install -- including inside a Docker
image). We deliberately ignore any uv on PATH so the analyzer always uses
the pinned, vendored uv. Returns ``None`` only if the package is somehow
missing (callers fall back to pip)."""
try:
from uv import find_uv_bin

return str(find_uv_bin())
except Exception:
return shutil.which("uv")
return None

def _install_into_venv(self, venv_python: Path, args: List[str]) -> None:
"""Install packages into the target venv, preferring uv for speed (parallel
Expand Down