Skip to content

Conversation

@ntBre
Copy link
Contributor

@ntBre ntBre commented Sep 1, 2025

Summary

Release branch for Ruff 0.13.0

Breaking changes

Behavior changes

Recoded rules

Deprecated rules

Changed rules

Removed rules

Stabilized rules

New or improved fixes

Deferred stabilizations

TODOs

  • Drop empty first commit (random whitespace change to get a baseline ecosystem check executable)
  • Merge with rebase-merge (don't squash merge!!!!)

Tests

Ruff invocations on examples to verify that behavior has been stabilized correctly.
# behaviors.py

with A() as a:
    with B() as b:
        print("hello") # SIM117 safe fix


# PLE2502
another = "x؜" * 50  #    "؜x" is assigned


assert my_mock.awaited # PGH005


# COM812
type X[ 
    T, U 
] = T
def f[
    T, U
](): pass
class C[
     T, U
]: pass

# COM819
type X[T,] = T
def f[T,](): pass
class C[T,]: pass

import unittest

def func_that_will_raise():
    raise ValueError

class Tests(unittest.TestCase):
    def test_raises(self):
        self.assertRaises(Exception, func_that_will_raise)  # B017


import pytest

pytest.raises(Exception, func_that_will_raise)  # B017

def f_byte():
    raise RuntimeError(b"This is an example exception") # EM101


def f_byte_empty():
    raise RuntimeError(b"") # EM101
# rules.py

from airflow import DAG


dag = DAG(dag_id="my_dag")  # AIR002


from airflow.utils.dates import days_ago


yesterday = days_ago(today, 1)  # AIR301


from airflow.auth.managers.fab.fab_auth_manager import FabAuthManager

fab_auth_manager_app = FabAuthManager().get_fastapi_app()  # AIR302


from airflow import Dataset


Dataset(uri="test://test/")  # AIR311


from airflow.operators.python import PythonOperator


def print_context(ds=None, **kwargs):
    print(kwargs)
    print(ds)


print_the_context = PythonOperator(  # AIR312
    task_id="print_the_context", python_callable=print_context
)


import trio


async def func():
    await trio.sleep(86401)  # ASYNC116


print(bin(1337)[2:])  # FURB116


import os

os.symlink("usr/bin/python", "tmp/python", target_is_directory=False)  # PTH211


from collections.abc import Container, Iterable, Sized
from typing import Generic, TypeVar


T = TypeVar("T")


class LinkedList(Generic[T], Sized):  # PYI059
    def push(self, item: T) -> None:
        self._items.append(item)


from typing import Literal

Literal[None]  # PYI061


import pytest


with pytest.raises(Exception, match="A full sentence."):  # RUF043
    do_thing_that_raises()


def get_pair():
    return 1, 2


def foo():
    x, y = get_pair()  # RUF059
    return x


class Foo(metaclass=type): ...  # UP050
# __init__.py

# not PLC0414
import numpy as numpy
# there should be one occurrence of each of these rules without --preview
./target/release/ruff check rules.py --no-cache \
--select AIR002,AIR301,AIR302,AIR311,AIR312,ASYNC116,FURB116,PTH211,PYI059,PYI061,RUF043,RUF059,UP050 \
--target-version py312

# there should be 3 each of COM812 and COM819, 2 each of B017 and EM101, and 1
# of each of the others. There should not be any occurrences of PLC0414 in
# __init__.py.
./target/release/ruff check behaviors.py __init__.py --no-cache \
--select B017,EM101,COM812,COM819,PGH005,PLE2502,SIM117,PLC0414 \
--target-version py312

@ntBre ntBre added breaking Breaking API change release Related to the release process labels Sep 1, 2025
@ntBre ntBre changed the title TODO drop this empty commit Ruff 0.13 Sep 1, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Sep 1, 2025

ruff-ecosystem results

Linter (stable)

ℹ️ ecosystem check detected linter changes. (+4141 -22 violations, +430 -0 fixes in 29 projects; 26 projects unchanged)

DisnakeDev/disnake (+14 -0 violations, +0 -0 fixes)

+ tests/test_embeds.py:353:42: RUF043 Pattern passed to `match=` contains metacharacters but is neither escaped nor raw
+ tests/test_embeds.py:359:42: RUF043 Pattern passed to `match=` contains metacharacters but is neither escaped nor raw
+ tests/test_embeds.py:365:42: RUF043 Pattern passed to `match=` contains metacharacters but is neither escaped nor raw
+ tests/test_embeds.py:371:42: RUF043 Pattern passed to `match=` contains metacharacters but is neither escaped nor raw
+ tests/test_embeds.py:393:42: RUF043 Pattern passed to `match=` contains metacharacters but is neither escaped nor raw
+ tests/test_embeds.py:400:42: RUF043 Pattern passed to `match=` contains metacharacters but is neither escaped nor raw
+ tests/test_embeds.py:406:42: RUF043 Pattern passed to `match=` contains metacharacters but is neither escaped nor raw
+ tests/test_embeds.py:412:42: RUF043 Pattern passed to `match=` contains metacharacters but is neither escaped nor raw
+ tests/test_flags.py:163:45: RUF043 Pattern passed to `match=` contains metacharacters but is neither escaped nor raw
+ tests/test_flags.py:167:45: RUF043 Pattern passed to `match=` contains metacharacters but is neither escaped nor raw
... 4 additional changes omitted for project

RasaHQ/rasa (+49 -0 violations, +0 -0 fixes)

+ rasa/telemetry.py:594:30: RUF059 Unpacked variable `tb` is never used
+ rasa/telemetry.py:594:9: RUF059 Unpacked variable `exc_type` is never used
+ tests/cli/test_rasa_export.py:278:5: RUF059 Unpacked variable `events` is never used
+ tests/core/evaluation/test_marker.py:287:13: RUF059 Unpacked variable `expected` is never used
+ tests/core/evaluation/test_marker.py:307:13: RUF059 Unpacked variable `expected` is never used
+ tests/core/evaluation/test_marker.py:558:13: RUF059 Unpacked variable `expected_size` is never used
... 34 additional changes omitted for rule RUF059
+ tests/core/test_migrate.py:1066:30: RUF043 Pattern passed to `match=` contains metacharacters but is neither escaped nor raw
+ tests/core/test_migrate.py:1116:15: RUF043 Pattern passed to `match=` contains metacharacters but is neither escaped nor raw
+ tests/core/test_migrate.py:680:15: RUF043 Pattern passed to `match=` contains metacharacters but is neither escaped nor raw
+ tests/core/test_migrate.py:720:15: RUF043 Pattern passed to `match=` contains metacharacters but is neither escaped nor raw
... 39 additional changes omitted for project

Snowflake-Labs/snowcli (+15 -14 violations, +0 -0 fixes)

+ scripts/cleanup.py:14:1: I001 [*] Import block is un-sorted or un-formatted
- src/snowflake/cli/_plugins/connection/util.py:15:1: I001 [*] Import block is un-sorted or un-formatted
+ src/snowflake/cli/_plugins/logs/manager.py:1:1: I001 [*] Import block is un-sorted or un-formatted
+ src/snowflake/cli/_plugins/logs/utils.py:1:1: I001 [*] Import block is un-sorted or un-formatted
+ src/snowflake/cli/_plugins/nativeapp/sf_sql_facade.py:14:1: I001 [*] Import block is un-sorted or un-formatted
+ src/snowflake/cli/_plugins/spcs/compute_pool/manager.py:15:1: I001 [*] Import block is un-sorted or un-formatted
+ src/snowflake/cli/_plugins/spcs/image_repository/manager.py:15:1: I001 [*] Import block is un-sorted or un-formatted
+ src/snowflake/cli/_plugins/sql/manager.py:15:1: I001 [*] Import block is un-sorted or un-formatted
+ src/snowflake/cli/_plugins/stage/diff.py:15:1: I001 [*] Import block is un-sorted or un-formatted
+ src/snowflake/cli/_plugins/streamlit/manager.py:15:1: I001 [*] Import block is un-sorted or un-formatted
... 19 additional changes omitted for project

apache/airflow (+2794 -0 violations, +312 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --no-fix --output-format concise --no-preview --select ALL

+ airflow-core/docs/conf.py:21:1: I001 [*] Import block is un-sorted or un-formatted
+ airflow-core/src/airflow/api_fastapi/auth/managers/base_auth_manager.py:80:22: PYI059 `Generic[]` should always be the last base class
+ airflow-core/src/airflow/api_fastapi/common/exceptions.py:38:23: PYI059 `Generic[]` should always be the last base class
+ airflow-core/src/airflow/api_fastapi/core_api/base.py:52:16: PYI059 `Generic[]` should always be the last base class
+ airflow-core/src/airflow/api_fastapi/core_api/routes/public/connections.py:115:17: AIR311 `airflow.models.Connection` is removed in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
+ airflow-core/src/airflow/api_fastapi/core_api/routes/public/connections.py:125:26: AIR311 `airflow.models.Connection` is removed in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
+ airflow-core/src/airflow/api_fastapi/core_api/routes/public/connections.py:154:18: AIR311 `airflow.models.Connection` is removed in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
+ airflow-core/src/airflow/api_fastapi/core_api/routes/public/connections.py:193:17: AIR311 `airflow.models.Connection` is removed in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
+ airflow-core/src/airflow/api_fastapi/core_api/routes/public/connections.py:193:52: AIR311 `airflow.models.Connection` is removed in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
+ airflow-core/src/airflow/api_fastapi/core_api/routes/public/connections.py:232:16: AIR311 `airflow.models.Connection` is removed in Airflow 3.0; It still works in Airflow 3.0 but is expected to be removed in a future version.
... 2313 additional changes omitted for rule AIR311
+ airflow-core/src/airflow/api_fastapi/core_api/services/public/common.py:37:18: PYI059 `Generic[]` should always be the last base class
+ airflow-core/src/airflow/api_fastapi/execution_api/deps.py:140:21: RUF059 Unpacked variable `exc` is never used
- airflow-core/src/airflow/cli/commands/rotate_fernet_key_command.py:36:5: SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements
+ airflow-core/src/airflow/cli/commands/rotate_fernet_key_command.py:36:5: SIM117 [*] Use a single `with` statement with multiple contexts instead of nested `with` statements
+ airflow-core/src/airflow/configuration.py:1672:22: RUF059 Unpacked variable `source` is never used
+ airflow-core/src/airflow/configuration.py:725:25: RUF059 Unpacked variable `should_continue` is never used
+ airflow-core/src/airflow/dag_processing/manager.py:851:25: PTH211 `os.symlink` should be replaced by `Path.symlink_to`
+ airflow-core/src/airflow/dag_processing/manager.py:857:21: PTH211 `os.symlink` should be replaced by `Path.symlink_to`
+ airflow-core/src/airflow/executors/local_executor.py:223:25: RUF059 Unpacked variable `exc` is never used
+ airflow-core/src/airflow/jobs/scheduler_job_runner.py:1092:21: RUF059 Unpacked variable `sep` is never used
+ airflow-core/src/airflow/providers_manager.py:925:13: RUF059 Unpacked variable `module` is never used
... 102 additional changes omitted for rule RUF059
+ airflow-core/src/airflow/serialization/serialized_objects.py:3260:36: PYI061 [*] Use `Literal[...] | None` rather than `Literal[None, ...]` 
+ airflow-core/src/airflow/utils/log/file_processor_handler.py:127:25: PTH211 `os.symlink` should be replaced by `Path.symlink_to`
+ airflow-core/src/airflow/utils/log/file_processor_handler.py:133:21: PTH211 `os.symlink` should be replaced by `Path.symlink_to`
- airflow-core/tests/unit/always/test_secrets_local_filesystem.py:401:9: SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements
+ airflow-core/tests/unit/always/test_secrets_local_filesystem.py:401:9: SIM117 [*] Use a single `with` statement with multiple contexts instead of nested `with` statements
- airflow-core/tests/unit/always/test_secrets_local_filesystem.py:413:9: SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements
+ airflow-core/tests/unit/always/test_secrets_local_filesystem.py:413:9: SIM117 [*] Use a single `with` statement with multiple contexts instead of nested `with` statements
... 307 additional changes omitted for rule SIM117
+ airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_xcom.py:406:15: AIR002 `DAG` or `@dag` should have an explicit `schedule` argument
+ airflow-core/tests/unit/cli/commands/test_connection_command.py:744:17: RUF043 Pattern passed to `match=` contains metacharacters but is neither escaped nor raw
+ airflow-core/tests/unit/cli/commands/test_legacy_commands.py:49:19: RUF043 Pattern passed to `match=` contains metacharacters but is neither escaped nor raw
+ airflow-core/tests/unit/core/test_configuration.py:1796:23: RUF043 Pattern passed to `match=` contains metacharacters but is neither escaped nor raw
+ airflow-core/tests/unit/dag_processing/bundles/test_dag_bundle_manager.py:380:58: RUF043 Pattern passed to `match=` contains metacharacters but is neither escaped nor raw
... 3073 additional changes omitted for project

apache/superset (+19 -3 violations, +62 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --no-fix --output-format concise --no-preview --select ALL

+ scripts/check-env.py:67:24: RUF059 Unpacked variable `supported_max` is never used
+ superset/commands/report/alert.py:173:13: RUF059 Unpacked variable `executor` is never used
- superset/db_engine_specs/gsheets.py:376:9: SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements
+ superset/db_engine_specs/gsheets.py:376:9: SIM117 [*] Use a single `with` statement with multiple contexts instead of nested `with` statements
- superset/models/core.py:579:9: SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements
+ superset/models/core.py:579:9: SIM117 [*] Use a single `with` statement with multiple contexts instead of nested `with` statements
+ superset/models/core.py:770:9: RUF059 Unpacked variable `cursor` is never used
- superset/sql_lab.py:658:5: SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements
+ superset/sql_lab.py:658:5: SIM117 [*] Use a single `with` statement with multiple contexts instead of nested `with` statements
... 57 additional changes omitted for rule SIM117
+ tests/integration_tests/core_tests.py:284:21: RUF059 Unpacked variable `tests` is never used
... 74 additional changes omitted for project

binary-husky/gpt_academic (+58 -0 violations, +10 -0 fixes)

+ crazy_functions/Conversation_To_File.py:223:9: RUF059 Unpacked variable `html` is never used
+ crazy_functions/Dynamic_Function_Generate.py:195:19: RUF059 Unpacked variable `installation_advance` is never used
+ crazy_functions/Latex_Function.py:382:18: RUF059 Unpacked variable `downloaded` is never used
+ crazy_functions/Mermaid_Figure_Gen.py:327:35: RUF059 Unpacked variable `page_one` is never used
+ crazy_functions/Social_Helper.py:70:17: RUF059 Unpacked variable `err_msg` is never used
+ crazy_functions/Vectorstore_QA.py:107:5: RUF059 Unpacked variable `resp` is never used
... 53 additional changes omitted for rule RUF059
- crazy_functions/review_fns/data_sources/openalex_source.py:115:9: SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements
+ crazy_functions/review_fns/data_sources/openalex_source.py:115:9: SIM117 [*] Use a single `with` statement with multiple contexts instead of nested `with` statements
- crazy_functions/review_fns/data_sources/openalex_source.py:22:9: SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements
+ crazy_functions/review_fns/data_sources/openalex_source.py:22:9: SIM117 [*] Use a single `with` statement with multiple contexts instead of nested `with` statements
... 58 additional changes omitted for project

... Truncated remaining completed project reports due to GitHub comment length restrictions

Changes by rule (17 rules affected)

code total + violation - violation + fix - fix
AIR311 2318 2318 0 0 0
RUF059 980 980 0 0 0
RUF043 548 548 0 0 0
SIM117 430 0 0 430 0
AIR002 204 204 0 0 0
I001 36 22 14 0 0
PYI061 21 21 0 0 0
AIR301 17 17 0 0 0
PTH211 12 12 0 0 0
PYI059 10 10 0 0 0
ANN201 4 2 2 0 0
RUF100 4 0 4 0 0
AIR302 2 2 0 0 0
AIR312 2 2 0 0 0
D212 2 1 1 0 0
B017 2 2 0 0 0
UP038 1 0 1 0 0

Linter (preview)

✅ ecosystem check detected no linter changes.

Formatter (stable)

✅ ecosystem check detected no format changes.

Formatter (preview)

✅ ecosystem check detected no format changes.

@ntBre ntBre added this to the v0.13 milestone Sep 3, 2025
@ntBre ntBre marked this pull request as ready for review September 8, 2025 17:17
@ntBre ntBre requested a review from AlexWaygood as a code owner September 8, 2025 17:17
Copy link
Contributor

@Lee-W Lee-W left a comment

Choose a reason for hiding this comment

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

took a look at the airflow part again. Looks goo!

ntBre and others added 16 commits September 10, 2025 08:40
The tests looked good. For the docs, I added a `## See also` section
pointing to
the closely-related F841 (unused-variable) and the corresponding section
to F841
pointing back to RUF059. It seems like you'd probably want both of these
active
or at least to know about the other when reading the docs.
Summary
--

Rule and test/snapshot updated, the docs look good

My one hesitation here is that we could hold off stabilizing the rule
until its fix is also ready for stabilization, but this is also the only
preview PTH rule, so I think it's okay to stabilize the rule and later
(probably in the next minor release) stabilize the fixes together.
Tests and docs look good

We nearly stabilized this last time
(#18601), but it needed one more
bug fix and a documentation improvement
(#18611)
## Summary
In #11115 we moved from defaulting to $HOME/Library/Application Support
to $XDG_HOME on macOS and added a deprecation warning if we find files
in the old location. So this PR removes the warning
closes #19145 

## Test Plan
Ran `cargo test`
## Summary
closes #7710 

## Test Plan

It is is removal so i don't think we have to add tests otherwise i have
followed test plan mentioned in contributing.md

---------

Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
## Summary
This PR Removes deprecated UP038 as per instructed in #18727 
closes #18727 
## Test Plan
I have run tests non of them failing 

One Question i have is do we have to document that UP038 is removed?

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
This one has been a bit contentious in the past. It usually uncovers
~700 ecosystem hits. See:

- #16657
- #16690

But I think there's consensus that it's okay to merge as-is. We'd love
an
autofix since it's so common, but we can't reliably tell what a user
meant. The
pattern is ambiguous after all 😆

This is the first rule that actually needed its test case relocated, but
the
docs looked good.
…` (`SIM117`) (#20270)

Introduced in #18208. Removed gating, updated tests and docs.
…02`) (#20276)

Introduced in #20106. Removed gating. Updated tests. No documentation to
update.
…` (`PLC0414`) (#20271)

Stabilizes change from #18400. Removed gating, updated docs, updated
tests.
This stabilizes the behavior introduced in #16565 which (roughly) tries
to match an import like `import a.b.c` to an actual directory path
`a/b/c` in order to label it as first-party, rather than simply looking
for a directory `a`.

Mainly this affects the sorting of imports in the presence of namespace
packages, but a few other rules are affected as well.
…access` (`PGH005`) (#20272)

Introduced in #18547. Removed gating, updated tests. Not documented so
documentation is the same.
dylwil3 and others added 6 commits September 10, 2025 08:40
… parameter lists (`COM812`, `COM819`) (#20275)

Introduced in #19390. Removed gating, updated tests. No documentation to
update.
… `assert-raises-exception` (`B017`) (#20274)

Introduced in #19063. Removed gating, updated tests. Not documented so
docs are the same.
- **Stabilize `airflow3-suggested-update` (`AIR311`)**
- **Stabilize `airflow3-suggested-to-move-to-provider` (`AIR312`)**
- **Stabilize `airflow3-removal` (`AIR301`)**
- **Stabilize `airflow3-moved-to-provider` (`AIR302`)**
- **Stabilize `airflow-dag-no-schedule-argument` (`AIR002`)**

I put this all in one PR to make it easier to double check with @Lee-W
before we merge this. I also made a few minor documentation changes and
updated one error message that I want to make sure are okay. But for the
most part this just moves the rules from `RuleGroup::Preview` to
`RuleGroup::Stable`!

Fixes #17749
…01`) to support byte strings (#20273)

Introduced in #18867. Removed gating, updated tests, updated docs.
Introduced in #19100. Removed gating, updated tests, removed warning(s),
and updated documentation.
<!--
Thank you for contributing to Ruff/ty! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title? (Please prefix
with `[ty]` for ty pull
  requests.)
- Does this pull request include references to any relevant issues?
-->

## Summary

Closes #18349

After this change:
- All deprecated rules are deselected by default
- They are only selected if the user specifically selects them by code,
e.g. `--select UP038`
- Thus, `--select ALL --select UP --select UP0` won't select the
deprecated rule UP038
- Documented the change in version policy. From now on, deprecating a
rule should increase the minor version

## Test Plan

Integration tests in "integration_tests.rs"

Also tested with a temporary test package:
```
~> ../../ruff/target/debug/ruff.exe check --select UP038
warning: Rule `UP038` is deprecated and will be removed in a future release.
warning: Detected debug build without --no-cache.
UP038 Use `X | Y` in `isinstance` call instead of `(X, Y)`
 --> main.py:2:11
  |
1 | def main():
2 |     print(isinstance(25, (str, int)))
  |           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
help: Convert to `X | Y`

Found 1 error.
No fixes available (1 hidden fix can be enabled with the `--unsafe-fixes` option).

~> ../../ruff/target/debug/ruff.exe check --select UP03
warning: Detected debug build without --no-cache.
All checks passed!

~> ../../ruff/target/debug/ruff.exe check --select UP0
warning: Detected debug build without --no-cache.
All checks passed!

~> ../../ruff/target/debug/ruff.exe check --select UP
warning: Detected debug build without --no-cache.
All checks passed!

~> ../../ruff/target/debug/ruff.exe check --select ALL
# warnings and errors, but because of other errors, UP038 was deselected
```
@ntBre ntBre merged commit 7a75702 into main Sep 10, 2025
35 checks passed
@ntBre ntBre deleted the brent/0.13.0 branch September 10, 2025 13:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking Breaking API change release Related to the release process

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants