diff --git a/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP036_5.py b/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP036_5.py index c7e1a8778d..697c84a804 100644 --- a/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP036_5.py +++ b/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP036_5.py @@ -28,3 +28,46 @@ else: else: print(3) return None + + +# https://github.com/astral-sh/ruff/issues/16082 + +## Errors +if sys.version_info < (3, 12, 0): + print() + +if sys.version_info <= (3, 12, 0): + print() + +if sys.version_info < (3, 12, 11): + print() + +if sys.version_info < (3, 13, 0): + print() + +if sys.version_info <= (3, 13, 100000): + print() + + +## No errors + +if sys.version_info <= (3, 13, foo): + print() + +if sys.version_info <= (3, 13, 'final'): + print() + +if sys.version_info <= (3, 13, 0): + print() + +if sys.version_info < (3, 13, 37): + print() + +if sys.version_info <= (3, 13, 37): + print() + +if sys.version_info <= (3, 14, 0): + print() + +if sys.version_info <= (3, 14, 15): + print() diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/outdated_version_block.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/outdated_version_block.rs index 37b1c7a859..8bf187a6cc 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/outdated_version_block.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/outdated_version_block.rs @@ -236,14 +236,27 @@ fn version_always_less_than( return Err(anyhow::anyhow!("invalid minor version: {if_minor}")); }; + let if_micro = match check_version_iter.next() { + None => None, + Some(micro) => match micro.as_u8() { + Some(micro) => Some(micro), + None => anyhow::bail!("invalid micro version: {micro}"), + }, + }; + Ok(if or_equal { // Ex) `sys.version_info <= 3.8`. If Python 3.8 is the minimum supported version, // the condition won't always evaluate to `false`, so we want to return `false`. if_minor < py_minor } else { - // Ex) `sys.version_info < 3.8`. If Python 3.8 is the minimum supported version, - // the condition _will_ always evaluate to `false`, so we want to return `true`. - if_minor <= py_minor + if let Some(if_micro) = if_micro { + // Ex) `sys.version_info < 3.8.3` + if_minor < py_minor || if_minor == py_minor && if_micro == 0 + } else { + // Ex) `sys.version_info < 3.8`. If Python 3.8 is the minimum supported version, + // the condition _will_ always evaluate to `false`, so we want to return `true`. + if_minor <= py_minor + } }) } } diff --git a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP036_5.py.snap b/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP036_5.py.snap index 478ed274d9..efd113261f 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP036_5.py.snap +++ b/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP036_5.py.snap @@ -66,3 +66,94 @@ UP036_5.py:18:4: UP036 [*] Version block is outdated for minimum Python version 23 |+ else: 24 |+ print(3) 25 |+ return None +31 26 | +32 27 | +33 28 | # https://github.com/astral-sh/ruff/issues/16082 + +UP036_5.py:36:4: UP036 [*] Version block is outdated for minimum Python version + | +35 | ## Errors +36 | if sys.version_info < (3, 12, 0): + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP036 +37 | print() + | + = help: Remove outdated version block + +ℹ Unsafe fix +33 33 | # https://github.com/astral-sh/ruff/issues/16082 +34 34 | +35 35 | ## Errors +36 |-if sys.version_info < (3, 12, 0): +37 |- print() +38 36 | +39 37 | if sys.version_info <= (3, 12, 0): +40 38 | print() + +UP036_5.py:39:4: UP036 [*] Version block is outdated for minimum Python version + | +37 | print() +38 | +39 | if sys.version_info <= (3, 12, 0): + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP036 +40 | print() + | + = help: Remove outdated version block + +ℹ Unsafe fix +36 36 | if sys.version_info < (3, 12, 0): +37 37 | print() +38 38 | +39 |-if sys.version_info <= (3, 12, 0): +40 |- print() +41 39 | +42 40 | if sys.version_info < (3, 12, 11): +43 41 | print() + +UP036_5.py:42:4: UP036 [*] Version block is outdated for minimum Python version + | +40 | print() +41 | +42 | if sys.version_info < (3, 12, 11): + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP036 +43 | print() + | + = help: Remove outdated version block + +ℹ Unsafe fix +39 39 | if sys.version_info <= (3, 12, 0): +40 40 | print() +41 41 | +42 |-if sys.version_info < (3, 12, 11): +43 |- print() +44 42 | +45 43 | if sys.version_info < (3, 13, 0): +46 44 | print() + +UP036_5.py:45:4: UP036 [*] Version block is outdated for minimum Python version + | +43 | print() +44 | +45 | if sys.version_info < (3, 13, 0): + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP036 +46 | print() + | + = help: Remove outdated version block + +ℹ Unsafe fix +42 42 | if sys.version_info < (3, 12, 11): +43 43 | print() +44 44 | +45 |-if sys.version_info < (3, 13, 0): +46 |- print() +47 45 | +48 46 | if sys.version_info <= (3, 13, 100000): +49 47 | print() + +UP036_5.py:48:24: UP036 Version specifier is invalid + | +46 | print() +47 | +48 | if sys.version_info <= (3, 13, 100000): + | ^^^^^^^^^^^^^^^ UP036 +49 | print() + |