Skip to content

[pyupgrade] Add rule to replace while 1 with while True (while-one, UP048) - #27190

Merged
ntBre merged 4 commits into
astral-sh:mainfrom
Avasam:while-one-UP052
Aug 12, 2026
Merged

ntBre merged 4 commits into
astral-sh:mainfrom
Avasam:while-one-UP052

Conversation

@Avasam

@Avasam Avasam commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Summary

A very simple pyupgrade-style rule to migrate Python-2 style infinite while loops (while 1) into more idiomatic while True.

Deliberately kept this rule very simple and scoped to Python 2 code migration as per discussion in linked issue.

Closes #21870

Test Plan

  1. Look at new mdtest
  2. Look at ecosystem resulst
  3. I ran cargo run -p ruff -- check --no-cache --select=UP048 ../pywin32 (with and without fix)

Coding Agent disclaimer

Code was initially written by Claude Opus 5. Fully human reviewed.

@astral-sh-bot
astral-sh-bot Bot requested a review from ntBre July 26, 2026 04:25
@astral-sh-bot

astral-sh-bot Bot commented Jul 26, 2026

Copy link
Copy Markdown

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

ℹ️ ecosystem check detected linter changes. (+122 -0 violations, +0 -0 fixes in 6 projects; 53 projects unchanged)

