redhat-et / redhat-et/ripwire

--quality-delta gates a clean tree on Python: 58 dead-code false positives for Django test hooks dispatched via cls./self.

Open
#228 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
2.1k
Forks
125
Avg merge
5h 42m
Merged PRs (30d)
136

Description

## What is wrong

On a Django monolith (~7,100 tracked files, Python), `ripwire . --quality-delta` on a **clean working tree** (identical to `git HEAD`, only untracked directories present) reports 58 gating regressions, all `kind="dead-code"`, all preexisting-worse, exit 2:

```

...
```

Two problems stacked:

1. **A no-op diff should never gate.** Working tree == HEAD, yet the baseline snapshot and the working-tree snapshot disagree on whether these symbols are dead. Whatever differs between the two parses (ordering, resolver tie-breaks, shallow-clone history) makes the exit code unreliable as a pre-commit hook on this repo. `--quality-delta=HEAD~1..HEAD` on a one-file test commit also reports 28 preexisting-worse dead-code rows in unrelated files.

2. **The symbols are not dead.** They are Django test-class hooks dispatched dynamically. A base class in `api_v2/tests/utils.py` does, inside `setUpTestData`:

```python
cls.create_test_objects()
```

and ~30 test classes each define their own `create_test_objects`. Likewise `detail_url_kwargs` is called as `self.detail_url_kwargs(...)` from base helpers and overridden per subclass. The name-based resolver sees one call site with ~30 same-language definitions in other files, declines the bind, and every override reads as unreachable. This is the Python equivalent of the C++ self-registering test macro case that `register_macros` already exempts, but there is no Python-side hook for it.

The `--callers=create_test_objects` verb reflects the same blind spot (`counts_floor="1"`, callers found only via `super().create_test_objects()` chains).

## Environment

- ripwire 0.6.0 (Release, AppleClang 16.0.0.16000026, built_from=2d2f10e62), macOS arm64
- Repo is a shallow clone (`--doctor` reports `shallow="1"`); private, so I cannot share it, but the shape is any Django project using `TestCase` subclasses with `@classmethod` hooks overridden per class.
- `--doctor`: 8 checks, 7 passed (the one failure is an unrelated stale tracked PNG).

## Reproduction shape

```python
# tests/base.py
class BaseAPITest(TestCase):
@classmethod
def setUpTestData(cls):
cls.create_test_objects() # dynamic dispatch on cls
@classmethod
def create_test_objects(cls): ...

# tests/test_a.py .. tests/test_z.py (many files)
class ATests(BaseAPITest):
@classmethod
def create_test_objects(cls): ... # reported dead
```

Run `ripwire . --quality-delta` on a clean tree. Expected: `gating="0"`. Observed: one gating dead-code row per override.

## Workaround that works

```
ripwire . --quality-delta --quality-ack="Django test hooks dispatched via cls/super" --ack-only=dead-code
```

After that, `gating="0" acked="58"`. But acking 58 findings to make a clean tree pass is a ratchet built on a false floor.

## Suggestions

- Treat a `cls.NAME()` / `self.NAME()` call site whose name has N same-language method definitions across subclasses as reaching all of them for dead-code purposes (receiver is provably an instance/class of the hierarchy). Or, cheaper: extend `.ripwire_config` with a Python analogue of `register_macros` naming method names to exempt from dead-code.
- Whatever the resolver decides, `--quality-delta` against an identical tree should be deterministic and report zero. That part looks like a bug independent of the dispatch question.

Contributor guide

Open the contributing guide

Research direction

Start by reproducing `ripwire . --quality-delta` on the clean-tree reproduction and compare the baseline and working-tree snapshots. Trace the Python resolver for `cls.NAME()` and `self.NAME()` dispatch, then inspect the `--quality-delta` path for identical-tree determinism. Done means a clean tree reports `gating="0"` and subclass-dispatched Django hooks are not reported as dead code.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, python
Domain
cli, devtools, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.