# ruff UP005: fix changes program behavior

Internal evidence sheet generated by fixhunt. Not an issue text. A human re-verifies, checks the duplicates
below, and writes the upstream report in their own words following the project's AI policy.

- Tool: ruff ruff 0.17.1
- Rule: UP005 (tool labels the fix: unknown, this fix reported as safe)
- Oracle: fix-changes-behavior
- Judge (Nemotron 3 Ultra, advisory): real, severity 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.
- Program: minimized from 8 to 6 lines

## Reproducer

```python
import unittest
class Test(unittest.TestCase):
    def test(self):
        data = [1, 2, 3]
        results = [(x := i) for i in data if self.assertEquals(x, i)]
Test().test()
```

## Commands

```sh
python3 prog.py
ruff check --preview --isolated --select UP005 --fix prog.py
python3 prog.py
```

## Observed

```
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
```

## Diff applied by the fix

```diff
--- orig.py	2026-10-22 13:37:22.316983411 -0400
+++ fixed.py	2026-10-22 13:37:25.390035361 -0400
@@ -2,5 +2,5 @@
 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)]
 Test().test()
```

## Why the rewrite is not equivalent (model draft, verify before use)

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.

## Upstream search

Queries: "UP005 fix", "UP005 assertEquals usage", "unittest method name correction", "walrus operator assignment expression"

- related: https://github.com/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: https://github.com/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><summary>All hits</summary>

- [github, closed] unused-function-argument not silenced by prefixed underscore if variable name is "次" — https://github.com/astral-sh/ruff/issues/28721
- [github, closed] Formatter: Bug with Pragma Comment for pyright being moved to invalid position — https://github.com/astral-sh/ruff/issues/8481
- [github, closed] Fixed code unformatted — https://github.com/astral-sh/ruff/issues/8619
- [github, closed] Add option to disable preview warnings — https://github.com/astral-sh/ruff/issues/8620
- [github, closed] Implement pyupgrade — https://github.com/astral-sh/ruff/issues/827
- [github, open] Implement flake8-walrus — https://github.com/astral-sh/ruff/issues/3464
- [github, open] Formatter: long walrus operator expression introduces parentheses  — https://github.com/astral-sh/ruff/issues/8546
- [github, open] Ruleset Suggestion: wemake-python-styleguide — https://github.com/astral-sh/ruff/issues/3845
- [github, open] Feature: Port Sonar's Python scanner checks — https://github.com/astral-sh/ruff/issues/4935
- [github, closed] Emit diagnostics for new syntax as per the target Python version — https://github.com/astral-sh/ruff/issues/6591
- [github, closed] [Fix error] C417 and walrus statements — https://github.com/astral-sh/ruff/issues/14808
- [github, closed] Red knot panics checking some named expressions — https://github.com/astral-sh/ruff/issues/13012
- [github, closed] Format assignment expressions (`FormatExprNamedExpr`) — https://github.com/astral-sh/ruff/issues/5613
- [github, closed] F821 (Undefined name) triggered when using assingment operator in all — https://github.com/astral-sh/ruff/issues/997

</details>