freedomofpress/securedrop (+2 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --no-fix --output-format concise --preview

+ securedrop/scripts/shredder:46:15: while-one [*] Use `while True:` instead of `while 1:`
+ securedrop/scripts/source_deleter:45:15: while-one [*] Use `while True:` instead of `while 1:`

mhammond/pywin32 (+96 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --no-fix --output-format concise --preview

+ AutoDuck/InsertExternalOverviews.py:15:11: while-one [*] Use `while True:` instead of `while 1:`
+ AutoDuck/makedfromi.py:99:11: while-one [*] Use `while True:` instead of `while 1:`
+ com/win32com/client/combrowse.py:200:19: while-one [*] Use `while True:` instead of `while 1:`
+ com/win32com/client/combrowse.py:222:31: while-one [*] Use `while True:` instead of `while 1:`
+ com/win32com/client/combrowse.py:546:19: while-one [*] Use `while True:` instead of `while 1:`
+ com/win32com/client/combrowse.py:557:27: while-one [*] Use `while True:` instead of `while 1:`
+ com/win32com/client/selecttlb.py:72:11: while-one [*] Use `while True:` instead of `while 1:`
+ com/win32com/demos/dump_clipboard.py:54:23: while-one [*] Use `while True:` instead of `while 1:`
+ com/win32com/makegw/makegwparse.py:846:15: while-one [*] Use `while True:` instead of `while 1:`
+ com/win32com/makegw/makegwparse.py:922:15: while-one [*] Use `while True:` instead of `while 1:`
+ com/win32com/makegw/makegwparse.py:954:15: while-one [*] Use `while True:` instead of `while 1:`
+ com/win32com/server/policy.py:603:15: while-one [*] Use `while True:` instead of `while 1:`
+ com/win32com/server/register.py:77:19: while-one [*] Use `while True:` instead of `while 1:`
+ com/win32com/test/policySemantics.py:52:11: while-one [*] Use `while True:` instead of `while 1:`
+ com/win32com/test/testGIT.py:105:11: while-one [*] Use `while True:` instead of `while 1:`
+ com/win32com/test/testMSOfficeEvents.py:96:11: while-one [*] Use `while True:` instead of `while 1:`
+ com/win32com/test/testMarshal.py:118:15: while-one [*] Use `while True:` instead of `while 1:`
+ com/win32com/test/testvb.py:223:11: while-one [*] Use `while True:` instead of `while 1:`
+ com/win32comext/adsi/demos/search.py:87:19: while-one [*] Use `while True:` instead of `while 1:`
+ com/win32comext/axscript/client/framework.py:485:19: while-one [*] Use `while True:` instead of `while 1:`
+ com/win32comext/shell/demos/servers/shell_view.py:668:19: while-one [*] Use `while True:` instead of `while 1:`
+ com/win32comext/shell/demos/servers/shell_view.py:737:15: while-one [*] Use `while True:` instead of `while 1:`
+ isapi/samples/advanced.py:92:15: while-one [*] Use `while True:` instead of `while 1:`
+ isapi/samples/test.py:43:15: while-one [*] Use `while True:` instead of `while 1:`
+ pythonwin/pywin/debugger/debugger.py:255:15: while-one [*] Use `while True:` instead of `while 1:`
+ pythonwin/pywin/debugger/debugger.py:578:19: while-one [*] Use `while True:` instead of `while 1:`
+ pythonwin/pywin/framework/editor/document.py:353:15: while-one [*] Use `while True:` instead of `while 1:`
+ pythonwin/pywin/framework/help.py:96:15: while-one [*] Use `while True:` instead of `while 1:`
+ pythonwin/pywin/framework/toolmenu.py:201:15: while-one [*] Use `while True:` instead of `while 1:`
+ pythonwin/pywin/framework/toolmenu.py:36:11: while-one [*] Use `while True:` instead of `while 1:`
+ pythonwin/pywin/framework/toolmenu.py:58:15: while-one [*] Use `while True:` instead of `while 1:`
+ pythonwin/pywin/idle/AutoIndent.py:149:15: while-one [*] Use `while True:` instead of `while 1:`
+ pythonwin/pywin/idle/IdleHistory.py:46:15: while-one [*] Use `while True:` instead of `while 1:`
+ pythonwin/pywin/idle/PyParse.py:204:15: while-one [*] Use `while True:` instead of `while 1:`
+ pythonwin/pywin/scintilla/IDLEenvironment.py:126:15: while-one [*] Use `while True:` instead of `while 1:`
+ pythonwin/pywin/scintilla/IDLEenvironment.py:272:11: while-one [*] Use `while True:` instead of `while 1:`
+ pythonwin/pywin/scintilla/config.py:273:15: while-one [*] Use `while True:` instead of `while 1:`
+ pythonwin/pywin/scintilla/config.py:293:15: while-one [*] Use `while True:` instead of `while 1:`
+ pythonwin/pywin/scintilla/config.py:313:15: while-one [*] Use `while True:` instead of `while 1:`
... 57 additional changes omitted for project

pypa/pip (+1 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --no-fix --output-format concise --preview

+ src/pip/_internal/utils/misc.py:260:11: while-one [*] Use `while True:` instead of `while 1:`

sphinx-doc/sphinx (+17 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --no-fix --output-format concise --preview

+ sphinx/domains/c/_parser.py:511:15: while-one [*] Use `while True:` instead of `while 1:`
+ sphinx/domains/c/_parser.py:589:19: while-one [*] Use `while True:` instead of `while 1:`
+ sphinx/domains/c/_parser.py:626:15: while-one [*] Use `while True:` instead of `while 1:`
+ sphinx/domains/c/_parser.py:725:15: while-one [*] Use `while True:` instead of `while 1:`
+ sphinx/domains/c/_parser.py:792:19: while-one [*] Use `while True:` instead of `while 1:`
+ sphinx/domains/c/_parser.py:975:15: while-one [*] Use `while True:` instead of `while 1:`
+ sphinx/domains/cpp/_parser.py:1161:19: while-one [*] Use `while True:` instead of `while 1:`
+ sphinx/domains/cpp/_parser.py:1267:15: while-one [*] Use `while True:` instead of `while 1:`
+ sphinx/domains/cpp/_parser.py:1413:15: while-one [*] Use `while True:` instead of `while 1:`
+ sphinx/domains/cpp/_parser.py:1453:19: while-one [*] Use `while True:` instead of `while 1:`
... 7 additional changes omitted for project

pytest-dev/pytest (+4 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --no-fix --output-format concise --preview

+ extra/get_issues.py:16:11: while-one [*] Use `while True:` instead of `while 1:`
+ src/_pytest/_py/path.py:1458:19: while-one [*] Use `while True:` instead of `while 1:`
+ src/_pytest/_py/path.py:495:15: while-one [*] Use `while True:` instead of `while 1:`
+ src/_pytest/_py/path.py:632:19: while-one [*] Use `while True:` instead of `while 1:`

home-assistant/core (+2 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --no-fix --output-format concise --preview

+ homeassistant/components/stream/fmp4utils.py:151:11: while-one [*] Use `while True:` instead of `while 1:`
+ homeassistant/components/stream/fmp4utils.py:26:11: while-one [*] Use `while True:` instead of `while 1:`

Changes by rule (1 rules affected)

code total + violation - violation + fix - fix
while-one 122 122 0 0 0

`while 1:` is a Python 2 idiom from when `True` was a rebindable
global that had to be loaded and tested each iteration. In Python 3
both spellings compile to the same bytecode, so `while True:` is
strictly clearer.

Scoped to integer literals equal to one, including `0x1`/`0b1`/`0o1`.
Deliberately not generalized to all always-truthy conditions
(`while "always"`, `while [1]`): that would collide with rules meant
to catch accidentally-constant conditions.

The fix rewrites only the literal's range, so enclosing parentheses
and comments survive. It is safe: `True` is a keyword and cannot be
shadowed, and no runtime behavior changes.

Closes astral-sh#21870

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Avasam
Avasam force-pushed the while-one-UP052 branch from 6f5aaa5 to f147577 Compare July 26, 2026 17:30
@Avasam Avasam changed the title [pyupgrade] Replace while 1 with while True (UP048) [pyupgrade] New Rule: Replace while 1 with while True (while-one, UP048) Jul 28, 2026
@Avasam

Avasam commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

Test failure looks like a flake (failed to download a file)

@ntBre ntBre left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! This looks good to me, besides making sure it's a preview rule.

I think I previously inferred more debate over the scope of the rule from the needs-decision label, but this seems like the primary pattern to focus on.

Comment thread crates/ruff_linter/src/rules/pyupgrade/rules/while_one.rs Outdated
Comment thread crates/ruff_linter/src/codes.rs
Comment thread crates/ruff_linter/resources/mdtest/pyupgrade/while-one.md
@ntBre ntBre changed the title [pyupgrade] New Rule: Replace while 1 with while True (while-one, UP048) [pyupgrade] Add rule to replace while 1 with while True (while-one, UP048) Aug 12, 2026
@ntBre ntBre added rule Implementing or modifying a lint rule preview Related to preview mode features labels Aug 12, 2026
Avasam and others added 3 commits August 12, 2026 16:27
New rules, even simple ones, should be in preview

Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>

@ntBre ntBre left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

More GitHub pain in CI, but I'll try to get it passing and then merge.

I was also briefly worried about the new ecosystem results, but that's just from the new project you added last week :)

@Avasam

Avasam commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

that's just from the new project you added last week :)

Hehe, yeah, a nearly 30-years old project that had ton of Python 2 code.

@ntBre
ntBre merged commit a9130f3 into astral-sh:main Aug 12, 2026
74 of 77 checks passed
George-Ogden pushed a commit to George-Ogden/ruff that referenced this pull request Aug 16, 2026
…-one`, `UP048`) (astral-sh#27190)

## Summary

A very simple pyupgrade-style rule to migrate Python-2 style infinite
while loops (`while 1`) into more idiomatic `while True`.

Deliberately kept this rule very simple and scoped to Python 2 code
migration as per discussion in linked issue.

Closes astral-sh#21870

## Test Plan

1. Look at new mdtest
2. Look at ecosystem resulst
3. I ran `cargo run -p ruff -- check --no-cache --select=UP048
../pywin32` (with and without fix)

## Coding Agent disclaimer

Code was initially written by Claude Opus 5. Fully human reviewed.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

preview Related to preview mode features rule Implementing or modifying a lint rule

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Request: Rule + Autofix to upgrade while 1 Python 2 code to while True

2 participants