ruff RUF019: fix changes program behavior
Hypothesis Nemotron 3 Super predicted to fire fired 1×
8. If d is a subclass of dict that overrides __contains__ or __getitem__ with side effects, the fix may alter behavior.
Program
Output
__contains__(x)
condition passed
- fired
- 1 before · 0 after
- runs
- each version twice, same file name, no network
Judge Nemotron 3 Ultra advisory real · high
The rule replaces an explicit key check (`'x' in d`) followed by access (`d['x']`) with a single `d.get('x')` call. In this program, the dictionary subclass overrides `__contains__` to produce a side effect (printing). The original code invokes `__contains__`, so the side effect occurs; the rewritten code calls `get`, which does not invoke `__contains__`, so the side effect is lost and the program's observable behavior changes silently.
Explanation Nemotron 3 Super unverified
The original condition evaluates `'x' in d` first, which triggers `__contains__`, printing '__contains__(x)'. Since this returns True, it then checks `d['x']`, retrieving the value 1 (truthy), so the message prints. The rewrite replaces both with `d.get('x')`, which directly fetches the value without calling `__contains__`. Thus, no print occurs, and only 'condition passed' appears—altering observable behavior. This change is unsafe because `__contains__` may have side effects beyond membership testing, which the fix ignores. The transformation assumes equivalence that does not hold when `__contains__` is overridden.
Reproduce
- file
prog.py(the before program)- minimized program
- r2-p008.py
- evidence sheet
- r2-p008.md
- regression fixture
- r2-p008.py the minimized program with a header stating the observed change, for the tool's test suite
python3 prog.py ruff check --preview --isolated --select RUF019 --fix prog.py python3 prog.py
Upstream search GitHub issues Tavily Nemotron 3 Super + Ultra
RUF019 fix · RUF019 dict get truthiness · LoggingDict contains method call · in operator replaced with get
- related astral-sh/ruff/issues/14011 same rule RUF019 but different construct (general false positives vs side-effectful __contains__)
- related astral-sh/ruff/issues/12953 same rule RUF019 and same root cause (contains_effect missing side-effects)
Details
- program
- Dict subclass overriding __contains__ and __getitem__ with side effects
- hazard
- 8. If d is a subclass of dict that overrides __contains__ or __getitem__ with side effects, the fix may alter behavior.
- oracle
stdout before: __contains__(x) stdout after: condition passed- run
- 2026-10-17T21-39-23-080Z-ah8u-ruff-RUF019
generated program (10 lines) and the fix's diff
--- orig.py 2026-10-17 17:39:47.030436187 -0400 +++ fixed.py 2026-10-17 17:39:47.188434854 -0400 @@ -6,5 +6,5 @@ print(f'__getitem__({key})') return super().__getitem__(key) d = LoggingDict({'x': 1}) -if 'x' in d and d['x']: +if d.get('x'): print('condition passed')
rule documentation given to the models
# unnecessary-key-check (RUF019)
Derived from the **Ruff-specific rules** linter.
Fix is always available.
## What it does
Checks for unnecessary key checks prior to accessing a dictionary.
## Why is this bad?
When working with dictionaries, the `get` can be used to access a value
without having to check if the dictionary contains the relevant key,
returning `None` if the key is not present.
## Example
```python
if "key" in dct and dct["key"]:
...
```
Use instead:
```python
if dct.get("key"):
...
```
## Fix safety
This rule's fix is marked as safe, unless the expression contains comments
or may have side effects.