ruff UP005: fix changes program behavior
Hypothesis Nemotron 3 Super predicted to fire fired 1×
UP005 replacement inside list comprehension with walrus operator alters variable scope capture, causing incorrect value retention after loop.
Program
Output
(no stdout) AttributeError: 'Test' object has no attribute 'assertEquals'. Did you mean: 'assertEqual'?
(no stdout) UnboundLocalError: cannot access local variable 'x' where it is not associated with a value
- fired
- 1 before · 0 after
- runs
- each version twice, same file name, no network
Judge Nemotron 3 Ultra advisory real · high
The fix replaces the deprecated alias `assertEquals` with `assertEqual`, but the original code relied on the `AttributeError` from the missing alias to short-circuit the list comprehension and prevent the walrus-assigned variable `x` from being read before assignment. After the fix, `assertEqual` exists and returns `None`, so the comprehension proceeds and triggers an `UnboundLocalError` when accessing `x`. This is a silent change in control flow that produces a crash in plausible code.
Explanation Nemotron 3 Super unverified
The original method name assertEquals does not exist on Test instances; calling it raises AttributeError before any list comprehension executes, so x is never bound. After renaming to assertEqual, the method exists and is called during each iteration; however, assertEqual returns None (falsy) when its arguments are equal, causing the comprehension’s condition to fail and skip the walrus assignment, leaving x unbound when the result tuple is later constructed, hence UnboundLocalError. The change alters which method is invoked and thus the truth value governing the conditional, affecting whether x is assigned. This shift in control flow modifies program behavior, so the rewrite is not semantics‑preserving.
Reproduce
- file
prog.py(the before program)- minimized program
- r1-p001.py
- evidence sheet
- r1-p001.md
- regression fixture
- r1-p001.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 UP005 --fix prog.py python3 prog.py
Upstream search GitHub issues Tavily Nemotron 3 Super + Ultra
UP005 fix · UP005 assertEquals usage · unittest method name correction · walrus operator assignment expression
- related astral-sh/ruff/issues/14808 Report describes a fix for C417 that introduces a syntax error when a walrus operator is the second map argument, a different construct but same rule class (walrus in comprehensions).
- related astral-sh/ruff/issues/997 Report describes F821 false positive with walrus in all/any comprehensions, a different construct but same walrus-in-comprehension semantic analysis area.
Details
- program
- Walrus and comprehension scoping interaction
- hazard
- UP005 replacement inside list comprehension with walrus operator alters variable scope capture, causing incorrect value retention after loop.
- oracle
stderr before: AttributeError: 'Test' object has no attribute 'assertEquals'. Did you mean: 'assertEqual'? stderr after: UnboundLocalError: cannot access local variable 'x' where it is not associated with a value- run
- 2026-10-17T21-11-13-477Z-9jdd-ruff-UP005
generated program (8 lines) and the fix's diff
--- orig.py 2026-10-17 17:11:31.333194520 -0400 +++ fixed.py 2026-10-17 17:11:31.786199166 -0400 @@ -2,7 +2,7 @@ class Test(unittest.TestCase): def test(self): data = [1, 2, 3] - results = [(x := i) for i in data if self.assertEquals(x, i)] + results = [(x := i) for i in data if self.assertEqual(x, i)] print('results:', results) print('final x:', x) Test().test()
rule documentation given to the models
# deprecated-unittest-alias (UP005)
Derived from the **pyupgrade** linter.
Fix is always available.
## What it does
Checks for uses of deprecated methods from the `unittest` module.
## Why is this bad?
The `unittest` module has deprecated aliases for some of its methods.
The deprecated aliases were removed in Python 3.12. Instead of aliases,
use their non-deprecated counterparts.
## Example
```python
from unittest import TestCase
class SomeTest(TestCase):
def test_something(self):
self.assertEquals(1, 1)
```
Use instead:
```python
from unittest import TestCase
class SomeTest(TestCase):
def test_something(self):
self.assertEqual(1, 1)
```
## References
- [Python 3.11 documentation: Deprecated aliases](https://docs.python.org/3.11/library/unittest.html#deprecated-aliases)