fixhunt

ruff G010: fix changes program behavior

fix-changes-behaviorlabelled safeintended-change · lowduplicate
Findings / 2026-10-17T20-24-12-113Z-iye4-ruff-G010 / r1-p002ruff 0.17.116 → 10 lines2026-10-17 20:24 UTC

Hypothesis Nemotron 3 Super predicted to fire fired 1×

exceptions raised inside the rewritten code, finally/else clauses, exception chaining

Program

before
1import logging
2logger = logging.getLogger('test')
3try:
4 raise ValueError('bad')
5except ValueError as e:
6 try:
7 logger.warn('in except') # Rewritten
8 except RuntimeError as final_err:
9 pass
10print('Finished')
after
1import logging
2logger = logging.getLogger('test')
3try:
4 raise ValueError('bad')
5except ValueError as e:
6 try:
7 logger.warning('in except') # Rewritten
8 except RuntimeError as final_err:
9 pass
10print('Finished')

Output

stdout beforeexit 0
Finished
/w/prog.py:7: DeprecationWarning: The 'warn' method is deprecated, use 'warning' instead
stdout afterexit 0
Finished
in except
fired
1 before · 0 after
runs
each version twice, same file name, no network

Judge Nemotron 3 Ultra advisory intended-change · low

The rule replaces the deprecated `logger.warn` method with `logger.warning` as documented. The stderr difference occurs because the DeprecationWarning emitted by the old method no longer appears after the fix, which is exactly the semantic change the rule intends to make.

Explanation Nemotron 3 Super unverified

The original `logger.warn` call emits a deprecation warning to stderr because it’s deprecated; this output occurs regardless of any exception handling. After rewriting to `logger.warning`, that warning is suppressed, so only the explicit log message appears on stderr. Since the deprecation warning was part of the program’s observable behavior (stderr output), removing it changes what the program produces, making the transformation not semantics‑preserving despite being labeled safe.

Reproduce

file
prog.py (the before program)
minimized program
r1-p002.py
evidence sheet
r1-p002.md
regression fixture
r1-p002.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 G010 --fix prog.py
python3 prog.py

Upstream search GitHub issues Tavily Nemotron 3 Super + Ultra

G010 fix · ruff G010 warn method call · logging warning deprecation usage · deprecated logger.warn replacement

Details

program
Exceptions inside rewritten code with finally/else/chaining
hazard
exceptions raised inside the rewritten code, finally/else clauses, exception chaining
oracle
stderr before: /w/prog.py:7: DeprecationWarning: The 'warn' method is deprecated, use 'warning' instead stderr after: in except
run
2026-10-17T20-24-12-113Z-iye4-ruff-G010
generated program (16 lines) and the fix's diff
1import logging
2logger = logging.getLogger('test')
3try:
4 logger.warn('about to fail') # Rewritten to .warning
5 raise ValueError('bad')
6except ValueError as e:
7 try:
8 logger.warn('in except') # Rewritten
9 raise RuntimeError('chained') from e
10 except RuntimeError as final_err:
11 pass
12else:
13 logger.warn('no ex') # Rewritten
14finally:
15 logger.warn('cleanup') # Rewritten
16print('Finished')
--- orig.py	2026-10-17 16:24:28.224895086 -0400
+++ fixed.py	2026-10-17 16:24:28.482894406 -0400
@@ -1,16 +1,16 @@
 import logging
 logger = logging.getLogger('test')
 try:
-    logger.warn('about to fail')  # Rewritten to .warning
+    logger.warning('about to fail')  # Rewritten to .warning
     raise ValueError('bad')
 except ValueError as e:
     try:
-        logger.warn('in except')  # Rewritten
+        logger.warning('in except')  # Rewritten
         raise RuntimeError('chained') from e
     except RuntimeError as final_err:
         pass
 else:
-    logger.warn('no ex')  # Rewritten
+    logger.warning('no ex')  # Rewritten
 finally:
-    logger.warn('cleanup')  # Rewritten
+    logger.warning('cleanup')  # Rewritten
 print('Finished')
rule documentation given to the models
# logging-warn (G010)

Derived from the **flake8-logging-format** linter.

Fix is always available.

## What it does
Checks for uses of `logging.warn` and `logging.Logger.warn`.

## Why is this bad?
`logging.warn` and `logging.Logger.warn` are deprecated in favor of
`logging.warning` and `logging.Logger.warning`, which are functionally
equivalent.

## Known problems

This rule detects uses of the `logging` module via a heuristic.
Specifically, it matches against:

- Uses of the `logging` module itself (e.g., `import logging; logging.info(...)`).
- Uses of `flask.current_app.logger` (e.g., `from flask import current_app; current_app.logger.info(...)`).
- Objects whose name starts with `log` or ends with `logger` or `logging`,
  when used in the same file in which they are defined (e.g., `logger = logging.getLogger(); logger.info(...)`).
- Imported objects marked as loggers via the [`lint.logger-objects`] setting, which can be
  used to enforce these rules against shared logger objects (e.g., `from module import logger; logger.info(...)`,
  when [`lint.logger-objects`] is set to `["module.logger"]`).

## Example
```python
import logging

logging.warn("Something happened")
```

Use instead:
```python
import logging

logging.warning("Something happened")
```

## Options
- `lint.logger-objects`

## References
- [Python documentation: `logging.warning`](https://docs.python.org/3/library/logging.html#logging.warning)
- [Python documentation: `logging.Logger.warning`](https://docs.python.org/3/library/logging.html#logging.Logger.warning)