astral-sh / astral-sh/ruff

B909 misses dict.keys() deletion

Open
#16,865 3 comments 1 reaction 0 assignees View on GitHub
preview rule
Dominant language
Rust
Stars
49.6k
Forks
2.4k
Avg merge
2d 1h
Merged PRs (30d)
458

Description

### Summary

Using this file:

```python
import typing as t

d: t.Dict[str, int] = {
"a": 1,
"b": 2,
}

for key in d.keys():
del d[key]
```

When I run this command:

```
ruff check --preview --select B909 testruff.py
```

I expect to see a B909 failure, but instead all tests pass. I feel like B909 should be able to catch this, especially because running this code raises a RuntimeError:

```
RuntimeError: dictionary changed size during iteration
```

For what it's worth, `flake8-bugbear` also fails to catch this problem.

Modifying the test code to this causes Ruff to correctly point out the B909 error:

```python
import typing as t

d: t.Dict[str, int] = {
"a": 1,
"b": 2,
}

for key in d:
del d[key]
```

### Version

ruff 0.11.0 (2cd25ef64 2025-03-14)

Contributor guide

Open the contributing guide

Research direction

Start with the B909 rule and reproduce the reported command using the `d.keys()` example, then compare it with the working direct-iteration example. Done means B909 reports the unsafe deletion through `dict.keys()` and tests cover both forms.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, rust
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.