Skip to content

Add CLAUDE.md maintainability checks and fix flagged code smells - #60

Merged
aarmey merged 3 commits into
mainfrom
code-smell-cleanup
Sep 19, 2026
Merged

aarmey merged 3 commits into
mainfrom
code-smell-cleanup

Conversation

@aarmey

@aarmey aarmey commented Sep 18, 2026

Copy link
Copy Markdown
Member

Summary

  • Copies over CLAUDE.md's maintainability-check guidance from cccRISE (adapted for src/vsparse/), adding vulture, radon, and xenon to the dev dependency group and documenting how/when to run them.
  • Runs the documented dead-code (vulture), duplication (jscpd), and complexity (radon/xenon) checks against this project and fixes what they turned up:
    • Removed _VCSBase._major_range in _base.py — a dead method with no callers anywhere in the repo, including tests.
    • Extracted the repeated varint-decode loop (_ivcsc.py/_rapid_load.py) into a shared _decode_varint numba helper, reused by _unpack, _decode_chunks, and _decode_selected_rows.
    • Extracted the duplicated X/raw_X coercion logic in VCSCAnnData's setters (_anndata_class.py) into a shared _coerce_vcs helper.
  • The remaining jscpd-flagged duplication is the major-is-row / major-is-col pair of numba kernels repeated throughout _norm_common.py, _vcs_matmul.py, and _ops.py — this is an intentional, already-documented pattern for cache-friendly parallel iteration over each array's own memory layout, not a code smell, so it's left alone (consistent with CLAUDE.md's own guidance to use judgment on tools like these rather than blindly act on every flag).
  • Pre-existing functions ranked C by radon/xenon (VCSCAnnData.from_anndata, .normalized, .to_anndata, .__getitem__, .copy, load_and_normalize, _column_stats_major_is_col, NormalizedViewBase.__init__) were left as-is per CLAUDE.md's guidance, since none of them were touched by this change.

Test plan

  • uv run pytest -q — 1352 passed, 61 skipped
  • uv run ruff check src/vsparse/ — all checks passed
  • uv run vulture src/vsparse/ — remaining hits confirmed as false positives (public API exercised only from tests)
  • npx jscpd src/vsparse/ --min-lines 5 --min-tokens 50 — duplicated clones down from 17 to 14

🤖 Generated with Claude Code

aarmey and others added 3 commits September 18, 2026 08:37
Adapted from cccRISE's CLAUDE.md: adds vulture/radon/xenon to the dev
dependency group and documents how to run dead-code, duplication, and
cyclomatic-complexity checks against src/vsparse/.

Running those checks surfaced and fixed:
- _base.py: removed _VCSBase._major_range, a dead method with no callers
  anywhere in the repo (including tests).
- _ivcsc.py/_rapid_load.py: extracted the repeated varint-decode loop into
  a shared _decode_varint njit helper, reused across _unpack,
  _decode_chunks, and _decode_selected_rows.
- _anndata_class.py: extracted the duplicated X/raw_X coercion logic in
  VCSCAnnData's setters into a shared _coerce_vcs helper.

The remaining jscpd-flagged duplication is the major=row/major=col pair of
numba kernels repeated throughout _norm_common.py, _vcs_matmul.py, and
_ops.py -- an intentional, documented pattern for cache-friendly parallel
iteration over each array's own memory layout, not a code smell.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Pulls apart every plain-Python function radon/xenon ranked C (cyclomatic
complexity >= 11), all in _anndata_class.py/_norm_common.py/_rapid_load.py,
by extracting cohesive pieces into named helpers:

- _anndata_class.py: __getitem__/copy/from_anndata/to_anndata/_write_group
  shared a repeated "filter the None key, transform each value" comprehension
  -- factored into _filtered/_map_subset_1d/_map_subset_2d/_map_copy.
  normalized()'s "reuse stats stored in obs/varm/uns" branch is now
  _normalized_from_stored(). X/raw_X's setter coercion was already shared
  via _coerce_vcs (see previous commit).
- _norm_common.py: NormalizedViewBase.__init__'s VCSC/VCSR statistics
  dispatch and mean/scale finishing are now _column_gstats/_column_mean_scale.
- _rapid_load.py: load_and_normalize's obs_filter/no-filter branches (each
  with their own gene-mask logic) are now _rows_without_obs_filter/
  _rows_with_obs_filter/_compute_gene_mask; the h5py group read and the
  min_cells validation are now _read_ivcsr_group/_validate_min_cells.

All of these were plain Python orchestration -- no behavior changes, and no
numba kernels touched. The one function still ranked C,
_column_stats_major_is_col in _norm_common.py, is a numba-parallel kernel
whose branchiness is the documented, intentional cost of fusing three
statistics passes into one over each column (see its docstring) -- left
alone, consistent with CLAUDE.md's guidance not to force-fix pre-existing
complexity that reflects a deliberate performance tradeoff.

uv run pytest: 1352 passed, 61 skipped (unchanged). ruff/vulture/jscpd
results unchanged from the previous commit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wKWZn2btQ3Uo4grjuxxd2
- benchmarks/cases.py: misaligned_matmat_vs_scipy/misaligned_rmatmat_vs_scipy
  still called peak_alloc_mb() after #56 dropped that helper entirely from
  benchmarks/harness.py, so every benchmark run failed with NameError. This
  was already broken on main (confirmed: main's own CI is red for the same
  reason), not something introduced by this branch, but it blocks this PR's
  gate too. Drops the two dead peak_alloc_mb entries (case output and
  baselines.json), matching how #56 already removed the other five
  memory-metric cases.
- _ivcsc.py/_rapid_load.py: the shared _decode_varint helper from an earlier
  commit here expects a np.int64 position, but both callers seeded `pos` as
  a plain `0`, which `ty check` flagged as a real (if numba-tolerated) type
  mismatch. Seed `pos = np.int64(0)` instead.
- _rapid_load.py: the _read_ivcsr_group extraction from the same earlier
  commit gives `kwargs` an explicit `dict[str, Any]` return type, which
  resolves the invalid-argument-type ty previously needed ignore comments
  for on `ad.AnnData(**kwargs)` -- removed the two now-unused ignores.
- ruff format on the three files touched by the complexity refactor.

uv run pytest: 1352 passed, 61 skipped. uv run python -m benchmarks.run
--set fast: no regressions. ruff check/format, ty check, codespell all pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wKWZn2btQ3Uo4grjuxxd2
@aarmey
aarmey merged commit 06523a2 into main Sep 19, 2026
6 checks passed
@aarmey
aarmey deleted the code-smell-cleanup branch September 19, 2026 02:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant