chore: update Python dependencies (uv.lock) (14 updates) #6

Merged
Wuast94 merged 2 commits from updatarr/python-dependencies--uv.lock-bbfe89acc5 into main 2026-09-28 22:33:52 +02:00
Owner

Updates Python dependencies (uv.lock).

Breaking change detected. Review the release notes before merging.

Automerge: Disabled because breaking change release notes were detected

Updates

Dependency From To Type Locations
aiohappyeyeballs 2.6.1 2.7.1 minor [1] L19
aiohttp 3.13.3 3.14.3 minor [1] L28
anyio 4.14.2 4.15.1 minor [1] L103
attrs 25.4.0 26.1.0 major [1] L115
idna 3.11 3.20 minor [1] L265
multidict 6.7.0 6.9.1 minor; breaking [1] L283
packaging 25.0 26.3 major [1] L328
propcache 0.4.1 0.5.4 minor; breaking [1] L364
pygments 2.19.2 2.21.0 minor [1] L447
pyrefly 1.2.0 1.3.1 minor [1] L497
ruff 0.14.11 0.16.9 minor; breaking [1] L556
typing-extensions current version 4.16.0 unknown [1]
watchfiles 1.2.0 1.3.0 minor [1] L618
yarl 1.22.0 1.25.1 minor [1] L665

Files

  • [1] uv.lock

Release notes

aiohappyeyeballs (2.6.1 → 2.7.1)

2.6.2: v2.6.2

Compare source

Source

Source ref: main

v2.6.2 (2026-05-20)

Bug Fixes

  • Clear error on empty addr_infos in start_connection (#222, 55dd76a)

Refactoring

  • Optimize obtaining event-loop down to 1 line (#185, 02a7029)

Testing

  • Stop verify_no_lingering_tasks from leaking an event loop (#221, ce43beb)

Detailed Changes: v2.6.1...v2.6.2

v2.7.0: v2.7.0

Compare source

Source

Source ref: main

v2.7.0 (2026-05-20)

Features


Detailed Changes: v2.6.2...v2.7.0

2.7.1: v2.7.1

Compare source

Source

Source ref: main

v2.7.1 (2026-07-01)

Performance Improvements

  • Use defaultdict to help with performance (#239, e10f335)

Refactoring

  • Collapse collect-then-remove pattern in utils helpers (#227, 0dd3fd1)

  • Merge identical except blocks in _connect_sock cleanup (#229, b7c186e)

  • Simplify _interleave_addrinfos family grouping (#226, fdf6548)


Detailed Changes: v2.7.0...v2.7.1

aiohttp (3.13.3 → 3.14.3)

Source comparison unavailable: source refs for this transition are not known.

3.13.4

3.13.5

3.14.0

3.14.1

3.14.2

3.14.3

anyio (4.14.2 → 4.15.1)

4.15.0: 4.15.0

Compare source

Source

Source ref: master

  • Added support for the newer keyword-only arguments on anyio.Path methods to match the standard library pathlib.Path:

    • follow_symlinks on exists() (Python 3.12+)
    • follow_symlinks on is_dir() (Python 3.13+)
    • follow_symlinks on is_file() (Python 3.13+)
    • follow_symlinks on owner() (Python 3.13+)
    • follow_symlinks on group() (Python 3.13+)
    • newline on read_text() (Python 3.13+)

    (#1286, #1293; PR by @jaideeppyne)

  • Added amap, gather, and as_completed utility functions to simplify common patterns (#1173; PR by @Graeme22)

  • Added --anyio-mode command-line option as an alternative to the anyio_mode ini setting, and fix the pytest plugin's auto mode detection to recognize the mode when set via either mechanism(e.g: pytest_asyncio). (#1242; PR by @EmmanuelNiyonshuti)

  • Added the anyio.Future synchronization primitive which behaves similar to asyncio.Future, allowing tasks to wait for a value (or exception) from another task (#1146; PR by @Vizonex)

  • Added guidance for managing multiple memory object stream producers and consumers with cloned streams (#330; PR by @nightcityblade)

  • Added StapledObjectStream.send_nowait() that delegates to the underlying ObjectSendStream, if it implements it (#1241; PR by @davidbrochart)

  • Added the move_on_at() and fail_at() functions to complement move_on_after() and fail_after()

  • Changed the default name for a task spawned with TaskGroup.create_task(func()) to match the default task name for the analogous task spawned with TaskGroup.start_soon(func) or TaskGroup.start(func) in more situations. Previously, the default name of a TaskGroup.create_task task never included the module name. (The default name for a task spawned with TaskGroup.start_soon or TaskGroup.start typically includes the module name.) (#1234; PR by @gschaffner)

  • Changed the anyio and anyio.abc modules to lazily (much like 810) import the necessary submodules. This is done by parsing the AST of the module and building a lookup table from the if TYPE_CHECKING: block. A fallback mode has been provided for installations where the source code is unavailable (e.g. PyInstaller). (#1169)

  • Fixed free-threading compatibility issues arising from the fact that on Python 3.14 free-threading builds, newly created threads inherit the current context by default, causing AnyIO to behave erroneously in relation to start_blocking_portal() and anyio.to_thread.run_sync() (#1224; PR by @EmmanuelNiyonshuti)

  • Fixed SpooledTemporaryFile.readinto() and readinto1() reading twice before rollover, so the destination buffer was overwritten by the second read and the file position advanced twice, silently losing data (#1215; PR by @c-tonneslan)

  • Added a reason parameter to fail_after (and the new fail_at) allowing for added exception context when raising TimeoutError (#1227; PR by @Graeme22)

  • Fixed the default TaskHandle.name missing part of the task name for tasks started with TaskGroup.start on Trio (#1231; PR by @gschaffner)

  • Fixed anyio.run leaking, or at least, delaying collection of loop and root_task due to the root task being cached in a RunVar. (#1203; PR by @tapetersen)

  • Fixed anyio.Path.with_stem() silently producing a wrong path (e.g. Path(".txt")) instead of raising ValueError when given an empty stem on a path with a non-empty suffix, unlike pathlib.PurePath.with_stem (#1200; PR by @Sanjays2402)

  • Fixed UNIXSocketStream.aclose() raising asyncio.InvalidStateError when a concurrent receive or send operation had just been cancelled on the asyncio backend (#1267; PR by @alloutflo)

  • Fixed the pytest plugin importing the deprecated _pytest.python.CallSpec2 alias, which triggers PytestRemovedIn10Warning on pytest>=9.2 and crashes pytest at startup when filterwarnings = error is configured (#1271; PR by @matthewfeickert)

  • Fixed an asyncio worker thread race that could raise RuntimeError when the event loop closed between checking its state and scheduling the worker result (#1265; PR by @hansu650)

  • Fixed CapacityLimiter on the asyncio backend over-granting tokens when total_tokens was raised while the limiter was over-subscribed (#1223; PR by @zelinewang)

  • Fixed asyncio task groups leaking unawaited coroutines when a custom task constructor fails; default task creation is unaffected (#1274; PR by @dsfaccini)

  • Fixed inconsistencies between Trio and asyncio when target TaskGroup is cancelled before a task created with .start() calls TaskStatus.started()

    • The started task shouldn't get a CancelledError until the first checkpoint after the started() call.
    • A value passed to started() should be available on the TaskHandle and correctly passed back to the caller of start even if cancelled.
    • The CancelledError shouldn't leak out of the TaskGroup.start() call to the calling task.

    (#1197; PR by @tapetersen)

  • Fixed TemporaryDirectory not cleaning up when the host task was cancelled while exiting the context manager, as the cleanup now runs in a shielded cancel scope (#1304; PR by @smurfix)

4.15.1: 4.15.1

Compare source

Source

Source ref: master

attrs (25.4.0 → 26.1.0)

26.1.0

idna (3.11 → 3.20)

3.12

Compare source

Source

Source ref: master

3.13

Compare source

Source

Source ref: master

3.14

Compare source

Source

Source ref: master

3.15

Compare source

Source

Source ref: master

3.16

Compare source

Source

Source ref: master

3.17

Compare source

Source

Source ref: master

3.18

Compare source

Source

Source ref: master

3.19

Compare source

Source

Source ref: master

  • Restore the std3_rules option, which had no effect since changes
    to UTS #46 processing in Unicode 16. Note that uts46_remap()
    defaults to enabling STD3 rules, so direct callers will see input
    containing non-LDH ASCII characters rejected again.
  • Performance improvements to UTS #46 mapping, particularly for
    ASCII-only domains.
  • Test on free-threaded CPython with the GIL disabled and document
    thread safety.
  • Expose the Unicode version of the generated tables as
    idna.unicode_version, and show it in idna --version.
  • Add code, text, codepoint and position attributes to
    IDNAError so that the failed rule and the offending character can
    be identified without parsing the exception message.
  • The deprecated transitional argument to encode() and
    uts46_remap() is now completely ignored, and gives a deprecation warning
    for the latter.
  • Reject A-labels that are not the canonical Punycode encoding of
    their U-label.
  • Fix CONTEXTJ violations raising IDNAError instead of
    InvalidCodepointContext.
  • Consistently raise IDNAError for empty labels and non-ASCII bytes
    passed to label helper functions and the incremental codec.
  • Add property-based tests, extended fuzzing targets, coverage
    measurement, and CI checks that the data tables match the generator
    output.
  • Various code quality and tooling improvements.

Thanks to stefan6419846, LouieLuNZ, and Salvatore Corvaglia for
contributions to this release.

3.20

Compare source

Source

Source ref: master

  • Update to Unicode 18.0.0.
  • Better enforcement of the domain length limit in the incremental
    codec.
  • Add support for Python 3.15.
multidict (6.7.0 → 6.9.1)

6.7.1: 6.7.1

Compare source

Source

Source ref: master

Bug fixes

  • Fixed slow memory leak caused by identity by adding Py_DECREF to identity value before leaving md_pop_one on success
    -- by :user:Vizonex.

    Related issues and pull requests on GitHub:
    #1284.


6.8.0: 6.8.0

Breaking change detected.

Compare source

Source

Source ref: master

Bug fixes

  • A segmentation fault that could be triggered when getting an item is now fixed
    -- by :user:Vizonex.

    Related issues and pull requests on GitHub:
    #1310.

  • Fixed reference leak in iterators, views and istr
    -- by :user:Vizonex.

    Related issues and pull requests on GitHub:
    #1311.

  • Fixed the pure-Python :class:~multidict.MultiDict constructor and
    :py:meth:~multidict.MultiDict.extend,
    :py:meth:~multidict.MultiDict.update, and
    :py:meth:~multidict.MultiDict.merge methods over-allocating their
    internal hash table when called with both a positional argument and
    keyword arguments, because keyword arguments were counted twice in the
    size estimate -- by :user:aiolibsbot.

    Related issues and pull requests on GitHub:
    #1338.

  • Fixed __repr__ of :class:~multidict.MultiDict,
    :class:~multidict.CIMultiDict, their proxies, and the keys/items views
    producing invalid output when keys contained quote characters --
    keys are now formatted with :func:repr so the result is a valid Python
    string literal -- by :user:aiolibsbot.

    Related issues and pull requests on GitHub:
    #1342.

  • Fixed a segfault when calling :py:meth:~multidict.MultiDict.add with only one of its two required arguments supplied by keyword, e.g. d.add(key="k"). Extra keyword arguments passed to the lookup and removal methods are also now rejected with :exc:TypeError instead of being silently ignored.

    -- by :user:devdanzin

    Related issues and pull requests on GitHub:
    #1376.

  • Fixed a segfault when constructing a multidict iterator type directly, e.g. type(iter(md.keys())).__new__(...). Such an iterator had a NULL internal pointer that next() dereferenced. The iterator types now forbid direct instantiation, the same way the view types were fixed in #1163.

    -- by :user:devdanzin

    Related issues and pull requests on GitHub:
    #1377.

  • Fixed a segfault when using a :py:class:~multidict.MultiDict or :py:class:~multidict.CIMultiDict created via __new__ without calling __init__ (for example a subclass that does not call super().__init__()). The internal state was left as NULL pointers that the first method call dereferenced. tp_new now initializes the object to a valid empty mapping.

    -- by :user:devdanzin

    Related issues and pull requests on GitHub:
    #1378.

  • Fixed two crashes in the C extension caused by holding a raw pointer into a hash table across an operation that could reshape it. Updating a multidict from itself (e.g. d.extend(d)) freed the very table being iterated -- a use-after-free; extend(self) now doubles the contents and update(self)/merge(self) are no-ops. Building a multidict from a list of pairs whose case-insensitive key .lower() shrinks that list read past the end of the list; the length is now re-checked on every iteration.

    -- by :user:devdanzin

    Related issues and pull requests on GitHub:
    #1379.

  • Fixed three reference/resource leaks on error paths in the C extension: the items-view __contains__ leaked the first element of a candidate pair when reading the second one raised; __repr__ leaked its PyUnicodeWriter when the multidict was mutated during iteration; and the internal iteration helper leaked the identity reference when key materialization failed under low memory.

    -- by :user:devdanzin

    Related issues and pull requests on GitHub:
    #1381.

  • Stopped several feature-detection fallbacks in the C extension from swallowing every exception. When probing an argument (arg.items()/arg.keys()) or measuring it (len(other)) fails, the code now clears only the expected :exc:TypeError/:exc:AttributeError and lets everything else -- notably :exc:MemoryError and :exc:KeyboardInterrupt -- propagate, matching the already-correct sites elsewhere in the module.

    -- by :user:devdanzin

    Related issues and pull requests on GitHub:
    #1382.

  • Fixed a segmentation fault when extending a multidict with itself
    -- by :user:cananoo and :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1398.

  • Fixed a memory leak when MultiDict and CIMultiDict instances are
    initialized more than once -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1412.

  • Fixed a reference leak in items-view set operations
    -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1413.

  • Fixed a memory leak when destroying C-extension multidict instances
    and proxies -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1415.

  • Fixed a reference leak from repeated __init__ calls on
    MultiDictProxy and CIMultiDictProxy instances -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1419.

  • Fixed missing decref for :data:None on error in :meth:~multidict.MultiDict.setdefault
    -- by :user:asvetlov

    Related issues and pull requests on GitHub:
    #1421.

Features

  • Added :py:func:reversed support to the keys, values, and items views of
    :class:~multidict.MultiDict, :class:~multidict.CIMultiDict, and their
    proxies in both the C-extension and pure-Python implementations
    -- by :user:aiolibsbot.

    Related issues and pull requests on GitHub:
    #448.

  • Optimized key identity comparison for C Extension.

    Now it uses fast path that is equal to :c:func:PyUnicode_Equal from
    Python 3.14+ but without redundant type checks. It gives ~15% speed-up on benchmarks with many key comparisons.

    -- by :user:asvetlov

    Related issues and pull requests on GitHub:
    #1406.

  • Changed both the pure-Python and C implementations to mark a temporarily
    removed hash table entry by setting the high bit of its hash instead of
    overwriting it with a sentinel value, so restoring the entry no longer
    recomputes the hash; :meth:~multidict.MultiDict.getall is faster ~10% now in C version
    -- by :user:asvetlov

    Related issues and pull requests on GitHub:
    #1426.

Removals and backward incompatible breaking changes

  • Dropped support for Python 3.9 as it has reached end of life.

    Related issues and pull requests on GitHub:
    #1316.

  • Dropped support for free-threaded Python 3.13 -- by :user:ngoldbaum.

    Related issues and pull requests on GitHub:
    #1326.

Improved documentation

  • Fixed CIMultiDictProxy documentation to state it inherits from
    MultiDictProxy (not MultiDict), and fixed missing word in
    istr section -- by :user:veeceey.

    Related issues and pull requests on GitHub:
    #1298.

  • Clarified that istr preserves the original casing and
    compares as a regular str; case-insensitive matching is
    handled by CIMultiDict -- by :user:gyanu2507.

    Related issues and pull requests on GitHub:
    #1397.

  • Fixed broken RST markup in items() docstrings
    -- by :user:veeceey.

    Related issues and pull requests on GitHub:
    #1299.

Packaging updates and notes for downstreams

  • Dropped support for free-threaded Python 3.13 -- by :user:ngoldbaum.

    Related issues and pull requests on GitHub:
    #1326.

  • Wheels for iOS and Android (CPython 3.13+) are now published on
    release-tag builds, so downstreams on those platforms no longer need a
    local compiler to install multidict; these wheels are build-verified
    only, since running the test suite on mobile needs a simulator or an
    emulator -- by :user:aiolibsbot.

    Related issues and pull requests on GitHub:
    #1337.

  • Added support for building and shipping riscv64 wheels
    -- by :user:justeph.

    Related issues and pull requests on GitHub:
    #1293.

  • The setuptools build dependency lower bound has been restored to be
    >= 47 after an incorrect automated increase in :pr:1315
    -- by :user:aiolibsbot.

    Related issues and pull requests on GitHub:
    #1400.

Contributor-facing changes

  • Added support for collecting code coverage of isolated multidict tests
    -- by :user:Vizonex.

    Related issues and pull requests on GitHub:
    #1314.

  • Switched to mirrors-clang-format and enabled clang-format in pre-commit.ci
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #1318.

  • Added a release-tag-gated CI job that cross-compiles the C extension
    for iOS and Android through cibuildwheel -- by :user:aiolibsbot.

    Related issues and pull requests on GitHub:
    #1337.

  • Added an AGENTS.md orientation file at the repository root, covering the
    pull request template, the CHANGES/ news fragment conventions, the
    draft-PR / human-review workflow, and the dual pure-Python and C-extension
    parity rule, so LLM contributors land changes that match project style
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #1339.

  • Added init, installable, instantiation, parametrization,
    parametrized, postfix, and unparseable to the docs spelling list
    so news fragments and docs can use these words without failing the spell
    check build -- by :user:pctablet505.

    Related issues and pull requests on GitHub:
    #1343.

  • Documented three common agent failure modes in
    :file:AGENTS.md: the docs spell check
    (make doc-spelling) catches unknown words in news fragments
    before CI does; coverage runs over the test tree too, so
    unreachable defensive raise guards and one-sided cleanup
    branches in tests will surface as uncovered on the codecov
    patch report; and branch creation is restricted on
    aio-libs/multidict, so PRs must be pushed from a fork
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #1343, #1345.

  • Trimmed the CI test matrix to drop redundant Py_DEBUG jobs on
    macOS and Windows and to gate the windows-11-arm wheel build to
    release-time only, cutting CI wall-clock by roughly a third without
    reducing code coverage -- by :user:aiolibsbot.

    Related issues and pull requests on GitHub:
    #1346.

  • Added a CLAUDE.md at the repository root that imports
    :file:AGENTS.md via Claude Code's @-syntax, so the
    project's LLM contributor rules load automatically when
    working in Claude Code
    -- by :user:aiolibsbot.

    Related issues and pull requests on GitHub:
    #1347.

  • Enabled the I (import sorting) rule in
    [tool.ruff.lint] so ruff check covers import order on top
    of the existing UP (pyupgrade) group, and updated the
    ruff-check pre-commit hook to run with
    --fix --exit-non-zero-on-fix --show-fixes so import-order
    fixes apply on commit. Sorted imports in four tests/ files
    to match the new rule -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #1348.

  • Enabled the PLC0415 (import-outside-top-level) rule in
    [tool.ruff.lint]. Function-scoped imports must now opt in
    with # noqa: PLC0415 plus a comment explaining the reason
    (typically avoiding a heavy optional dependency at import time).
    This catches a pattern that LLM contributors frequently introduce.
    There are currently no opt-outs in the tree, so the rule is
    enforced everywhere ruff check runs
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #1349.

  • Switched the cibuildwheel build frontend to build[uv] so
    that uv provisions every build and test virtual environment
    in the wheel matrix. Test-dependency installation in particular
    drops from a multi-second pip install per ABI to a roughly
    sub-second uv resolve
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #1350.

  • Overrode CIBW_BUILD_FRONTEND=build for the odd-arch wheel
    matrix; the upstream manylinux/musllinux images for
    those arches do not ship uv
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #1352.

  • Allowed re-running the deploy job after a partial release failure: the
    Make Release step now skips when the GitHub Release already exists,
    and the PyPI publish step uses skip-existing so dists that were
    already uploaded on a prior attempt do not break the retry
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #1353.

  • Switched the aarch64 and armv7l wheel builds to GitHub's native ARM
    runners. The aarch64 wheels now build without QEMU emulation, and
    armv7l runs on aarch64 hosts so its 32-bit ARM execution is far
    cheaper than the previous aarch64-on-x86_64 path
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #1354.

  • Documented design principles for pure-Python :class:~multidict.istr implementation
    -- by :user:asvetlov

    Related issues and pull requests on GitHub:
    #1360.

  • Pinned coverage to the ctrace measurement core so the test suite runs
    on Python 3.14. Coverage picks sysmon there, which cannot record the
    dynamic contexts pytest-cov switches at runtime, and the resulting warning
    became an error under the suite's filterwarnings setting
    -- by :user:rodrigobnogueira.

    Related issues and pull requests on GitHub:
    #1393.

  • Dependabot has been restricted to the requirements subdirectory to
    avoid unintended updates outside dependency requirement files
    -- by :user:aiolibsbot.

    Related issues and pull requests on GitHub:
    #1400.

  • Enabled automatic upgrades from ruff after each python version that is dropped
    -- by :user:Vizonex.

    Related issues and pull requests on GitHub:
    #1325.

Miscellaneous internal changes

  • Explicitly marked empty_htkeys as const.

    Moved the structure to .rodata linker section.

    Unexpected modification of the structure will lead to segfault instead
    of corrupting the data and fail fast.

    .rodata is mount as read-only-mapped, it is shared well across
    multiple threads without cache misses.

    The change is pretty trivial, it is made for the sake of correctness,
    not for speedup.

    -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1405.

  • Slightly reorganized multidict creating process.

    1. Removed unnecessary calculations when md_init() creates an empty multidict.
    2. Now tp_alloc slot is used in object cloning instead of bare :c:func:PyType_GenericNew call.

    -- by :user:asvetlov

    Related issues and pull requests on GitHub:
    #1420.

  • Dropped dead code, _md_del_at() and _md_del_at_for_upd() never fails
    -- by :user:asvetlov

    Related issues and pull requests on GitHub:
    #1423.

  • Fixed a missing space in the :exc:ValueError message
    raised when constructing a multidict from a sequence
    -- by :user:veeceey.

    Related issues and pull requests on GitHub:
    #1295.

  • Renamed the benchmark script from benchmarks/becnhmark.py to
    benchmarks/benchmark.py so it matches the invocation documented in
    :doc:benchmark -- by :user:aiolibsbot.

    Related issues and pull requests on GitHub:
    #1335.


6.9.0: 6.9.0

Compare source

Source

Source ref: master

Bug fixes

  • Protected repr() of MultiDict, MultiDictProxy, and their views
    in the C extension with a critical section, avoiding data races on the
    free-threaded build of CPython -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1431.

  • Guarded repr() of MultiDictProxy in the C extension and of
    KeysView in both the C extension and the pure-Python
    implementation against infinite recursion on self-referential
    containers, matching the existing guard on MultiDict,
    ItemsView, and ValuesView -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1431.

  • Protected MultiDict.update(), .extend(), .merge(), .clear(),
    .copy(), and the MultiDict/CIMultiDict constructors in the C
    extension with a critical section, using the two-object form when a
    second multidict, multidict proxy, or plain dict instance is
    involved, avoiding data races and a segmentation fault on the
    free-threaded build of CPython. .clear() now also publishes the
    empty table before releasing any entry's references, so a concurrent
    caller can never observe a partially-cleared multidict even if releasing
    a value runs arbitrary Python code that suspends the held critical
    section -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1433.

  • Protected MultiDict.add(), __setitem__/__delitem__,
    get()/getone()/__getitem__, __contains__, getall(),
    setdefault(), pop()/popone()/popall()/popitem(),
    __eq__, iteration, and the &/|/-/^/in/
    isdisjoint() operations on .keys() and .items() views in the
    C extension with a critical section, avoiding data races and
    use-after-free crashes on the free-threaded build of CPython
    -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1438.

  • Fixed a data race on the free-threaded build where MultiDictObject.used
    was written non-atomically while len() read it with a relaxed atomic
    load -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1441.

  • Fixed several pre-existing use-after-free races on the free-threaded build: _md_resize()
    and md_clone_from_ht() could allocate a new hash table, have their
    critical section transiently suspended during that allocation, and then use
    a keys-table pointer or size a concurrent operation had already invalidated;
    _md_del_at() (plain del/pop()) could likewise leave self in
    an inconsistent state across a suspending decref -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1441.

  • Fixed a data race on the free-threaded build where md->keys was
    published with a plain store while lock-free readers loaded it
    atomically, and a false-negative race in get()/__contains__
    where a hash temporarily marked by a concurrent replace could make a
    present key look absent -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1441.

  • Fixed several more pre-existing use-after-free and data-corruption races on
    the free-threaded build, this time in the __setitem__()/update()/
    extend()/merge() replace path: a decref suspending the critical
    section mid-replace could leave a stale table pointer in use, misplace a
    temporarily-marked entry during a concurrent resize, or let one thread's
    duplicate-tracking mark get overwritten by an unrelated key's entry sharing
    the same hash bucket -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1441.

  • Fixed an unbounded memory leak on the free-threaded build where a retired
    hash table could sit on md->retired for the rest of the object's
    lifetime under sustained concurrent read traffic instead of being freed
    -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1443.

  • Fixed a data race on the free-threaded build of the C extension where
    state->global_version, the version counter shared by every
    multidict instance and used to derive getversion(), was bumped with
    a plain increment instead of an atomic op. Two threads mutating
    different instances at the same time could step on each other's update
    and hand out a duplicate (or non-monotonic) version number
    -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1444.

  • Fixed a data race on the free-threaded build of the C extension where
    getall()/popall() and update()/extend()/merge()
    temporarily marked and unmarked a matching entry's hash with a plain,
    non-atomic store, while a lock-free __contains__/get() on another
    thread could load that same field with an atomic operation and no lock at
    all -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1448.

  • Fixed a data race in the pure-Python MultiDict/CIMultiDict
    fallback where concurrent mutating calls (add(), __setitem__,
    __delitem__, setdefault(), pop()/popone(),
    popall(), popitem(), update(), extend(), merge(),
    clear(), and re-__init__) could corrupt the shared hash table,
    or silently drop a concurrent write, on a regular, GIL-enabled
    interpreter. Pure-Python bytecode is not atomic under the GIL, so two
    threads could interleave mid hash-table insert or deletion, leaving
    the index table pointing at stale or out-of-range entries and causing
    an infinite probe loop, an AttributeError, or a lost mutation.
    Each MultiDict/CIMultiDict instance now holds its own lock for
    the duration of these operations, with two-object operations locking
    both instances in a fixed order to avoid deadlock. The C extension
    already serializes these operations with a critical section and was
    not affected
    -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1449.

  • Fixed a data race on the free-threaded build of the C extension where
    to_dict() cleared every entry's temporary "seen" mark with a plain,
    non-atomic store, while a lock-free __contains__/get() on another
    thread could load that same field with an atomic operation and no lock at
    all -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1450.

  • Fixed a data race on the free-threaded build of the C extension where
    update()/extend()/merge() read self's module state without
    holding self's lock, while a concurrent __init__() on the same,
    already-published multidict could rewrite that same field under lock.
    Rather than routing every read through a lock-free lookup, the field is
    now written only once, at object construction, and never touched again by
    __init__(), so it is safe to read unlocked anywhere -- by
    :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1452.

  • Fixed items() set algebra (&, |, -, in, isdisjoint()) so it no
    longer corrupts or hangs when a compared value's __eq__() re-enters the
    same :class:~multidict.MultiDict, for example by calling getall() on
    it. The comparison now runs only after the internal hash-chain walk has
    been fully materialized and restored, so the callback can no longer
    observe entries the walk still has marked -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1453.

  • Fixed a data race on the free-threaded build of the C extension where
    popall()/popone()/__delitem__/add() rewrote a hash table
    index slot with a plain, non-atomic store, while a lock-free
    get()/getone()/__getitem__/__contains__ on another thread
    walked that same index array with a plain, non-atomic load and no lock at
    all -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1454.

  • Stopped folding the case of :class:~multidict.istr keys in the
    case-sensitive :class:~multidict.MultiDict, so both the C and the pure
    Python implementations now keep such a key exactly as given
    -- by :user:youdie006.

    Related issues and pull requests on GitHub:
    #1457.

  • Fixed the C extension's update() (and merge(), which shares the same
    code path) silently failing to invalidate an in-progress keys()/
    items()/values() iterator when the call only overwrote an
    already-present key's value in place. Adding a new key already invalidated
    iterators correctly; only the in-place overwrite branch was missing the
    version bump -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1458.

  • Fixed the pure-Python MultiDict/CIMultiDict iterator guard so that
    mutating the mapping before the first next() call on an items(),
    keys(), or values() iterator (or on iter(md)) now reliably raises
    RuntimeError, matching the C extension. Previously a mutation that
    happened before the iterator was ever advanced, such as clear() or a
    del/popone() that removed the only remaining entry, could make the
    iterator silently raise StopIteration instead -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1459.

  • Fixed a use-after-free race on the free-threaded build of the C extension
    where a retired hash table could be freed while a lock-free
    get()/getone()/__getitem__/__contains__ reader on another
    thread was still walking it: the coarse "no reader in flight" gate
    reaching zero did not reliably mean every such reader had also reached
    its own per-table exit, so a table whose own reader count is still
    nonzero is now deferred for a later retry instead of freed
    -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1461.

Features

  • Added a :meth:~multidict.MultiDict.to_dict method returning a plain
    :class:dict that maps every key to the list of all its values. Unlike
    dict(md), which keeps only the first value per key, and unlike a
    {k: md.getall(k) for k in md} comprehension, which emits one entry per
    spelling of a case-insensitive key, it groups by key identity
    -- by :user:rodrigobnogueira.

    Related issues and pull requests on GitHub:
    #783.

  • MultiDict, CIMultiDict, MultiDictProxy and CIMultiDictProxy in the
    C extension implemented the vectorcall calling convention for construction.
    This sped up MultiDict(...)-style calls by avoiding an intermediate
    positional-arguments tuple and keyword-arguments dictionary in the common case; the gained burst is ~10.
    -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1436.

  • Made MultiDict.__contains__(), .get(), .getone() and
    __getitem__() lock-free on CPython 3.14+'s free-threaded build, instead
    of taking a critical section like the rest of the C extension's API (on
    3.13, which lacks the public API these need to safely read an entry
    concurrently, they still take the critical section, exactly as before). A
    resize/shrink/clear no longer frees the outgoing hash table immediately; it
    is deferred until no lock-free reader could still be walking it -- by
    :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1441.

  • Made the pure-Python MultiDict/CIMultiDict implementation safe to
    use from multiple threads under a free-threaded (no-GIL) build. Every
    method that touches an instance's hash table now takes that instance's own
    lock, two-object operations (update(), extend(), merge(),
    __eq__(), copying) lock both objects in a fixed, deadlock-safe order,
    and the version counter shared by every instance is guarded separately. On
    a regular (GIL-enabled) interpreter this adds no overhead: the locked
    methods are the exact same function objects as before -- by
    :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1447.

  • Sped up adding many values for the same key to a
    :class:~multidict.MultiDict or :class:~multidict.CIMultiDict, each
    added value no longer gets slower than the one before it
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #1466.

Improved documentation

  • Added the plural form "fallbacks" to the docs spell checker's allowed
    word list so :file:CHANGES.rst builds cleanly -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1439.

Contributor-facing changes

  • Added race tests that iterate and extend a :class:~multidict.MultiDict
    from several threads on a free-threaded build, so a regression in the C
    extension's locking fails a free-threaded CI leg instead of going unnoticed
    -- by :user:rodrigobnogueira.

    Related issues and pull requests on GitHub:
    #1317.

  • Added AddressSanitizer/UndefinedBehaviorSanitizer and
    ThreadSanitizer CI jobs. The former runs the suite under a
    regular CPython with MULTIDICT_ASAN_BUILD=1; the latter builds a
    free-threaded CPython instrumented with --with-thread-sanitizer
    and runs the suite against it via MULTIDICT_TSAN_BUILD=1 -- by
    :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1455.

  • Added Hypothesis-based property and stateful fuzz tests covering
    :class:~multidict.MultiDict/:class:~multidict.CIMultiDict semantics,
    views, iterators, and threaded stress scenarios, run against both the
    C-extension and pure-Python backends -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1460.

  • Added core dump collection to the AddressSanitizer and ThreadSanitizer
    CI jobs: a crash now uploads the core file alongside the crashing
    interpreter binary and the compiled extension as a downloadable
    artifact, for offline debugging with a matching symbol-carrying binary
    instead of raw hex offsets -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1462.

  • Added benchmarks for adding many values for the same key and for
    creating a multidict with many items -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #1465.

  • Skipped abstractmethods from coverage leaks report, they are empty placeholders that are never executed -- by :user:asvetlov

    Related issues and pull requests on GitHub:
    #1470.

  • Add benchmarks for __setitem__ -- by :user:asvetlov

    Related issues and pull requests on GitHub:
    #1471.

  • The AddressSanitizer and ThreadSanitizer CI jobs were changed to run pytest
    with --capture=no. Previously a sanitizer abort could exit the process
    before pytest flushed its per-test output buffer, silently dropping the
    sanitizer report from the job log -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1472.

  • Moved the hypothesis pin out of requirements/pytest.txt into its own
    requirements/pytest-hypothesis.txt, installed only by the dedicated
    Hypothesis CI jobs. hypothesis now ships a Rust extension with no
    prebuilt wheel for some emulated architectures (e.g. musllinux i686),
    which broke wheel-testing jobs that never run the Hypothesis-marked tests
    in the first place -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1475.

Miscellaneous internal changes

  • Replaced PyIter_Next() calls with the newer PyIter_NextItem() API in
    the C extension, so the iterator-exhausted and error cases are told apart by
    the return code instead of an ambiguous NULL result -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1440.


6.9.1: 6.9.1

Compare source

Source

Source ref: master

Bug fixes

  • Fixed the C extension reading freed memory on free-threaded builds when a
    list handed to :py:meth:~multidict.MultiDict.update,
    :py:meth:~multidict.MultiDict.extend, :py:meth:~multidict.MultiDict.merge
    or the :py:class:~multidict.MultiDict and :py:class:~multidict.CIMultiDict
    constructors, a [key, value] item inside any iterable handed to them, or a
    list tested with in against :py:meth:~multidict.MultiDict.items, is
    changed by another thread; a call that catches the list shrinking under it
    now raises :py:exc:RuntimeError -- by :user:rodrigobnogueira.

    Related issues and pull requests on GitHub:
    #1437.

  • Fixed a data race on the free-threaded build where a retired hash table's
    reader count used relaxed atomics, letting a lock-free get()/getone()/
    __getitem__() read race a concurrent free of that table. The reader-exit
    decrement and the drain's free check now use release/acquire ordering
    instead -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1481.

  • Fixed a free-threaded build bug where two threads calling update(),
    merge(), or __setitem__() on the same key at the same time could lose
    the key entirely instead of just racing on which value wins. A decref of the
    replaced value could transiently suspend the writer's critical section,
    letting a second writer for the same key observe the first writer's
    in-progress entry as absent and, once both settled, mistake it for a stale
    duplicate and delete it. Every such decref is now deferred until the writer
    has released its critical section, so the window can no longer open.
    setdefault() had an unrelated instance of the same blind spot (it could
    insert a duplicate rather than recognizing an in-flight key), fixed alongside
    it -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1483.

  • Fixed a free-threaded build bug where getall() and the items()/
    keys()/values() equality path could raise KeyError or report a
    present, never-deleted key as missing. A concurrent update()/extend()/
    __setitem__() call can have its critical section transiently suspended
    (a decref triggering a blocking allocator call) while an entry is marked as
    part of its own bookkeeping; a reader landing in that window used to treat
    the mark as "not found" instead of "still there, in flight" -- by
    :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1484.

  • Fixed a reference leak in the C extension where operand | md.items()
    and md.items() - operand leaked one key and one value reference per
    element of operand, letting a large operand grow memory without bound
    (:gh:GHSA-54p9-h82j-f925 <aio-libs/multidict/security/advisories/GHSA-54p9-h82j-f925>)
    -- by :user:asvetlov.

    The issue was reported by :user:waydeshi.

    Related commits on GitHub:
    :commit:350b4a0.

  • Fixed a segmentation fault on the standard (non-free-threaded) C extension
    build when a value type's __del__ released the GIL (for example by
    calling time.sleep()) while update(), merge(), __setitem__(),
    __delitem__(), pop(), popone(), or popall() was dropping a
    replaced or removed value. Py_BEGIN_CRITICAL_SECTION compiles to a no-op
    on this build, so nothing else was stopping a second thread from mutating the
    very same MultiDict concurrently once the GIL was released mid-mutation.
    Every such decref is now deferred until the mutation has fully finished, the
    same technique already used to close the analogous free-threaded-build race
    -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1489.

  • Fixed the C extension reading freed memory while iterating a
    :py:class:~multidict.CIMultiDict whose keys are plain :py:class:str.
    Converting such a key to :py:class:~multidict.istr could run Python code
    (a :py:class:str subclass's __str__ or __del__) or, on free-threaded
    builds, suspend the iterator's critical section, after which the iterator read
    the entry again even though a concurrent mutation could already have freed it.
    As part of the fix, :py:meth:~multidict.MultiDict.copy and re-initializing
    from another multidict now assign a new version in the C extension instead of
    reusing the source's, matching the pure Python implementation
    -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1496.

  • Fixed a use-after-free on the free-threaded build where a lock-free
    get(), [] or in could read a hash table that a concurrent
    resize had just retired and another reader was freeing
    -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1497.

Contributor-facing changes

  • Removed a redundant include and a duplicated exclude line from
    MANIFEST.in; sdist contents are unchanged -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1478.

  • Added .claudeignore file -- by :user:asvetlov

    Related issues and pull requests on GitHub:
    #1479.

  • Scaled up the pure-Python pop(), popitem(), __delitem__(),
    add() and item-insertion benchmarks to do more work per measurement.
    Repeated CodSpeed runs on the same commit showed these particular
    benchmarks flagged as dominated by syscalls, understating their real
    cost and adding noise to the reported values; a larger working set
    amortizes that overhead -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1485.

  • Replaced deprecated instrumentation codspeed mode with simulation -- by :user:asvetlov

    Related issues and pull requests on GitHub:
    #1493.

  • Reorganized the mutating benchmarks (item insertion, update(),
    add() of the same key, pop(), popitem(), clear(),
    __delitem__() and __setitem__()) to copy a fresh multidict and
    apply the operation in a loop, like the add() and extend()
    benchmarks already do. The insertion, update() and clear()
    benchmarks previously mutated a single multidict shared across
    rounds, so only the first round measured the intended operation; the
    rest did a single copy per round, letting per-round overhead dominate
    -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1494.

  • The repr() and view inequality benchmarks were updated to repeat their
    operation in a loop, like the other benchmarks, and the CodSpeed benchmark
    job was moved to Python 3.14 -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1498.

  • Dropped -I from the AddressSanitizer test command in AGENTS.md
    and in the CI job. It implies -E, which made Python ignore
    PYTHONMALLOC=malloc, so small hash tables were still served from
    pymalloc arenas where use-after-free went undetected
    -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1499.

  • The CI/CD workflow was updated to stop superseded runs of the same pull request
    when a new commit is pushed; runs on master, release branches, tags,
    the merge queue, and the daily schedule are never interrupted
    -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1500.

  • The release job was changed to upload distributions and their signatures
    to the GitHub Release one file at a time, skipping assets that were
    already attached and retrying after a pause, so that a parallel upload
    burst no longer tripped the GitHub secondary rate limit
    -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1503.

Miscellaneous internal changes

  • Corrected several comments in the free-threaded C extension that
    attributed critical-section suspension to a blocking PyMem_Malloc()
    call; allocation alone never suspends an acquired critical section, and
    the real risk at those sites is a decref running
    a finalizer or weakref callback. Also dropped a retry loop in
    md_clone_from_ht() that guarded against the same, non-existent
    allocation-triggered suspension -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1486.

  • Changed the free-threaded build's deferred decref buffer, used by
    update() and __setitem__(), to a chain of fixed-size blocks
    with a large inline first block instead of a small inline array that
    was reallocated on growth -- by :user:asvetlov.

    Related issues and pull requests on GitHub:
    #1501.


packaging (25.0 → 26.3)

26.0: 26.0

Compare source

Source

Source ref: main

Read about the performance improvements here: https://iscinumpy.dev/post/packaging-faster.

What's Changed

Features:

Behavior adaptations:

Fixes:

Performance:

Type annotations:

Internal:

New Contributors

Since last RC

Fixes:

Performance:

Documentaiton:

Full Changelog: https://github.com/pypa/packaging/compare/26.0rc3...26.0

26.1: 26.1

Compare source

Source

Source ref: main

Features:

Behavior adaptations:

Pylock (PEP 751) updates:

Fixes:

Performance:

Internal:

Documentation:

Benchmarks

Performance improvements since 26.0, from the new integrated benchmark suite:

uv run asv run 26.0..HEAD
Screenshot 2026-04-13 at 11 32 14 PM Screenshot 2026-04-13 at 11 32 43 PM

New Contributors

Full Changelog: https://github.com/pypa/packaging/compare/26.0...26.1

26.2: 26.2

Compare source

Source

Source ref: main

What's Changed

Fixes:

Documentation:

Internal:

New Contributors

Full Changelog: https://github.com/pypa/packaging/compare/26.1...26.2

26.3: 26.3

Compare source

Source

Source ref: main

What's Changed

Features

  • Add a public VersionRange API and SpecifierSet.to_range(), representing the versions a specifier set accepts as an interval set that supports intersection, union, difference, complement, set relations, membership tests, and filtering. VersionRange.to_specifier_set() converts a range back to a SpecifierSet where a PEP 440 form exists. (#1267, #1270, #1298)
  • PEP 808: accept Metadata-Version: 2.6. (#1194)
  • Add a limit argument to parse_tag() for compressed tag sets. (#1220)
  • Add a prefer_sdist_predicate argument to Pylock.select() to prefer source distributions over wheels for selected packages. (#1334)
  • Add pure_python_tags() to generate the pure-Python tags for a Python version without touching the running platform. (#1346)
  • Add SpecifierSet.is_subset(), SpecifierSet.is_superset(), and SpecifierSet.is_disjoint(), which compare the versions two specifier sets accept. (#1313)

Behavior adaptations

  • Drop support for Python 3.8; packaging now requires Python 3.9 or later. (#1157)
  • Prefer native linux_* platform tags over manylinux and musllinux tags on Linux. (#160)

Fixes for versions and specifiers

  • Raise InvalidVersion instead of TypeError when Version is given a non-string. (#1319)
  • Raise InvalidVersion for non-string pre-release letters passed to Version.from_parts. (#1241)
  • Fix an AttributeError when hashing internally trimmed versions. (#1242)
  • Fix SpecifierSet.is_unsatisfiable for post-release boundary intersections. (#1257)

Fixes for requirements and markers

  • Make Requirement.__hash__ consistent with __eq__ for trailing-zero-equivalent specifiers (e.g. foo==1.0.0 and foo==1.0.0.0), so equal requirements hash equal and deduplicate in sets and dicts. (#1232)
  • Normalize requested extra names before comparing or hashing requirements. (#644)
  • Preserve a Requirement's specifier prereleases override across a pickle round trip. (#1204)
  • Raise InvalidRequirement instead of InvalidSpecifier when a requirement contains an invalid specifier. (#1332)
  • Clarify the error for post-release prefix wildcards like ==1.0.post1.*. (#1299)
  • Preserve quoting semantics when serializing marker values, so round-tripped markers parse back to the same marker. (#1213)
  • Keep the parentheses of a nested group when serializing markers. (#1316)
  • Normalize extra and dependency_groups values in nested markers at parse time. (#1246, #1310)
  • Raise UndefinedComparison when a set-valued variable like extras is used outside the membership form. (#1265)
  • Raise UndefinedEnvironmentName (a KeyError subclass) for missing environment keys during marker evaluation. (#1276)
  • Wrap malformed string literal errors in InvalidMarker / InvalidRequirement instead of leaking a low-level error. (#1249)
  • Reject requirements and markers with a trailing line break. (#1345)

Fixes for metadata and licenses

  • Collect all from_email validation errors into one ExceptionGroup instead of raising the first. (#1268)
  • Accept the UTF-8 charset case-insensitively in email payloads. (#1330)
  • Reject malformed Description-Content-Type values. (#1329)
  • Don't rewrite user values that contain {field} placeholders in error messages. (#1327)
  • Route multipart email payloads to unparsed instead of asserting. (#1247)
  • Make InvalidMetadata and CyclicDependencyGroup picklable. (#1328)
  • Fold every line boundary str.splitlines recognizes when writing a header with RFC822Message. (#1356)
  • Raise InvalidLicenseExpression for misplaced WITH clauses and empty LicenseRef- names. (#1266)
  • Raise InvalidLicenseExpression instead of KeyError for a LicenseRef- with a + suffix. (#1219)

Fixes for tags and filenames

  • Raise InvalidTag from parse_tag() for tags with the wrong number of components. (#1238)
  • Reject empty tag components in parse_wheel_filename() and parse_tag(). (#1234)
  • Reject an empty project name in the wheel and sdist filename parsers. (#1305)
  • Reject wheel filenames with a trailing newline. (#1341)
  • Reject wheel tags whose interpreter component is not an identifier. (#577)
  • is_normalized_name now rejects names with collapsed double hyphens like a--b. (#1230)
  • Fix duplicate explicit abi3t tags. (#1245)
  • Forward the warn argument to generic_tags() in sys_tags(). (#1264)
  • Raise SystemError for an empty or malformed CPython EXT_SUFFIX. (#1271, #1301)
  • Fix a typo in the macOS fat3 architecture name (was fat32). (#1199)

Fixes for pylock, direct URLs, and dependency groups

  • Percent-decode pylock artifact file names derived from a url so that local versions (e.g. a wheel with 2.12.1+cu130 encoded as 2.12.1%2Bcu130) yield a valid file name. (#1314)
  • Use an explicitly empty tags sequence in Pylock.select() instead of falling back to sys_tags(). (#1349)
  • Fix Pylock.select() on Python builds that report a non-PEP 440 python_full_version (e.g. 3.15.0+). (#1179)
  • Reject TOML booleans where integers are expected in pylock files. (#1244)
  • Add PylockSelectError to packaging.pylock.__all__. (#1202)
  • Fix DirectUrl credential stripping for passwords containing @. (#1218)
  • Parse the URL scheme case-insensitively when checking for file URLs in direct_url. (#1240)
  • Require absolute file URLs for local directories in direct_url. (#1297)
  • Collect InvalidRequirement errors while resolving dependency groups instead of leaking them. (#1302)
  • Don't cache malformed dependency group parses. (#1248)

Performance

  • Implement Specifier and SpecifierSet filtering with the new range engine. (#1120, #1259)
  • Cache the default marker environment. (#1250)
  • Cache the _manylinux module lookup process-wide. (#1254)
  • Add __slots__ to Requirement and the token classes. (#1320, #1258)
  • Keep range caches across canonicalization, precompile the wheel project-name pattern, simplify parse_tag(), and skip platform.mac_ver() when the version and arch are given. (#1253, #1256, #1236, #1255)

Documentation

Internal

  • Add Python 3.15 to the test matrix. (#1190)
  • Add a musl/Alpine test job and make the test suite pass on musl. (#1226, #1227)
  • Expand the downstream test matrix by ten projects. (#1261)
  • Update to mypy 2. (#1191)
  • Use nox's uv integration. (#1057)

New Contributors

Full Changelog: https://github.com/pypa/packaging/compare/26.2...26.3

propcache (0.4.1 → 0.5.4)

v0.5.1: 0.5.1

Compare source

Source

Source ref: master

No significant changes.


0.5.2: 0.5.2

Breaking change detected.

Compare source

Source

Source ref: master

0.5.0 and 0.5.1 were tagged earlier today but never reached PyPI: 0.5.0's deploy failed at cibuildwheel's post-build pytest on free-threaded armv7l musllinux (SIGBUS under QEMU emulation while importing the C extension), and 0.5.1's deploy hit a transient sigstore Rekor 502 during the attestation step. 0.5.2 is the first of the three to actually publish.

Features

  • Added support for newer type hints and remove Optional and Union from all annotations
    -- by :user:Vizonex

    Related issues and pull requests on GitHub:
    #193.

Removals and backward incompatible breaking changes

  • Dropped support for Python 3.9 as it has reached end of life.

    Related issues and pull requests on GitHub:
    #216.

Packaging updates and notes for downstreams

  • Changed the Cython build dependency from ~= 3.1.0 to >= 3.2.0,
    removing the upper version bound to avoid conflicts for downstream packagers
    -- by :user:jameshilliard and :user:gundalow.

    The upstream Cython version is pinned to 3.2.4 in the CI/CD environment.

    Related issues and pull requests on GitHub:
    #184, #188, #214.

  • Start building and shipping riscv64 wheels
    -- by :user:justeph.

    Related issues and pull requests on GitHub:
    #194.

  • The :pep:517 build backend now supports a new build-inplace
    config setting (and PROPCACHE_BUILD_INPLACE environment variable)
    for controlling whether to build the project in-tree or in a
    temporary directory. It only affects wheels and is set up to build
    in a temporary directory by default. It does not affect editable
    wheel builds; they will keep being built in-tree regardless.

    Here's an example of using this setting:

    .. code-block:: console

    $ python -m build --config-setting=build-inplace=true

    Additionally, when building wheels in an automatically created
    temporary directory, the build backend now normalizes the
    respective file system path to a deterministic source checkout
    directory by injecting the -ffile-prefix-map compiler option
    into the CFLAGS environment variable, as suggested by known
    reproducible build practices <https://reproducible-builds.org/docs/build-path/>__.

    The effect is that downstreams will get reproducible build results.

    Related issues and pull requests on GitHub:
    #218.


0.5.3: 0.5.3

Breaking change detected.

Compare source

Source

Source ref: master

Bug fixes

  • Fixed a possible crash in the C implementation of cached_property
    and under_cached_property on free-threaded Python, where a cached
    value could be freed by another thread while it was being read; errors
    raised while looking up the cache are now propagated on all builds,
    and the computed value is no longer leaked if storing it fails
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #297.

Removals and backward incompatible breaking changes

  • Dropped support for free-threaded Python 3.13 -- by :user:Vizonex.

    Related issues and pull requests on GitHub:
    #223.

Improved documentation

  • Updated discussion links from the defunct Google Groups forum to
    GitHub Discussions
    -- by :user:gundalow.

    Related issues and pull requests on GitHub:
    #217.

Packaging updates and notes for downstreams

  • The setuptools build dependency lower bound has been restored to be
    >= 47 after an incorrect automated increase in :pr:207
    -- by :user:bbhtt.

    Related issues and pull requests on GitHub:
    #207.

  • Dropped support for free-threaded Python 3.13 -- by :user:Vizonex.

    Related issues and pull requests on GitHub:
    #223.

  • Dropped the deprecated License :: OSI Approved :: Apache Software License classifier; setuptools 84 warns about it and the dist
    build treats warnings as errors, so releases could no longer be built
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #299.

Contributor-facing changes

  • Dependabot has been restricted to the requirements subdirectory to
    avoid unintended updates outside dependency requirement files
    -- by :user:bbhtt.

    Related issues and pull requests on GitHub:
    #207.

  • Added an AGENTS.md file with contributor guidance for AI
    coding agents, adapted from the yarl equivalent
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #231.

  • Migrated from standalone black and isort pre-commit hooks
    to ruff format and the ruff I lint rule, sharing a new
    [tool.ruff] config in pyproject.toml. ruff-check runs
    with --fix so import-order fixes apply on commit, and the
    orphan [isort] block in setup.cfg was removed
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #232.

  • Switched the cibuildwheel build frontend to build[uv] so
    that uv provisions every build and test virtual environment
    in the wheel matrix. Test-dependency installation in particular
    drops from a multi-second pip install per ABI to a roughly
    sub-second uv resolve
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #234.

  • Dropped the libffi-devel install from the cibuildwheel
    Linux before-all step. It was added in :pr:75 so
    cffi could build from source during wheel testing; the
    current wheel-test chain no longer pulls in cffi, so the
    header package is dead weight
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #236.

  • The type preciseness coverage report generated by MyPy <https://mypy-lang.org>__ is now uploaded to Coveralls <https://coveralls.io/github/aio-libs/propcache>__ and
    will not be included in the Codecov views <https://app.codecov.io/gh/aio-libs/propcache>__ going forward
    -- by :user:aiolibsbot.

    Related issues and pull requests on GitHub:
    #239.

  • Switched CI/CD to tox-dev/workflow's :file:reusable-tox.yml
    driven by an in-tree :file:tox.ini. The build,
    metadata-validation and lint (pre-commit,
    spellcheck-docs) jobs all run through the reusable workflow;
    mypy coverage uploads to Coveralls from a post-tox-job
    hook
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #243.

  • Overrode CIBW_BUILD_FRONTEND=build for the QEMU-emulated
    odd-arch wheel matrix, since the pypa odd-arch container images
    do not ship uv preinstalled and the project's
    :file:pyproject.toml sets build-frontend = "build[uv]"
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #246.

  • Allowed re-running the deploy job after a partial release failure: the
    Make Release step now skips when the GitHub Release already exists,
    and the PyPI publish step uses skip-existing so dists that were
    already uploaded on a prior attempt do not break the retry
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #247.

  • Switched the aarch64 and armv7l wheel builds to GitHub's native ARM
    runners. The aarch64 wheels now build without QEMU emulation, and
    armv7l runs on aarch64 hosts so its 32-bit ARM execution is far
    cheaper than the previous aarch64-on-x86_64 path
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #248.

  • Added UV_CONSTRAINT and UV_BUILD_CONSTRAINT alongside
    PIP_CONSTRAINT and PIP_BUILD_CONSTRAINT in the
    cibuildwheel environment so the :file:requirements/cython.txt
    pin is honored under the build[uv] frontend; uv pip
    ignores the PIP_ variables and reads only the UV_ ones,
    while the PIP_ variants are kept for the pip fallback path
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #249.

  • Fixed coverage for testing benchmarks when codspeed is not installed
    -- by :user:Vizonex.

    Related issues and pull requests on GitHub:
    #251.

  • Stopped running the test suite inside the wheel build jobs outside of
    release builds, since the test matrix installs and tests the same
    wheels, and added Python 3.15 and 3.15t to the test matrix so those
    wheels stay covered. Off-tag macOS builds are now limited to the
    architecture the test matrix runs on. Release builds still build every
    architecture and test every wheel, and all release checks in the CI
    workflow now use github.ref_type
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #300.


0.5.4: 0.5.4

Compare source

Source

Source ref: master

Packaging updates and notes for downstreams

  • Fixed the release wheels being compiled without optimization since
    version 0.5.0. The build backend set CFLAGS to add
    -ffile-prefix-map, which replaced the interpreter's own compiler
    flags instead of extending them, so -O3 and -DNDEBUG were
    dropped; the extra flags now go through CPPFLAGS, which is
    appended. Cached property reads are about 1.5x faster than in 0.5.3
    -- by :user:bdraco.

    Related issues and pull requests on GitHub:
    #244, #302.


pygments (2.19.2 → 2.21.0)

2.20.0: 2.20.0

Compare source

Source

Source ref: master

  • New lexers:

  • Updated lexers:

    • archetype: Fix catastrophic backtracking in GUID and ID patterns (#3064)
    • ASN.1: Recognize minus sign and fix range operator (#3014, #3060)
    • C++: Add C++26 keywords (#2955), add integer literal suffixes (#2966)
    • ComponentPascal: Fix analyse_text (#3028, #3032)
    • Coq renamed to Rocq (#2883, #2908)
    • Cython: Various improvements (#2932, #2933)
    • Debian control: Improve architecture parsing (#3052)
    • Devicetree: Add support for overlay/fragments (#3021), add bytestring support (#3022), fix catastrophic backtracking (#3057)
    • Fennel: Various improvements (#2911)
    • Haskell: Handle escape sequences in character literals (#3069, #1795)
    • Java: Add module keywords (#2955)
    • Lean4: Add operators ]', ]?, ]! (#2946)
    • LESS: Support single-line comments (#3005)
    • LilyPond: Update to 2.25.29 (#2974)
    • LLVM: Support C-style comments (#3023, #2978)
    • Lua(u): Fix catastrophic backtracking (#3047)
    • Macaulay2: Update to 1.25.05 (#2893), 1.25.11 (#2988)
    • Mathematica: Various improvements (#2957)
    • meson: Add additional operators (#2919)
    • MySQL: Update keywords (#2970)
    • org-Mode: Support both schedule and deadline (#2899)
    • PHP: Add __PROPERTY__ magic constant (#2924), add reserved keywords (#3002)
    • PostgreSQL: Add more keywords (#2985)
    • protobuf: Fix namespace tokenization (#2929)
    • Python: Add t-string support (#2973, #3009, #3010)
    • Tablegen: Fix infinite loop (#2972, #2940)
    • Tera Term macro: Add commands introduced in v5.3 through v5.6 (#2951)
    • TOML: Support TOML 1.1.0 (#3026, #3027)
    • Turtle: Allow empty comment lines (#2980)
    • XML: Added .xbrl as file ending (#2890, #2891)
  • Drop Python 3.8, and add Python 3.14 as a supported version (#2987, #3012)

  • Various improvements to autopygmentize (#2894)

  • Update onedark style to support more token types (#2977)

  • Update rtt style to support more token types (#2895)

  • Cache entry points to improve performance (#2979)

  • Fix xterm-256 color table (#3043)

  • Fix kwargs dictionary getting mutated on each call (#3044)

2.21.0: 2.21.0

Compare source

Source

Source ref: master

  • New lexers:

  • Updated lexers:

    • Bash: Fix coloured keyword at the beginning of a name (#2926)
    • Boogie: Add missing Boogie and Civl Verifier keywords (#3156)
    • C#:
      • Recognize interpolated verbatim strings with either $@ or @$
        prefixes (#2685)
      • Support dollar-prefixed and multi-quote raw strings (#3129, #2897)
      • Recognize union (#3182)
    • C/C++:
      • Add C23/C++26 attributes (#3084)
      • Add more C2Y keywords (#3092)
      • Highlight a function following a namespace body (#2928)
      • Fix C/C++ lexer support for multiline pre-processor comments (#3051)
      • Add .ipp as a file extension (#3141, #1008)
    • Clojure: Recognize named, octal and unicode character literals such as
      \space and \o377 as a single token (#979)
    • Csound: Add missing opcode parameter type letter (#3161)
    • CUDA: Derive from the C++ lexer instead of C to highlight C++
      constructs such as template, class and namespace (#3127)
    • D: Allow non-ASCII (Unicode) identifiers (#1088)
    • Fish: Fix single quote backslash escape (#3138, #2821)
    • Go: Various lexer improvements (#3199)
    • GoogleSQL: Require a word break after SET (#3167)
    • Hexdump: Only match valid digits (#3200, #2847)
    • JavaScript: Highlight the arguments object (#3146)
    • Jsonnet: Recognize colons in array slice expressions (#2828)
    • JSX: Allow apostrophes in element text (#2816)
    • Julia: Fix rstrings backslash (#3140, #2537)
    • Kotlin: Support companion objects without an explicit name (#2525)
    • Kotlin: Don't let a nullable type marker (?) consume the following
      character, so Foo?, and a?:b tokenize correctly (#2964)
    • Kusto: Recognize member-access dots in dynamic objects (#2779)
    • Lua: Various improvements (#3143)
    • Macaulay2: Update symbols to 1.26.05 (#3120)
    • Markdown:
      • Highlight bold-italics (***...*** and ___...___) (#3067)
      • Fix mention regex to support hyphens in usernames (#3139, #3135)
    • Markdown, reStructuredText, TiddlyWiki5: Fix wrong token offsets for
      embedded code blocks (#3133)
    • Mathematica: Recognize \[Name] named-character escapes such as
      \[Nu] instead of emitting an Error token (#3097)
    • MATLAB, Octave, Scilab: Allow ... line continuations in function
      definition signatures (#659)
    • MySQL: Require a word break after SET (#3110)
    • PostgreSQL: Add more keywords (#3066)
    • Python:
      • Recognize sentinel (#3114)
      • Recognize frozendict (#3119)
      • Recognize lazy imports (#3115)
    • reStructuredText: Allow . and + in directive/role names (#3085)
    • Ruby: Don't duplicate the body of an unterminated heredoc (#2998)
    • Ruby: Treat << after ), ] or } as the shift operator
      rather than the start of a heredoc (#760)
    • SCSS: Recognize variable references in property values (#2818)
    • Shell: Recognize chevron prompts (#3096)
    • Smithy: Fix text blocks and add missing syntax (#3168)
    • Swift: Keep func a keyword in class func type methods (#1125)
    • Tcl: Stop $name variable references at a dash (#1720)
    • TeX: Recognize LaTeX math environments as math (#3034)
    • Twig: Allow uppercase letters at the start of identifiers (#3159, #2965)
    • TypeScript: Only treat module as a keyword when followed by
      whitespace, so identifiers like modules and module.exports
      are highlighted correctly (#2823)
    • Vala: Recognize verbatim strings before ordinary quoted strings (#2861)
    • Vala: Recognize conditional compilation directives (#2858)
    • Vim:
      • Bump the syntax file to vim 9.2 (#3183, #3174)
      • Small improvements to the VimScript lexer (#3173)
    • YAML: Add yml alias (#3169), recognize non-breaking spaces as valid
      scalar content (#2827)
    • WebAssembly: Recognize sign-extension operators (#2991, #3160)
    • XML: Mark SVG files as XML (#3093)
  • New styles:

  • Fix catastrophic backtracking in looks_like_xml (#2931, #3112)

  • Improve monokai theme colors (#3100)

  • Improve handling of non-string types in html_escape to fix broken clients (#3090, #3086)

  • LaTeX formatter: honor the wrapped lexer's stripnl and other input
    options when escapeinside is set, so blank lines are no longer stripped
    under stripnl=false (#2975)

  • RawTokenFormatter: fix a crash when error_color is set (#3215)

  • Groff formatter: don't duplicate a character when word-wrapping (wrap)
    a token that is not at the end of a line (#3201)

  • Add support for Python 3.15 (#3099)

  • Fix invalid -L values report success (#3217)

  • Allow transparent as a color style definition (#3180, #3170)

  • HtmlFormatter: " and ' now render literally (#3185)

pyrefly (1.2.0 → 1.3.1)

1.2.1

1.3.0

1.3.1

ruff (0.14.11 → 0.16.9)

0.14.12

0.14.13: 0.14.13

Compare source

Source

Release Notes

Released on 2026-01-15.

This is a follow-up release to 0.14.12. Because of an issue publishing the WASM packages, there is no GitHub release or Git tag for 0.14.12, although the package was published to PyPI. The contents of the 0.14.13 release are identical to 0.14.12.

0.14.12

Preview features

  • [flake8-blind-except] Allow more logging methods (BLE001) (#22057)
  • [ruff] Respect lint.pydocstyle.property-decorators in RUF066 (#22515)

Bug fixes

  • Fix configuration path in --show-settings (#22478)
  • Respect fmt: skip for multiple statements on the same logical line (#22119)

Rule changes

  • [pydocstyle] Update Rust crate imperative to v1.0.7 (D401) (#22519)
  • [isort] Insert imports in alphabetical order (I002) (#22493)

Documentation

  • Add llms.txt support for documentation (#22463)
  • Use prek in documentation and CI (#22505)
  • [flake8-pytest-style] Add check parameter example to PT017 docs (#22546)
  • [ruff] Make example error out-of-the-box (RUF103) (#22558)
  • [ruff] document RUF100 trailing comment fix behavior (#22479)

Other changes

  • wasm: Require explicit logging initialization (#22587)

Contributors

Install ruff 0.14.13

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-installer.ps1 | iex"

Download ruff 0.14.13

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

0.14.14: 0.14.14

Compare source

Source

Release Notes

Released on 2026-01-22.

Preview features

  • Preserve required parentheses in lambda bodies (#22747)
  • Combine range suppression code diagnostics (#22613)
  • [airflow] Second positional argument to Asset/Dataset should not be a dictionary (AIR303) (#22453)
  • [ruff] Detect duplicate entries in __all__ (RUF068) (#22114)

Bug fixes

  • [pyupgrade] Allow shadowing non-builtin bindings (UP029) (#22749)
  • [pyupgrade] Apply UP045 to string arguments of typing.cast (#22320)
  • [flake8-pie] Detect duplicated declared class fields in PIE794 (#22717)

Rule changes

Documentation

  • Add --exit-non-zero-on-format to formatter exit codes section (#22761)
  • Update contributing guide for adding a new rule (#22779)
  • [FastAPI] Document fix safety for FAST001 (#22655)
  • [flake8-async] Tweak explanation to focus on latency/efficiency tradeoff (ASYNC110) (#22715)
  • [pandas-vet] Make example error out-of-the-box (PD002) (#22561)
  • [refurb] Make the example work out of box (FURB101) (#22770)
  • [refurb] Make the example work out of box (FURB103) (#22769)

Contributors

Install ruff 0.14.14

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-installer.ps1 | iex"

Download ruff 0.14.14

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

0.15.0: 0.15.0

Breaking change detected.

Compare source

Source

Release Notes

Released on 2026-02-03.

Check out the blog post for a migration guide and overview of the changes!

Breaking changes

  • Ruff now formats your code according to the 2026 style guide. See the formatter section below or in the blog post for a detailed list of changes.

  • The linter now supports block suppression comments. For example, to suppress N803 for all parameters in this function:

    # ruff: disable[N803]
    def foo(
        legacyArg1,
        legacyArg2,
        legacyArg3,
        legacyArg4,
    ): ...
    # ruff: enable[N803]
    

    See the documentation for more details.

  • The ruff:alpine Docker image is now based on Alpine 3.23 (up from 3.21).

  • The ruff:debian and ruff:debian-slim Docker images are now based on Debian 13 "Trixie" instead of Debian 12 "Bookworm."

  • Binaries for the ppc64 (64-bit big-endian PowerPC) architecture are no longer included in our releases. It should still be possible to build Ruff manually for this platform, if needed.

  • Ruff now resolves all extended configuration files before falling back on a default Python version.

Stabilization

The following rules have been stabilized and are no longer in preview:

The following behaviors have been stabilized:

  • The --output-format flag is now respected when running Ruff in --watch mode, and the full output format is now used by default, matching the regular CLI output.
  • builtin-attribute-shadowing (A003) now detects the use of shadowed built-in names in additional contexts like decorators, default arguments, and other attribute definitions.
  • duplicate-union-member (PYI016) now considers typing.Optional when searching for duplicate union members.
  • split-static-string (SIM905) now offers an autofix when the maxsplit argument is provided, even without a sep argument.
  • dict-get-with-none-default (SIM910) now applies to more types of key expressions.
  • super-call-with-parameters (UP008) now has a safe fix when it will not delete comments.
  • unnecessary-default-type-args (UP043) now applies to stub (.pyi) files on Python versions before 3.13.

Formatter

This release introduces the new 2026 style guide, with the following changes:

  • Lambda parameters are now kept on the same line and lambda bodies will be parenthesized to let them break across multiple lines (#21385)
  • Parentheses around tuples of exceptions in except clauses will now be removed on Python 3.14 and later (#20768)
  • A single empty line is now permitted at the beginning of function bodies (#21110)
  • Parentheses are avoided for long as captures in match statements (#21176)
  • Extra spaces between escaped quotes and ending triple quotes can now be omitted (#17216)
  • Blank lines are now enforced before classes with decorators in stub files (#18888)

Preview features

Bug fixes

  • Fix suppression indentation matching (#22903)

Rule changes

  • Customize where the fix_title sub-diagnostic appears (#23044)
  • [FastAPI] Add sub-diagnostic explaining why a fix was unavailable (FAST002) (#22565)
  • [flake8-annotations] Don't suggest NoReturn for functions raising NotImplementedError (ANN201, ANN202, ANN205, ANN206) (#21311)
  • [pyupgrade] Make fix unsafe if it deletes comments (UP017) (#22873)
  • [pyupgrade] Make fix unsafe if it deletes comments (UP020) (#22872)
  • [pyupgrade] Make fix unsafe if it deletes comments (UP033) (#22871)
  • [refurb] Do not add abc.ABC if already present (FURB180) (#22234)
  • [refurb] Make fix unsafe if it deletes comments (FURB110) (#22768)
  • [ruff] Add sub-diagnostics with permissions (RUF064) (#22972)

Server

  • Identify notebooks by LSP didOpen instead of .ipynb file extension (#22810)

CLI

  • Add --color CLI option to force colored output (#22806)

Documentation

  • Document - stdin convention in CLI help text (#22817)
  • [refurb] Change example to re.search with ^ anchor (FURB167) (#22984)
  • Fix link to Sphinx code block directives (#23041)
  • [pydocstyle] Clarify which quote styles are allowed (D300) (#22825)
  • [flake8-bugbear] Improve docs for no-explicit-stacklevel (B028) (#22538)

Other changes

  • Update MSRV to 1.91 (#22874)

Contributors

Install ruff 0.15.0

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-installer.ps1 | iex"

Download ruff 0.15.0

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

0.15.1: 0.15.1

Compare source

Source

Release Notes

Released on 2026-02-12.

Preview features

  • [airflow] Add ruff rules to catch deprecated Airflow imports for Airflow 3.1 (AIR321) (#22376)
  • [airflow] Third positional parameter not named ti_key should be flagged for BaseOperatorLink.get_link (AIR303) (#22828)
  • [flake8-gettext] Fix false negatives for plural argument of ngettext (INT001, INT002, INT003) (#21078)
  • [pyflakes] Fix infinite loop in preview fix for unused-import (F401) (#23038)
  • [pygrep-hooks] Detect non-existent mock methods in standalone expressions (PGH005) (#22830)
  • [pylint] Allow dunder submodules and improve diagnostic range (PLC2701) (#22804)
  • [pyupgrade] Improve diagnostic range for tuples (UP024) (#23013)
  • [refurb] Check subscripts in tuple do not use lambda parameters in reimplemented-operator (FURB118) (#23079)
  • [ruff] Detect mutable defaults in field calls (RUF008) (#23046)
  • [ruff] Ignore std cmath.inf (RUF069) (#23120)
  • [ruff] New rule float-equality-comparison (RUF069) (#20585)
  • Don't format unlabeled Markdown code blocks (#23106)
  • Markdown formatting support in LSP (#23063)
  • Support Quarto Markdown language markers (#22947)
  • Support formatting pycon Markdown code blocks (#23112)
  • Use extension mapping to select Markdown code block language (#22934)

Bug fixes

  • Avoid false positive for undefined variables in FAST001 (#23224)
  • Avoid introducing syntax errors for FAST003 autofix (#23227)
  • Avoid suggesting InitVar for __post_init__ that references PEP 695 type parameters (#23226)
  • Deduplicate type variables in generic functions (#23225)
  • Fix exception handler parenthesis removal for Python 3.14+ (#23126)
  • Fix f-string middle panic when parsing t-strings (#23232)
  • Wrap RUF020 target for multiline fixes (#23210)
  • Wrap UP007 target for multiline fixes (#23208)
  • Fix missing diagnostics for last range suppression in file (#23242)
  • [pyupgrade] Fix syntax error on string with newline escape and comment (UP037) (#22968)

Rule changes

  • Use ruff instead of Ruff as the program name in GitHub output format (#23240)
  • [PT006] Fix syntax error when unpacking nested tuples in parametrize fixes (#22441) (#22464)
  • [airflow] Catch deprecated attribute access from context key for Airflow 3.0 (AIR301) (#22850)
  • [airflow] Capture deprecated arguments and a decorator (AIR301) (#23170)
  • [flake8-boolean-trap] Add multiprocessing.Value to excluded functions for FBT003 (#23010)
  • [flake8-bugbear] Add a secondary annotation showing the previous occurrence (B033) (#22634)
  • [flake8-type-checking] Add sub-diagnostic showing the runtime use of an annotation (TC004) (#23091)
  • [isort] Support configurable import section heading comments (#23151)
  • [ruff] Improve the diagnostic for RUF012 (#23202)

Formatter

  • Suppress diagnostic output for format --check --silent (#17736)

Documentation

  • Add tabbed shell completion documentation (#23169)
  • Explain how to enable Markdown formatting for pre-commit hook (#23077)
  • Fixed import in runtime-evaluated-decorators example (#23187)
  • Update ruff server contributing guide (#23060)

Other changes

  • Exclude WASM artifacts from GitHub releases (#23221)

Contributors

Install ruff 0.15.1

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-installer.ps1 | iex"

Download ruff 0.15.1

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

0.15.2: 0.15.2

Compare source

Source

Release Notes

Released on 2026-02-19.

Preview features

Bug fixes

  • [flake8-async] Fix in_async_context logic (#23426)
  • [ruff] Fix for RUF102 should delete entire comment (#23380)
  • [ruff] Suppress diagnostic for strings with backslashes in interpolations before Python 3.12 (RUF027) (#21069)
  • [flake8-bugbear] Fix B023 false positive for immediately-invoked lambdas (#23294)
  • [parser] Fix false syntax error for match-like annotated assignments (#23297)
  • [parser] Fix indentation tracking after line continuations (#23417)

Rule changes

  • [flake8-executable] Allow global flags in uv shebangs (EXE003) (#22582)
  • [pyupgrade] Fix handling of typing.{io,re} (UP035) (#23131)
  • [ruff] Detect PLC0207 on chained str.split() calls (#23275)

CLI

  • Remove invalid inline noqa warning (#23270)

Configuration

  • Add extension mapping to configuration file options (#23384)

Documentation

  • Add Q004 to the list of conflicting rules (#23340)
  • [ruff] Expand lint.external docs and add sub-diagnostic (RUF100, RUF102) (#23268)

Contributors

Install ruff 0.15.2

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-installer.ps1 | iex"

Download ruff 0.15.2

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.15.3: 0.15.3

Compare source

Source

Release Notes

Released on 2026-02-26.

Preview features

  • Drop explicit support for .qmd file extension (#23572)

    This can now be enabled instead by setting the extension option:

    # ruff.toml
    extension = { qmd = "markdown" }
    
    # pyproject.toml
    [tool.ruff]
    extension = { qmd = "markdown" }
    
  • Include configured extensions in file discovery (#23400)

  • [flake8-bandit] Allow suspicious imports in TYPE_CHECKING blocks (S401-S415) (#23441)

  • [flake8-bugbear] Allow B901 in pytest hook wrappers (#21931)

  • [flake8-import-conventions] Add missing conventions from upstream (ICN001, ICN002) (#21373)

  • [pydocstyle] Add rule to enforce docstring section ordering (D420) (#23537)

  • [pylint] Implement swap-with-temporary-variable (PLR1712) (#22205)

  • [ruff] Add unnecessary-assign-before-yield (RUF070) (#23300)

  • [ruff] Support file-level noqa in RUF102 (#23535)

  • [ruff] Suppress diagnostic for invalid f-strings before Python 3.12 (RUF027) (#23480)

  • [flake8-bandit] Don't flag BaseLoader/CBaseLoader as unsafe (S506) (#23510)

Bug fixes

  • Avoid infinite loop between I002 and PYI025 (#23352)
  • [pyflakes] Fix false positive for @overload from lint.typing-modules (F811) (#23357)
  • [pyupgrade] Fix false positive for TypeVar default before Python 3.12 (UP046) (#23540)
  • [pyupgrade] Fix handling of \N in raw strings (UP032) (#22149)

Rule changes

  • Render sub-diagnostics in the GitHub output format (#23455)

  • [flake8-bugbear] Tag certain B007 diagnostics as unnecessary (#23453)

  • [ruff] Ignore unknown rule codes in RUF100 (#23531)

    These are now flagged by RUF102 instead.

Documentation

  • Fix missing settings links for several linters (#23519)
  • Update isort action comments heading (#23515)
  • [pydocstyle] Fix double comma in description of D404 (#23440)

Other changes

  • Update the Python module (notably find_ruff_bin) for parity with uv (#23406)

Contributors

Install ruff 0.15.3

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-installer.ps1 | iex"

Download ruff 0.15.3

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.15.4: 0.15.4

Compare source

Source

Release Notes

Released on 2026-02-26.

This is a follow-up release to 0.15.3 that resolves a panic when the new rule PLR1712 was enabled with any rule that analyzes definitions, such as many of the ANN or D rules.

Bug fixes

  • Fix panic on access to definitions after analyzing definitions (#23588)
  • [pyflakes] Suppress false positive in F821 for names used before del in stub files (#23550)

Documentation

  • Clarify first-party import detection in Ruff (#23591)
  • Fix incorrect import-heading example (#23568)

Contributors

Install ruff 0.15.4

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-installer.ps1 | iex"

Download ruff 0.15.4

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.15.5: 0.15.5

Compare source

Source

Release Notes

Released on 2026-03-05.

Preview features

  • Discover Markdown files by default in preview mode (#23434)
  • [perflint] Extend PERF102 to comprehensions and generators (#23473)
  • [refurb] Fix FURB101 and FURB103 false positives when I/O variable is used later (#23542)
  • [ruff] Add fix for none-not-at-end-of-union (RUF036) (#22829)
  • [ruff] Fix false positive for re.split with empty string pattern (RUF055) (#23634)

Bug fixes

  • [fastapi] Handle callable class dependencies with __call__ method (FAST003) (#23553)
  • [pydocstyle] Fix numpy section ordering (D420) (#23685)
  • [pyflakes] Fix false positive for names shadowing re-exports (F811) (#23356)
  • [pyupgrade] Avoid inserting redundant None elements in UP045 (#23459)

Documentation

  • Document extension mapping for Markdown code formatting (#23574)
  • Update default Python version examples (#23605)

Other changes

  • Publish releases to Astral mirror (#23616)

Contributors

Install ruff 0.15.5

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-installer.ps1 | iex"

Download ruff 0.15.5

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.15.6: 0.15.6

Compare source

Source

Release Notes

Released on 2026-03-12.

Preview features

  • Add support for lazy import parsing (#23755)
  • Add support for star-unpacking of comprehensions (PEP 798) (#23788)
  • Reject semantic syntax errors for lazy imports (#23757)
  • Drop a few rules from the preview default set (#23879)
  • [airflow] Flag Variable.get() calls outside of task execution context (AIR003) (#23584)
  • [airflow] Flag runtime-varying values in DAG/task constructor arguments (AIR304) (#23631)
  • [flake8-bugbear] Implement delattr-with-constant (B043) (#23737)
  • [flake8-tidy-imports] Add TID254 to enforce lazy imports (#23777)
  • [flake8-tidy-imports] Allow users to ban lazy imports with TID254 (#23847)
  • [isort] Retain lazy keyword when sorting imports (#23762)
  • [pyupgrade] Add from __future__ import annotations automatically (UP006) (#23260)
  • [refurb] Support newline parameter in FURB101 for Python 3.13+ (#23754)
  • [ruff] Add os-path-commonprefix (RUF071) (#23814)
  • [ruff] Add unsafe fix for os-path-commonprefix (RUF071) (#23852)
  • [ruff] Limit RUF036 to typing contexts; make it unsafe for non-typing-only (#23765)
  • [ruff] Use starred unpacking for RUF017 in Python 3.15+ (#23789)

Bug fixes

  • Fix --add-noqa creating unwanted leading whitespace (#23773)
  • Fix --add-noqa breaking shebangs (#23577)
  • [formatter] Fix lambda body formatting for multiline calls and subscripts (#23866)
  • [formatter] Preserve required annotation parentheses in annotated assignments (#23865)
  • [formatter] Preserve type-expression parentheses in the formatter (#23867)
  • [flake8-annotations] Fix stack overflow in ANN401 on quoted annotations with escape sequences (#23912)
  • [pep8-naming] Check naming conventions in match pattern bindings (N806, N815, N816) (#23899)
  • [perflint] Fix comment duplication in fixes (PERF401, PERF403) (#23729)
  • [pyupgrade] Properly trigger super change in nested class (UP008) (#22677)
  • [ruff] Avoid syntax errors in RUF036 fixes (#23764)

Rule changes

  • [flake8-bandit] Flag S501 with requests.request (#23873)
  • [flake8-executable] Fix WSL detection in non-Docker containers (#22879)
  • [flake8-print] Ignore pprint calls with stream= (#23787)

Documentation

  • Update docs for Markdown code block formatting (#23871)
  • [flake8-bugbear] Fix misleading description for B904 (#23731)

Contributors

Install ruff 0.15.6

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-installer.ps1 | iex"

Download ruff 0.15.6

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.15.7: 0.15.7

Compare source

Source

Release Notes

Released on 2026-03-19.

Preview features

  • Display output severity in preview (#23845)
  • Don't show noqa hover for non-Python documents (#24040)

Rule changes

  • [pycodestyle] Recognize pyrefly: as a pragma comment (E501) (#24019)

Server

  • Don't return code actions for non-Python documents (#23905)

Documentation

  • Add company AI policy to contributing guide (#24021)
  • Document editor features for Markdown code formatting (#23924)
  • [pylint] Improve phrasing (PLC0208) (#24033)

Other changes

  • Use PEP 639 license information (#19661)

Contributors

Install ruff 0.15.7

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-installer.ps1 | iex"

Download ruff 0.15.7

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.15.8: 0.15.8

Compare source

Source

Release Notes

Released on 2026-03-26.

Preview features

  • [ruff] New rule unnecessary-if (RUF050) (#24114)
  • [ruff] New rule useless-finally (RUF072) (#24165)
  • [ruff] New rule f-string-percent-format (RUF073): warn when using % operator on an f-string (#24162)
  • [pyflakes] Recognize frozendict as a builtin for Python 3.15+ (#24100)

Bug fixes

  • [flake8-async] Use fully-qualified anyio.lowlevel import in autofix (ASYNC115) (#24166)
  • [flake8-bandit] Check tuple arguments for partial paths in S607 (#24080)
  • [pyflakes] Skip undefined-name (F821) for conditionally deleted variables (#24088)
  • E501/W505/formatter: Exclude nested pragma comments from line width calculation (#24071)
  • Fix %foo? parsing in IPython assignment expressions (#24152)
  • analyze graph: resolve string imports that reference attributes, not just modules (#24058)

Rule changes

  • [eradicate] ignore ty: ignore comments in ERA001 (#24192)
  • [flake8-bandit] Treat sys.executable as trusted input in S603 (#24106)
  • [flake8-self] Recognize Self annotation and self assignment in SLF001 (#24144)
  • [pyflakes] F507: Fix false negative for non-tuple RHS in %-formatting (#24142)
  • [refurb] Parenthesize generator arguments in FURB142 fixer (#24200)

Performance

  • Speed up diagnostic rendering (#24146)

Server

  • Warn when Markdown files are skipped due to preview being disabled (#24150)

Documentation

  • Clarify extend-ignore and extend-select settings documentation (#24064)
  • Mention AI policy in PR template (#24198)

Other changes

  • Use trusted publishing for NPM packages (#24171)

Contributors

Install ruff 0.15.8

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-installer.ps1 | iex"

Download ruff 0.15.8

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.15.9: 0.15.9

Compare source

Source

Release Notes

Released on 2026-04-02.

Preview features

  • [pyflakes] Flag annotated variable redeclarations as F811 in preview mode (#24244)
  • [ruff] Allow dunder-named assignments in non-strict mode for RUF067 (#24089)

Bug fixes

  • [flake8-errmsg] Avoid shadowing existing msg in fix for EM101 (#24363)
  • [flake8-simplify] Ignore pre-initialization references in SIM113 (#24235)
  • [pycodestyle] Fix W391 fixes for consecutive empty notebook cells (#24236)
  • [pyupgrade] Fix UP008 nested class matching (#24273)
  • [pyupgrade] Ignore strings with string-only escapes (UP012) (#16058)
  • [ruff] RUF072: skip formfeeds on dedent (#24308)
  • [ruff] Avoid re-using symbol in RUF024 fix (#24316)
  • [ruff] Parenthesize expression in RUF050 fix (#24234)
  • Disallow starred expressions as values of starred expressions (#24280)

Rule changes

  • [flake8-simplify] Suppress SIM105 for except* before Python 3.12 (#23869)
  • [pyflakes] Extend F507 to flag %-format strings with zero placeholders (#24215)
  • [pyupgrade] UP018 should detect more unnecessarily wrapped literals (UP018) (#24093)
  • [pyupgrade] Fix UP008 callable scope handling to support lambdas (#24274)
  • [ruff] RUF010: Mark fix as unsafe when it deletes a comment (#24270)

Formatter

  • Add nested-string-quote-style formatting option (#24312)

Documentation

  • [flake8-bugbear] Clarify RUF071 fix safety for non-path string comparisons (#24149)
  • [flake8-type-checking] Clarify import cycle wording for TC001/TC002/TC003 (#24322)

Other changes

  • Avoid rendering fix lines with trailing whitespace after | (#24343)

Contributors

Install ruff 0.15.9

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-installer.ps1 | iex"

Download ruff 0.15.9

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.15.10: 0.15.10

Compare source

Source

Release Notes

Released on 2026-04-09.

Preview features

  • [flake8-logging] Allow closures in except handlers (LOG004) (#24464)
  • [flake8-self] Make SLF diagnostics robust to non-self-named variables (#24281)
  • [flake8-simplify] Make the fix for collapsible-if safe in preview (SIM102) (#24371)

Bug fixes

  • Avoid emitting multi-line f-string elements before Python 3.12 (#24377)
  • Avoid syntax error from E502 fixes in f-strings and t-strings (#24410)
  • Strip form feeds from indent passed to dedent_to (#24381)
  • [pyupgrade] Fix panic caused by handling of octals (UP012) (#24390)
  • Reject multi-line f-string elements before Python 3.12 (#24355)

Rule changes

  • [ruff] Treat f-string interpolation as potential side effect (RUF019) (#24426)

Server

  • Add support for custom file extensions (#24463)

Documentation

  • Document adding fixes in CONTRIBUTING.md (#24393)
  • Fix JSON typo in settings example (#24517)

Contributors

Install ruff 0.15.10

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-installer.ps1 | iex"

Download ruff 0.15.10

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.15.11: 0.15.11

Compare source

Source

Release Notes

Released on 2026-04-16.

Preview features

  • [ruff] Ignore RUF029 when function is decorated with asynccontextmanager (#24642)
  • [airflow] Implement airflow-xcom-pull-in-template-string (AIR201) (#23583)
  • [flake8-bandit] Fix S103 false positives and negatives in mask analysis (#24424)

Bug fixes

  • [flake8-async] Omit overridden methods for ASYNC109 (#24648)

Documentation

  • [flake8-async] Add override mention to ASYNC109 docs (#24666)
  • Update Neovim config examples to use vim.lsp.config (#24577)

Contributors

Install ruff 0.15.11

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-installer.ps1 | iex"

Download ruff 0.15.11

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.15.12: 0.15.12

Compare source

Source

Release Notes

Released on 2026-04-24.

Preview features

  • Implement #ruff:file-ignore file-level suppressions (#23599)
  • Implement #ruff:ignore logical-line suppressions (#23404)
  • Revert preview changes to displayed diagnostic severity in LSP (#24789)
  • [airflow] Implement task-branch-as-short-circuit (AIR004) (#23579)
  • [flake8-bugbear] Fix break/continue handling in loop-iterator-mutation (B909) (#24440)
  • [pylint] Fix PLC2701 for type parameter scopes (#24576)

Rule changes

  • [pandas-vet] Suggest .array as well in PD011 (#24805)

CLI

  • Respect default Unix permissions for cache files (#24794)

Documentation

  • [pylint] Fix PLR0124 description not to claim self-comparison always returns the same value (#24749)
  • [pyupgrade] Expand docs on reusable TypeVars and scoping (UP046) (#24153)
  • Improve rules table accessibility (#24711)

Contributors

Install ruff 0.15.12

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-installer.ps1 | iex"

Download ruff 0.15.12

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.15.13: 0.15.13

Compare source

Source

Release Notes

Released on 2026-05-14.

Preview features

  • Add a rule to flag lazy imports that are eagerly evaluated (#25016)
  • [pylint] Standardize diagnostic message (PLR0914, PLR0917) (#24996)

Bug fixes

  • Fix F811 false positive for class methods (#24933)
  • Fix setting selection for multi-folder workspace (#24819)
  • [eradicate] Fix false positive for lines with leading whitespace (ERA001) (#25122)
  • [flake8-pyi] Fix false positive for f-string debug specifier (PYI016) (#24098)

Rule changes

  • Always include panic payload in panic diagnostic message (#24873)
  • Restrict PYI034 for in-place operations to enclosing class (#24511)
  • Improve error message for parameters that are declared global (#24902)
  • Update known stdlib (#25103)

Performance

  • [isort] Avoid constructing glob::Patterns for literal known modules (#25123)

CLI

  • Add TOML examples to --config help text (#25013)
  • Colorize ruff check 'All checks passed' (#25085)

Configuration

  • Increase max allowed value of line-length setting (#24962)

Documentation

  • Add D203 to rules that conflict with the formatter (#25044)
  • Clarify COM819 and formatter interaction (#25045)
  • Clarify that NotImplemented is a value, not an exception (F901) (#25054)
  • Update number of lint rules supported (#24942)

Other changes

  • Simplify the playground's markdown template (#24924)

Contributors

Install ruff 0.15.13

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-installer.ps1 | iex"

Download ruff 0.15.13

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.15.14: 0.15.14

Compare source

Source

Release Notes

Released on 2026-05-21.

Preview features

  • [airflow] Implement airflow-task-implicit-multiple-outputs (AIR202) (#25152)
  • [flake8-use-pathlib] Mark PTH101 fix as unsafe when first argument is a class attribute annotated as int (#25086)
  • [pylint] Implement too-many-try-statements (W0717) (#23970)
  • [ruff] Add incorrect-decorator-order (RUF074) (#23461)
  • [ruff] Add fallible-context-manager (RUF075) (#22844)

Bug fixes

  • Fix lambda formatting in interpolated string expressions (#25144)
  • Treat generic frozenset annotations as immutable (#25251)
  • [flake8-type-checking] Avoid strict behavior when future-annotations are enabled (TC001, TC002, TC003) (#25035)
  • [pylint] Avoid false positives in else clause (PLR1733) (#25177)

Rule changes

  • [flake8-comprehensions] Skip C417 for lambdas with positional-only parameters (#25272)
  • [flake8-simplify] Preserve f-string source verbatim in SIM101 fix (#25061)

Performance

  • Avoid unnecessary parser lookahead for operators (#25290)

Documentation

  • Update code example setting Neovim LSP log level (#25284)

Other changes

  • Add full PEP 798 support (#25104)
  • Add a parser recursion limit (#24810)
  • Update various ruff_python_stdlib APIs (#25273)

Contributors

Install ruff 0.15.14

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-installer.ps1 | iex"

Download ruff 0.15.14

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.15.15: 0.15.15

Compare source

Source

Release Notes

Released on 2026-05-28.

Preview features

  • Fix Markdown closing fence handling (#25310)
  • [pyflakes] Report duplicate imports in typing.TYPE_CHECKING block (F811) (#22560)

Bug fixes

  • [pyflakes] Treat function-scope bare annotations as locals per PEP 526 (F821) (#21540)

Performance

  • Avoid redundant TokenValue drops in the lexer (#25300)
  • Reduce memory usage by dropping token-excess capacity and improve performance by approximating the initial tokens Vec size (#25354)
  • Use ThinVec in AST to shrink Stmt (#25361)

Documentation

  • Fix line-length example for --config option (#25389)
  • [flake8-comprehensions] Document RecursionError edge case in __len__ (C416) (#25286)
  • [mccabe] Improve example (C901) (#25287)
  • [pyupgrade] Clarify fix safety docs (UP007, UP045) (#25288)
  • [refurb] Document FURB192 exception change for empty sequences (#25317)
  • [ruff] Document false negative for user-defined types (RUF013) (#25289)

Formatter

  • Fix formatting of lambdas nested within f-strings (#25398)

Server

  • Return code action for codeAction/resolve requests that contain no or no valid URL (#25365)

Other changes

  • Expand semantic syntax errors for invalid walruses (#25415)

Contributors

Install ruff 0.15.15

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-installer.ps1 | iex"

Download ruff 0.15.15

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.15.16: 0.15.16

Compare source

Source

Release Notes

Released on 2026-06-04.

Preview features

  • [flake8-async] Implement yield-in-context-manager-in-async-generator (ASYNC119) (#24644)
  • [pylint] Narrow diagnostic range and exclude cases without exception handlers (PLW0717) (#25440)
  • [ruff] Treat yield before break from a terminal loop as terminal (RUF075) (#25447)

Bug fixes

  • [eradicate] Avoid flagging ruff:ignore comments as code (ERA001) (#25537)
  • [eradicate] Fix ERA001/RUF100 conflict when noqa is on commented-out code (#25414)
  • [pyflakes] Avoid removing the format call when it would change behavior (F523) (#25320)
  • [pylint] Avoid syntax errors in invalid character replacements in f-strings before Python 3.12 (PLE2510, PLE2512, PLE2513, PLE2514, PLE2515) (#25544)
  • [pyupgrade] Avoid converting format calls with more kinds of side effects (UP032) (#25484)

Rule changes

  • [flake8-pytest-style] Avoid fixes for ambiguous argnames and argvalues combinations (PT006) (#24776)

Performance

  • Drop excess capacity from statement suites during parsing (#25368)

Documentation

  • [pydocstyle] Improve discoverability of rules enabled for each convention (#24973)
  • [ruff] Restore example code for Python versions before 3.15 (RUF017) (#25439)
  • Fix typo bin/active → bin/activate in tutorial (#25473)

Other changes

  • Shrink additional parser AST collections (#25465)

Contributors

Install ruff 0.15.16

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-installer.ps1 | iex"

Download ruff 0.15.16

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.15.17: 0.15.17

Compare source

Source

Release Notes

Released on 2026-06-11.

Preview features

  • Allow human-readable names in suppression comments (#25614)
  • Fix handling of ignore comments within a disable/enable pair (#25845)
  • Prioritize human-readable names in CLI output (#25869)
  • Respect diagnostic start and parent ranges and trailing comments in ruff:ignore suppressions (#25673)
  • [flake8-async] Add trio.as_safe_channel to safe decorators (ASYNC119) (#25775)
  • [flake8-pytest-style] Also check pytest_asyncio fixtures (#25375)
  • [ruff] Ban pytest autouse fixtures (RUF076) (#25477)
  • [pyupgrade] Add from __future__ import annotations automatically (UP007, UP045) (#23259)

Bug fixes

  • Fix diagnostic when ruff:enable or ruff:disable appears where ruff:ignore is expected (#25700)
  • [pyupgrade] Preserve leading empty literals to avoid syntax errors (UP032) (#25491)

Rule changes

  • [flake8-pytest-style] Clarify diagnostic message for single parameters (PT007) (#25592)
  • [numpy] Drop autofix for np.in1d (NPY201) (#25612)
  • [pylint] Exempt Python version comparisons (PLR2004) (#25743)

Performance

  • Reserve AST Vecs with correct capacity for common cases (#25451)

Formatter

  • Preserve whitespace for Quarto cell option comments (#25641)

CLI

  • Allow rule names in ruff rule (#25640)

Other changes

  • Fix playground diagnostics scrollbars (#25642)

Contributors

Install ruff 0.15.17

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-installer.ps1 | iex"

Download ruff 0.15.17

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.15.18: 0.15.18

Compare source

Source

Release Notes

Released on 2026-06-18.

Preview features

  • Handle nested ruff:ignore comments (#25791)
  • Stop displaying severity in output (#26050)
  • Use human-readable names in CLI output (#25937)
  • Use human-readable names in LSP and playground diagnostics (#26058)
  • [pydocstyle] Prevent property docstrings starting with verbs (D421) (#23775)
  • [flake8-pyi] Extend PYI033 to Python files (#26129)

Bug fixes

  • Detect equivalent numeric mapping keys (#26009)
  • Detect mapping keys equivalent to booleans (#25982)
  • Detect repeated signed and complex dictionary keys (#26007)

Rule changes

  • [flake8-pyi] Rename PYI033 to legacy-type-comment (#26131)

Performance

  • Use ThinVec for call keywords (#25999)
  • Inline parser recovery context checks (#26038)
  • Match parser keywords as bytes (#26037)
  • Move value parsing out of lexing (#25360)

Server

  • Render subdiagnostics and secondary annotations as related information (#26011)

Documentation

  • Update fix availability for always-fixable rules (#26091)
  • [flake8-tidy-imports] Add fix safety section (TID252) (#17491)

Parser

  • Reject __debug__ lambda parameters (#26022)
  • Reject _ as a match-pattern target (#25977)
  • Reject multiple starred names in sequence patterns (#25976)
  • Reject parenthesized star imports (#26021)
  • Reject starred comprehension targets (#26023)
  • Reject unparenthesized generator expressions in class bases (#25978)
  • Reject yield expressions after commas (#26024)
  • Validate function type parameter default order (#25981)

Playground

  • Make diagnostic links clickable (#26104)
  • Use diagnostic tags (#26105)

Contributors

Install ruff 0.15.18

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-installer.ps1 | iex"

Download ruff 0.15.18

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.15.19: 0.15.19

Compare source

Source

Release Notes

Released on 2026-06-23.

Preview features

  • Support human-readable names when hovering suppression comments and in code actions (#26114)

Bug fixes

  • Fall back to default settings when editor-only settings are invalid (#26244)
  • Fix panic when inserting text at a notebook cell boundary (#26111)

Rule changes

  • [pylint] Update fix suggestions for __floor__, __trunc__, __length_hint__, and __matmul__ variants (PLC2801) (#26239)

Performance

  • Avoid allocating when parsing single string literals (#26200)
  • Avoid reallocating singleton call arguments (#26223)
  • Lazily create source files for lint diagnostics (#26226)
  • Optimize formatter text width and indentation (#26236)
  • Reserve capacity for builtin bindings (#26229)
  • Skip repeated-key checks for singleton dictionaries (#26228)
  • Use ArrayVec for qualified name segments (#26224)

Documentation

  • [flake8-pyi] Note that PYI051 is an opinionated stylistic rule (#26179)
  • [pyupgrade] Clarify UP029 as a Python 2 compatibility rule (#26243)

Other changes

  • Publish Ruff crates to crates.io (#26271)

Contributors

Install ruff 0.15.19

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-installer.ps1 | iex"

Download ruff 0.15.19

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.15.20: 0.15.20

Compare source

Source

Release Notes

Released on 2026-06-25.

Preview features

  • Allow human-readable names in rule selectors (#25887)
  • Emit a warning instead of an error for unknown rule selectors (#26113)
  • Match noqa shebang handling in ruff:ignore comments (#26286)
  • [ruff] Remove pytest-fixture-autouse (RUF076) (#26240, #26371)

Documentation

  • Add versioning sections to custom crate READMEs (#26317)
  • Update ruff_python_parser README for crates.io (#26315)
  • [perflint] Clarify that PERF402 applies to any iterable (#26242)

Contributors

Install ruff 0.15.20

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-installer.ps1 | iex"

Download ruff 0.15.20

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.15.21: 0.15.21

Compare source

Source

Release Notes

Released on 2026-07-09.

Preview features

  • Add --add-ignore for adding ruff:ignore comments (#26346)
  • [flake8-comprehensions] Drop C409 tuple comprehension preview behavior (#25707)
  • Avoid whitespace normalization when formatting comments (#26455)
  • [pyupgrade] Lint and fix use of deprecated abc decorators (UP051) (#26417)

Bug fixes

  • Refine non-empty f-string detection (#26526)
  • Detect syntax errors in individual notebook cells (#26419)
  • [flake8-implicit-str-concat] Fix ISC003 autofix incorrectly stripping + from comments (#26554)

Rule changes

  • [flake8-executable] Mark EXE004 fix as unsafe (#26033)
  • [flake8-pyi] Mark PYI061 fixes as unsafe in Python files (#26533)
  • [pydocstyle] Skip overload-with-docstring in stub files (D418) (#26318)

Performance

  • Avoid per-token source index visitor calls (#26506)
  • Cache parenthesized expression boundaries in the formatter (#26344)
  • Improve performance of rendering edits in preview mode (#26565)
  • Inline fits_element in formatter (#26429)
  • Inline formatter printing hot paths (#26504)
  • Lazily create builtin bindings (#26510)
  • Skip empty trivia scans in the source indexer (#26507)
  • Use ICF for macOS release builds (#25780)

Formatter

  • Add --extend-exclude to ruff format (#26372)

Documentation

  • Add "How does Ruff's import sorting compare to isort?" link to README (#26530)
  • Fix Mozilla Firefox repository link in README (#26537)
  • [flake8-bandit] Fix misleading docstring for mako-templates (S702) (#26432)
  • [ruff] Fix non-triggering example for if-key-in-dict-del (RUF051) (#26433)

Contributors

Install ruff 0.15.21

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-installer.ps1 | iex"

Download ruff 0.15.21

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.15.22: 0.15.22

Compare source

Source

Release Notes

Released on 2026-07-16.

Preview features

  • [pycodestyle] Add an autofix for E402 (#22212)
  • [refurb] Allow subclassing builtins in stub files (FURB189) (#26812)
  • [ruff] Add rule to replace noqa comments with ruff:ignore (RUF105) (#26423)
  • [ruff] Add rule to use human-readable names in ruff:ignore comments (RUF106) (#26682)
  • [ruff] Add rule to use human-readable names in configuration selectors (RUF201) (#26772)

Bug fixes

  • [flake8-pyi] Fix false positive in __all__ (PYI053) (#26872)

Rule changes

  • [pylint] Ignore mutable type updates in redefined-loop-name (PLW2901) (#25733)

Performance

  • Avoid redundant lexer token bookkeeping (#26765)
  • Avoid redundant pending-indentation writes (#26774)
  • Avoid unnecessary identifier lookahead (#26525)
  • Reuse parser scratch buffers (#26798)

Documentation

  • Document argfile support (#26803)
  • [flake8-datetimez] Clarify naming guidance for datetime.today (DTZ002) (#26658)
  • [pycodestyle] Document E731 fix safety (#26847)
  • [ruff] Clarify intentional async contexts for unused-async (RUF029) (#26641)

Contributors

Install ruff 0.15.22

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-installer.ps1 | iex"

Download ruff 0.15.22

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.16.0: 0.16.0

Breaking change detected.

Compare source

Source

Release Notes

Released on 2026-07-23.

Check out the blog post for a migration guide and overview of the changes!

Breaking changes

  • Ruff now enables a much larger set of rules by default (413, up from 59). See the blog post for more details and the new Default Rules page for a full listing of the enabled rules. Note that this is primarily an expansion, but 18 of the more opinionated pycodestyle (E) and pyflakes (F) rules have been removed from the default set: E401, E402, E701, E702, E703, E711, E712, E713, E714, E721, E731, E741, E742, E743, F403, F405, F406, and F722.

  • Ruff can now format Python code blocks in Markdown files and will do this by default. See the documentation for more details.

  • Ruff now supports ruff: ignore comments at the ends of lines, like noqa comments, or on the line preceding a diagnostic. For example, these both suppress an unused-import (F401) diagnostic:

    import math  # ruff: ignore[F401]
    
    # ruff: ignore[F401]
    import os
    
  • Fixes are now shown in check and format --check output:

    ❯ ruff format --check .
    unformatted: File would be reformatted
     --> try.md:1:1
      |
    1 | ```python
      - import   math
    2 + import math
    3 | ```
      |
    
    1 file would be reformatted
    

    This example also shows off the Markdown formatting.

  • format --check now supports the same output formats as the linter, including the github and gitlab outputs for rendering annotations in CI:

    ❯ ruff format --check --output-format github .
    ::error title=ruff (unformatted),file=try.md,line=2,col=8,endLine=2,endColumn=10::try.md:2:8: unformatted: File would be reformatted
    

    See the CLI help or documentation for the full list of supported formats.

  • The filename, location, end_location, fix.edits[].location, and fix.edits[].end_location fields in the JSON output format may now be null rather than defaulting to the empty string and row 1, column 1, respectively.

Stabilization

The following rules have been stabilized and are no longer in preview:

The following behaviors have been stabilized:

Preview features

  • [pyupgrade] Fix false positive with TypeVar default before Python 3.13 (UP040) (#26888)

Bug fixes

  • [ruff] Fix missing check on unrecognized early bound (RUF016) (#26986)

Rule changes

  • Insert a space after the colon in Ruff suppression comments (#27123)

Performance

  • [pyupgrade] Speed up unnecessary-future-import (UP010) (#27047)

Documentation

  • [ruff] Add missing period in "Why is this bad?" section (RUF200) (#26930)
  • [flake8-simplify] Clarify os.environ behavior on Windows (SIM112) (#26972)
  • [pydocstyle] Document fix safety (D400) (#26971)

Contributors

Install ruff 0.16.0

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-installer.ps1 | iex"

Download ruff 0.16.0

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.16.1: 0.16.1

Compare source

Source

Release Notes

Released on 2026-07-30.

Preview features

  • Add an option to opt out of human-readable names (#27160)
  • [flake8-pytest-style] Make fixes safe by default and unsafe only when comments are present (PT018) (#27201)
  • [pyupgrade] Skip fix when a defaulted TypeVar precedes a non-defaulted one (UP040, UP046, UP047) (#27133)
  • [ruff] Fix false positive with unpacked arguments (RUF065) (#26959)

Bug fixes

  • Bump gen-lsp-types to gracefully handle unknown enumeration values in LSP messages (#27230)
  • [flake8-bugbear] Mark range as immutable (B008) (#27247)
  • [flake8-comprehensions] NFKC-normalize keyword names in C408 fix (#26813)
  • [flake8-return] Fix false positive when variable is read in finally clause (RET504) (#25441)
  • [pydocstyle] Skip section detection inside RST directive bodies (D214, D405, D413) (#23635)
  • [refurb] Parenthesize yield arguments in the FURB192 fix (#27192)

Rule changes

  • [flake8-pytest-style] Mark PT022 fixes as unsafe (#26440)
  • [refurb] Mark fixes that remove unknown separators as unsafe (FURB105) (#27200)

Server

  • Fix indexing of excluded nested Ruff workspaces (#27303)
  • Lint TOML files in the LSP (#26862)

Documentation

  • Cover pycon Markdown formatting (#27153)
  • [flake8-bandit] Document TYPE_CHECKING exception (S101) (#27004)
  • [flake8-import-conventions] Document that extend-aliases can override default aliases (#27191)
  • [pylint] Add missing fix safety gotchas for non-augmented-assignment (PLR6104) (#27250)

Other changes

  • Reduce syntax error noise by swallowing dedents like indents (#27170)
  • Vendor latest annotate-snippets (#27033)

Contributors

Install ruff 0.16.1

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-installer.ps1 | iex"

Download ruff 0.16.1

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.16.2: 0.16.2

Compare source

Source

Release Notes

Released on 2026-08-06.

Bug fixes

  • [flake8-pyi] Avoid false positives on singledispatch functions (PYI041) (#27335)

Server

  • Register formatting capabilities dynamically to exclude TOML files (#27332)

Contributors

Install ruff 0.16.2

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-installer.ps1 | iex"

Download ruff 0.16.2

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.16.3: 0.16.3

Compare source

Source

Release Notes

Released on 2026-08-13.

Preview features

  • [pylint] Fix false negatives on negative numbers (PLR6104) (#27251)
  • [pyupgrade] Add rule to replace while 1 with while True (UP048) (#27190)

Bug fixes

  • [flake8-bandit] Also check keyword arguments (S602, S603, S607, S609) (#27687)
  • [pylint] Allow continue in finally on Python 3.8 (#27626)
  • [pylint] Fix PLE1307 false positive with bools (#27651)
  • [pylint] Fix false positives and negatives with %b format character (PLE1300, PLE1307) (#27560)
  • [pylint] Improve handling of concatenated strings (PLE1300) (#27659)

Rule changes

  • [numpy] Make np.chararray autofix backwards-compatible (NPY201) (#27527)

Performance

  • Enable PGO for Linux x86-64 Ruff releases (#27570)
  • Enable PGO for Linux ARM64 Ruff releases (#27574)
  • Enable PGO for Windows x86-64 Ruff releases (#27573)
  • Enable PGO for macOS ARM64 Ruff releases (#27572)
  • Reduce Expr size to 64 bytes (#27591)

CLI

  • Hyperlink rule codes in ruff check --statistics output (#27646)

Documentation

  • [ruff] Also suggest asyncio.TaskGroup (RUF006) (#27461)

Other changes

Contributors

Install ruff 0.16.3

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-installer.ps1 | iex"

Download ruff 0.16.3

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.16.4: 0.16.4

Compare source

Source

Release Notes

Released on 2026-08-20.

Preview features

  • [flake8-use-pathlib] Add autofix for PTH116 (#26460)
  • [refurb] Restrict delete-full-slice to lists (FURB131) (#27711)
  • [refurb] Skip FURB101 and FURB103 when the open argument is a file descriptor (#27643)

Bug fixes

  • Fix InvalidInstruction on Windows CPUs that do not support POPCNT (#27803)
  • [pyflakes] Emit semantic syntax errors in string type definitions as F722 (#27835)
  • [pylint] Allow os._exit imports in import-private-name (PLC2701) (#27738)

Rule changes

  • [syntax-errors] Align mixed t-string/bytes error message with CPython 3.14 (#27766)
  • [ruff] Add ctypes.LittleEndianStructure and related types to existing exception (RUF012) (#27753)
  • [syntax-errors] Detect duplicate keyword arguments (#17804)
  • [syntax-errors] Detect parameters declared nonlocal (#27628)

Server

  • Offer display-only fixes and mark safe fixes preferred (#27807)
  • Support pull diagnostics for notebook cells (#27779)

Documentation

  • Add default indicator to rules table (#27724)
  • Fix broken link to Python docs (#27757)

Other changes

  • Fix s390x stacker assembly in release builds (#27776)
  • Guarantee minimum stack size when parsing a module, standalone expression, and suites (#25464)
  • Reduce configuration deserialization code size (#27924)
  • Check packed AST index bounds (#27849)

Contributors

Install ruff 0.16.4

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-installer.ps1 | iex"

Download ruff 0.16.4

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.16.5: 0.16.5

Compare source

Source

Release Notes

Released on 2026-08-27.

Preview features

  • Allow rules without codes (#28049)
  • Introduce category selectors (#27666)
  • Update preview default rules and categories (#27877)

Bug fixes

  • [flake8-async] Detect blocking generic HTTP requests (ASYNC210) (#28024)
  • [flake8-datetimez] Allow timezone-safe strptime chains (DTZ007) (#28023)
  • [flake8-simplify] Respect side effects in lambda defaults (SIM401) (#28000)

Server

  • Fix duplicated "of" in ClientOptions doc comment (#27978)

Documentation

  • Document rule acceptance guidelines (#27910)
  • Document the new category selectors (#27906)

Contributors

Install ruff 0.16.5

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-installer.ps1 | iex"

Download ruff 0.16.5

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.16.6: 0.16.6

Compare source

Source

Release Notes

Released on 2026-09-03.

Preview features

  • Move pytest-fixture-autouse to the restriction category (#28219)
  • [flake8-pytest-style] Add an autofix for PT020 (#27993)
  • [flake8-tidy-imports] Prevent fix loop between TID254 and TID255 (#28262)
  • [isort] Exclude pragma comments from line length calculation (I001) (#27313)

Bug fixes

  • Validate unary expressions when parsing (#28233)
  • [flake8-async, pylint] Recognize builtins.open (ASYNC230, PLW1514) (#28021)
  • [flake8-bugbear] Fix panic on match subjects (B031) (#27781)
  • [flake8-datetimez] Reject tzinfo=None for datetime bounds (DTZ901) (#28022)
  • [flake8-pytest-style] Avoid duplicate PT017 diagnostics (#27918)
  • [ruff] Remove lint.external hint for Ruff-specific suppressions (RUF102) (#27923)

Rule changes

  • [flake8-use-pathlib] Add display-only fix for os.listdir (PTH208) (#28027)

Documentation

  • Add another example and glob reference for lint.per-file-ignores (#28106)
  • Add duplicate work guidance (#28229)
  • [flake8-async] Document thread offloading (ASYNC240) (#28008)
  • [pyupgrade] Clarify default encoding argument handling (UP012) (#27315)

Other changes

  • Allow unary plus in match patterns on Python 3.15 (#28231)

Contributors

Install ruff 0.16.6

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-installer.ps1 | iex"

Download ruff 0.16.6

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.16.7: 0.16.7

Compare source

Source

Release Notes

Released on 2026-09-10.

Preview features

  • [ruff] Add rule for default values on method receivers (RUF077) (#26700)
  • [ruff] Recognize re.prefixmatch (RUF039, RUF055) (#28311)

Bug fixes

  • Alternate nested quotes inside format spec interpolations (#28259)
  • [flake8-implicit-str-concat] Mark fix unsafe when it creates a docstring (ISC003) (#27981)
  • [flake8-tidy-imports] Skip fixes for multi-member imports (TID254) (#26584)
  • [pylint] Gate ImportCycleError on Python 3.15 (PLW0133) (#28310)

Rule changes

  • Correct D211 and D203 rule conflict diagnostic (#28444)
  • Recognize slice and frozendict generics (#28477)
  • Stop defining __cached__ for Python 3.15 (#28476)
  • [pyupgrade] Stop recommending removed typing.no_type_check_decorator (UP035) (#28475)

Performance

  • Reuse parser name lookups when interning (#28399)
  • Speed up inherited configuration resolution (#28299)

Documentation

  • Fix line-length path in --config example (#28392)
  • Remove the "Who’s Using Ruff?" list (#28455)

Other changes

  • Embed archive checksums in the shell installer (#28281)

Contributors

Install ruff 0.16.7

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-installer.ps1 | iex"

Download ruff 0.16.7

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.16.8: 0.16.8

Compare source

Source

Release Notes

Released on 2026-09-16.

Bug fixes

  • Visit functional TypedDict keyword arguments correctly (#28584)
  • [flake8-simplify] Detect nested async with under sync parent (SIM117) (#27821)
  • [flake8-simplify] Preserve operand order in SIM109 fix (#27824)
  • [pyupgrade] Preserve required parentheses in multiline UP040 fixes (#28164)
  • [pyupgrade] Skip TypeVarTuple and ParamSpec conversions with bounds or constraints (UP040, UP046, UP047) (#28505)

Rule changes

  • Add support for __lazy_modules__ (#28459)
  • Recognize PEP-728 TypedDict class keywords (#28533)
  • Recognize quoted types in typing.TypeForm (#28507)
  • Support conditional assignment to __lazy_modules__ (#28491)
  • [flake8-type-checking] Prefer lazy imports over TYPE_CHECKING on Python 3.15 and later (TC001, TC002, TC003) (#28541)
  • [pyupgrade] Make the fix for UP040 always unsafe (#28526)
  • [pyupgrade] Stop recommending deprecated ByteString aliases (UP035) (#28498)
  • [ruff, flake8-use-pathlib] Recognize the parent_mode argument (RUF064, PTH103) (#28528)
  • [ruff] Detect \Z in pytest.raises() match patterns (RUF043) (#28598)

CLI

  • Use rule name and code in formatter incompatibility warnings (#28571)

Configuration

  • [flake8-tidy-imports] Add extend-banned-api (#28644)

Contributors

Install ruff 0.16.8

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-installer.ps1 | iex"

Download ruff 0.16.8

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>

0.16.9: 0.16.9

Compare source

Source

Release Notes

Released on 2026-09-24.

Preview features

  • [ruff] Avoid false positives for overloaded division (RUF069) (#28309)

Bug fixes

  • [flake8-bugbear] Avoid false positives for calls with keyword arguments (B009, B010, B043) (#28776)
  • [flake8-tidy-imports] Allow lazy imports to be used in deferred annotations (TID255) (#28767)

Rule changes

  • Update LibCST-based fixes for Python 3.15 (#28616)
  • [flake8-pyi] Mention stubs in the diagnostic message (PYI002) (#28542)

Documentation

  • Fix horizontal overflow on the rules documentation page (#28699)
  • Update rules table with category information (#28651)
  • [flake8-annotations] Clarify that ANN401 checks return types in addition to arguments (#28334)
  • [flake8-bugbear] Document type-checker interaction (B010) (#28509)
  • [flake8-comprehensions] Document map/generator exception behavior (C417) (#27794)
  • [ruff] Mention related isort settings (RUF022) (#28719)

Contributors

Install ruff 0.16.9

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-installer.ps1 | iex"

Download ruff 0.16.9

File Platform Checksum
ruff-aarch64-apple-darwin.tar.gz Apple Silicon macOS checksum
ruff-x86_64-apple-darwin.tar.gz Intel macOS checksum
ruff-aarch64-pc-windows-msvc.zip ARM64 Windows checksum
ruff-i686-pc-windows-msvc.zip x86 Windows checksum
ruff-x86_64-pc-windows-msvc.zip x64 Windows checksum
ruff-aarch64-unknown-linux-gnu.tar.gz ARM64 Linux checksum
ruff-i686-unknown-linux-gnu.tar.gz x86 Linux checksum
ruff-powerpc64-unknown-linux-gnu.tar.gz PPC64 Linux checksum
ruff-powerpc64le-unknown-linux-gnu.tar.gz PPC64LE Linux checksum
ruff-riscv64gc-unknown-linux-gnu.tar.gz RISCV Linux checksum
ruff-s390x-unknown-linux-gnu.tar.gz S390x Linux checksum
ruff-x86_64-unknown-linux-gnu.tar.gz x64 Linux checksum
ruff-armv7-unknown-linux-gnueabihf.tar.gz ARMv7 Linux checksum
ruff-aarch64-unknown-linux-musl.tar.gz ARM64 MUSL Linux checksum
ruff-i686-unknown-linux-musl.tar.gz x86 MUSL Linux checksum
ruff-x86_64-unknown-linux-musl.tar.gz x64 MUSL Linux checksum
ruff-arm-unknown-linux-musleabihf.tar.gz ARMv6 MUSL Linux (Hardfloat) checksum
ruff-armv7-unknown-linux-musleabihf.tar.gz ARMv7 MUSL Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>
typing-extensions (current version → 4.16.0)

Source comparison unavailable: source refs for this transition are not known.

3.6.2

3.6.2.1

3.6.5

3.6.6

3.7.2

3.7.4

3.7.4.1

3.7.4.2

3.7.4.3

3.10.0.0

3.10.0.1

3.10.0.2

4.0.0

4.0.1

4.1.0

4.1.1

4.2.0

4.3.0

4.4.0

4.5.0

4.6.0

4.6.1

4.6.2

4.6.3

4.7.0: 4.7.0

Source

Source ref: main

This is a feature release. Major changes include:

  • All non-deprecated names from typing are now re-exported by typing_extensions for convenience
  • Add typing_extensions.get_protocol_members and typing_extensions.is_protocol
  • Declare support for Python 3.12
  • This will be the last feature release to support Python 3.7, which recently reached its end-of-life

Full changelog of versions 4.7.0 and 4.7.0rc1:

Release 4.7.0 (June 28, 2023)

  • This is expected to be the last feature release supporting Python 3.7,
    which reaches its end of life on June 27, 2023. Version 4.8.0 will support
    only Python 3.8.0 and up.
  • Fix bug where a typing_extensions.Protocol class that had one or more
    non-callable members would raise TypeError when issubclass()
    was called against it, even if it defined a custom __subclasshook__
    method. The correct behaviour -- which has now been restored -- is not to
    raise TypeError in these situations if a custom __subclasshook__ method
    is defined. Patch by Alex Waygood (backporting
    https://github.com/python/cpython/pull/105976).

Release 4.7.0rc1 (June 21, 2023)

  • Add typing_extensions.get_protocol_members and
    typing_extensions.is_protocol (backport of CPython PR #104878).
    Patch by Jelle Zijlstra.
  • typing_extensions now re-exports all names in the standard library's
    typing module, except the deprecated ByteString. Patch by Jelle
    Zijlstra.
  • Due to changes in the implementation of typing_extensions.Protocol,
    typing.runtime_checkable can now be used on typing_extensions.Protocol
    (previously, users had to use typing_extensions.runtime_checkable if they
    were using typing_extensions.Protocol).
  • Align the implementation of TypedDict with the implementation in the
    standard library on Python 3.9 and higher.
    typing_extensions.TypedDict is now a function instead of a class. The
    private functions _check_fails, _dict_new, and _typeddict_new
    have been removed. is_typeddict now returns False when called with
    TypedDict itself as the argument. Patch by Jelle Zijlstra.
  • Declare support for Python 3.12. Patch by Jelle Zijlstra.
  • Fix tests on Python 3.13, which removes support for creating
    TypedDict classes through the keyword-argument syntax. Patch by
    Jelle Zijlstra.
  • Fix a regression introduced in v4.6.3 that meant that
    issubclass(object, typing_extensions.Protocol) would erroneously raise
    TypeError. Patch by Alex Waygood (backporting the CPython PR
    https://github.com/python/cpython/pull/105239).
  • Allow Protocol classes to inherit from typing_extensions.Buffer or
    collections.abc.Buffer. Patch by Alex Waygood (backporting
    https://github.com/python/cpython/pull/104827, by Jelle Zijlstra).
  • Allow classes to inherit from both typing.Protocol and typing_extensions.Protocol
    simultaneously. Since v4.6.0, this caused TypeError to be raised due to a
    metaclass conflict. Patch by Alex Waygood.
  • Backport several deprecations from CPython relating to unusual ways to
    create TypedDicts and NamedTuples. CPython PRs #105609 and #105780
    by Alex Waygood; typing_extensions backport by Jelle Zijlstra.
    • Creating a NamedTuple using the functional syntax with keyword arguments
      (NT = NamedTuple("NT", a=int)) is now deprecated.
    • Creating a NamedTuple with zero fields using the syntax NT = NamedTuple("NT")
      or NT = NamedTuple("NT", None) is now deprecated.
    • Creating a TypedDict with zero fields using the syntax TD = TypedDict("TD")
      or TD = TypedDict("TD", None) is now deprecated.
  • Fix bug on Python 3.7 where a protocol X that had a member a would not be
    considered an implicit subclass of an unrelated protocol Y that only has a
    member a. Where the members of X are a superset of the members of Y,
    X should always be considered a subclass of Y iff Y is a
    runtime-checkable protocol that only has callable members. Patch by Alex
    Waygood (backporting CPython PR
    https://github.com/python/cpython/pull/105835).

4.7.1: 4.7.1

Source

Source ref: main

  • Fix support for TypedDict, NamedTuple and is_protocol on PyPy-3.7 and
    PyPy-3.8. Patch by Alex Waygood. Note that PyPy-3.7 and PyPy-3.8 are unsupported
    by the PyPy project. The next feature release of typing-extensions will
    drop support for PyPy-3.7 and may also drop support for PyPy-3.8.

4.8.0: 4.8.0

Source

Source ref: main

Changes since 4.7.1:

  • Add typing_extensions.Doc, as proposed by PEP 727. Patch by
    Sebastián Ramírez.
  • Drop support for Python 3.7 (including PyPy-3.7). Patch by Alex Waygood.
  • Fix bug where get_original_bases() would return incorrect results when
    called on a concrete subclass of a generic class. Patch by Alex Waygood
    (backporting https://github.com/python/cpython/pull/107584, by James
    Hilton-Balfe).
  • Fix bug where ParamSpec(default=...) would raise a TypeError on Python
    versions <3.11. Patch by James Hilton-Balfe

No changes since 4.8.0rc1.

4.9.0: 4.9.0

Source

Source ref: main

This feature release adds typing_extensions.ReadOnly, as specified
by PEP 705, and makes various other improvements, especially to
@typing_extensions.deprecated().

There are no changes since 4.9.0rc1.

4.10.0

Source

Source ref: main

Release 4.10.0 (February 25, 2024)

This feature release adds support for PEP 728 (TypedDict with extra
items) and PEP 742 (TypeIs).

There are no changes since 4.10.0rc1.

4.11.0: 4.11.0

Source

Source ref: main

Release 4.11.0 (April 5, 2024)

This feature release provides improvements to various recently
added features, most importantly type parameter defaults (PEP 696).

There are no changes since 4.11.0rc1.

Changes since 4.10.0:

  • Fix tests on Python 3.13.0a5. Patch by Jelle Zijlstra.
  • Fix the runtime behavior of type parameters with defaults (PEP 696).
    Patch by Nadir Chowdhury.
  • Fix minor discrepancy between error messages produced by typing
    and typing_extensions on Python 3.10. Patch by Jelle Zijlstra.
  • When include_extra=False, get_type_hints() now strips ReadOnly from the annotation.

4.12.0: 4.12.0

Source

Source ref: main

This release focuses on compatibility with the upcoming release of
Python 3.13. Most changes are related to the implementation of type
parameter defaults (PEP 696).

Thanks to all of the people who contributed patches, especially Alex
Waygood, who did most of the work adapting typing-extensions to the
CPython PEP 696 implementation.

There is a single change since 4.12.0rc1:

  • Fix incorrect behaviour of typing_extensions.ParamSpec on Python 3.8 and
    3.9 that meant that
    isinstance(typing_extensions.ParamSpec("P"), typing.TypeVar) would have a
    different result in some situations depending on whether or not a profiling
    function had been set using sys.setprofile. Patch by Alex Waygood.

Changes included in 4.12.0rc1:

  • Improve the implementation of type parameter defaults (PEP 696)
    • Backport the typing.NoDefault sentinel object from Python 3.13.
      TypeVars, ParamSpecs and TypeVarTuples without default values now have
      their __default__ attribute set to this sentinel value.
    • TypeVars, ParamSpecs and TypeVarTuples now have a has_default()
      method, matching typing.TypeVar, typing.ParamSpec and
      typing.TypeVarTuple on Python 3.13+.
    • TypeVars, ParamSpecs and TypeVarTuples with default=None passed to
      their constructors now have their __default__ attribute set to None
      at runtime rather than types.NoneType.
    • Fix most tests for TypeVar, ParamSpec and TypeVarTuple on Python
      3.13.0b1 and newer.
    • Backport CPython PR #118774,
      allowing type parameters without default values to follow those with
      default values in some type parameter lists. Patch by Alex Waygood,
      backporting a CPython PR by Jelle Zijlstra.
    • It is now disallowed to use a TypeVar with a default value after a
      TypeVarTuple in a type parameter list. This matches the CPython
      implementation of PEP 696 on Python 3.13+.
    • Fix bug in PEP-696 implementation where a default value for a ParamSpec
      would be cast to a tuple if a list was provided.
      Patch by Alex Waygood.
  • Fix Protocol tests on Python 3.13.0a6 and newer. 3.13.0a6 adds a new
    __static_attributes__ attribute to all classes in Python,
    which broke some assumptions made by the implementation of
    typing_extensions.Protocol. Similarly, 3.13.0b1 adds the new
    __firstlineno__ attribute to all classes.
  • Fix AttributeError when using typing_extensions.runtime_checkable
    in combination with typing.Protocol on Python 3.12.2 or newer.
    Patch by Alex Waygood.
  • At runtime, assert_never now includes the repr of the argument
    in the AssertionError. Patch by Hashem, backporting of the original
    fix https://github.com/python/cpython/pull/91720 by Jelle Zijlstra.
  • The second and third parameters of typing_extensions.Generator,
    and the second parameter of typing_extensions.AsyncGenerator,
    now default to None. This matches the behaviour of typing.Generator
    and typing.AsyncGenerator on Python 3.13+.
  • typing_extensions.ContextManager and
    typing_extensions.AsyncContextManager now have an optional second
    parameter, which defaults to Optional[bool]. The new parameter
    signifies the return type of the __(a)exit__ method, matching
    typing.ContextManager and typing.AsyncContextManager on Python
    3.13+.
  • Backport types.CapsuleType from Python 3.13.
  • Releases are now made using Trusted Publishers
    improving the security of the release process. Patch by Jelle Zijlstra.

4.12.1: 4.12.1

Source

Source ref: main

  • Preliminary changes for compatibility with the draft implementation
    of PEP 649 in Python 3.14. Patch by Jelle Zijlstra.
  • Fix regression in v4.12.0 where nested Annotated types would cause
    TypeError to be raised if the nested Annotated type had unhashable
    metadata. Patch by Alex Waygood.

4.12.2: 4.12.2

Source

Source ref: main

  • Fix regression in v4.12.0 where specialization of certain generics with an overridden __eq__ method would raise errors. Patch by Jelle Zijlstra.
  • Fix tests so they pass on 3.13.0b2

4.13.0

Source

Source ref: main

New features:

  • Add typing_extensions.TypeForm from PEP 747. Patch by
    Jelle Zijlstra.
  • Add typing_extensions.get_annotations, a backport of
    inspect.get_annotations that adds features specified
    by PEP 649. Patches by Jelle Zijlstra and Alex Waygood.
  • Backport evaluate_forward_ref from CPython PR
    #119891 to evaluate ForwardRefs.
    Patch by Daraan, backporting a CPython PR by Jelle Zijlstra.

Bugfixes and changed features:

  • Update PEP 728 implementation to a newer version of the PEP. Patch by Jelle Zijlstra.
  • Copy the coroutine status of functions and methods wrapped
    with @typing_extensions.deprecated. Patch by Sebastian Rittau.
  • Fix bug where TypeAliasType instances could be subscripted even
    where they were not generic. Patch by Daraan.
  • Fix bug where a subscripted TypeAliasType instance did not have all
    attributes of the original TypeAliasType instance on older Python versions.
    Patch by Daraan and Alex Waygood.
  • Fix bug where subscripted TypeAliasType instances (and some other
    subscripted objects) had wrong parameters if they were directly
    subscripted with an Unpack object.
    Patch by Daraan.
  • Backport to Python 3.10 the ability to substitute ... in generic Callable
    aliases that have a Concatenate special form as their argument.
    Patch by Daraan.
  • Extended the Concatenate backport for Python 3.8-3.10 to now accept
    Ellipsis as an argument. Patch by Daraan.
  • Fix backport of get_type_hints to reflect Python 3.11+ behavior which does not add
    Union[..., NoneType] to annotations that have a None default value anymore.
    This fixes wrapping of Annotated in an unwanted Optional in such cases.
    Patch by Daraan.
  • Fix error in subscription of Unpack aliases causing nested Unpacks
    to not be resolved correctly. Patch by Daraan.
  • Backport CPython PR #124795:
    fix TypeAliasType not raising an error on non-tuple inputs for type_params.
    Patch by Daraan.
  • Fix that lists and ... could not be used for parameter expressions for TypeAliasType
    instances before Python 3.11.
    Patch by Daraan.
  • Fix error on Python 3.10 when using typing.Concatenate and
    typing_extensions.Concatenate together. Patch by Daraan.
  • Backport of CPython PR #109544
    to reflect Python 3.13+ behavior: A value assigned to __total__ in the class body of a
    TypedDict will be overwritten by the total argument of the TypedDict constructor.
    Patch by Daraan, backporting a CPython PR by Jelle Zijlstra.
  • isinstance(typing_extensions.Unpack[...], TypeVar) now evaluates to False on Python 3.11
    and newer, but remains True on versions before 3.11.
    Patch by Daraan.

4.13.1

Source

Source ref: main

This is a bugfix release fixing two edge cases that appear on old bugfix releases of CPython.

Bugfixes:

  • Fix regression in 4.13.0 on Python 3.10.2 causing a TypeError when using Concatenate.
    Patch by Daraan.
  • Fix TypeError when using evaluate_forward_ref on Python 3.10.1-2 and 3.9.8-10.
    Patch by Daraan.

4.13.2

Source

Source ref: main

  • Fix TypeError when taking the union of typing_extensions.TypeAliasType and a
    typing.TypeAliasType on Python 3.12 and 3.13.
    Patch by Joren Hammudoglu.
  • Backport from CPython PR #132160
    to avoid having user arguments shadowed in generated __new__ by
    @typing_extensions.deprecated.
    Patch by Victorien Plot.

4.14.0

Source

Source ref: main

This release adds several new features, including experimental support for inline typed dictionaries (PEP 764) and sentinels (PEP 661), and support for changes in Python 3.14. In addition, Python 3.8 is no longer supported.

Changes since 4.14.0rc1:

  • Remove __or__ and __ror__ methods from typing_extensions.Sentinel
    on Python versions <3.10. PEP 604 was introduced in Python 3.10, and
    typing_extensions does not generally attempt to backport PEP-604 methods
    to prior versions.
  • Further update typing_extensions.evaluate_forward_ref with changes in Python 3.14.

Changes included in 4.14.0rc1:

  • Drop support for Python 3.8 (including PyPy-3.8). Patch by Victorien Plot.
  • Do not attempt to re-export names that have been removed from typing,
    anticipating the removal of typing.no_type_check_decorator in Python 3.15.
    Patch by Jelle Zijlstra.
  • Update typing_extensions.Format, typing_extensions.evaluate_forward_ref, and
    typing_extensions.TypedDict to align
    with changes in Python 3.14. Patches by Jelle Zijlstra.
  • Fix tests for Python 3.14 and 3.15. Patches by Jelle Zijlstra.

New features:

  • Add support for inline typed dictionaries (PEP 764).
    Patch by Victorien Plot.
  • Add typing_extensions.Reader and typing_extensions.Writer. Patch by
    Sebastian Rittau.
  • Add support for sentinels (PEP 661). Patch by
    Victorien Plot.

4.14.1

Source

Source ref: main

Release 4.14.1 (July 4, 2025)

  • Fix usage of typing_extensions.TypedDict nested inside other types
    (e.g., typing.Type[typing_extensions.TypedDict]). This is not allowed by the
    type system but worked on older versions, so we maintain support.

4.15.0: 4.15.0

Source

Source ref: main

No user-facing changes since 4.15.0rc1.

New features since 4.14.1:

  • Add the @typing_extensions.disjoint_base decorator, as specified
    in PEP 800. Patch by Jelle Zijlstra.
  • Add typing_extensions.type_repr, a backport of
    annotationlib.type_repr,
    introduced in Python 3.14 (CPython PR #124551,
    originally by Jelle Zijlstra). Patch by Semyon Moroz.
  • Fix behavior of type params in typing_extensions.evaluate_forward_ref. Backport of
    CPython PR #137227 by Jelle Zijlstra.

4.16.0: 4.16.0

Source

Source ref: main

No changes since 4.16.0rc2.

Changes since 4.15.0:

  • Make typing_extensions.TypeAliasType's __module__ attribute writable. Backport of CPython PR #149172.
  • Fix setting of __required_keys__ and __optional_keys__ when inheriting keys with the same name.
  • Add support for AsyncIterator, io.Reader, io.Writer and os.PathLike protocols as bases for other protocols.
  • Fix incorrect behaviour on Python 3.9 and Python 3.10 that meant that calling isinstance with typing_extensions.Concatenate[...] or typing_extensions.Unpack[...] as the first argument could have a different result in some situations depending on whether or not a profiling function had been set using sys.setprofile. This affected both CPython and PyPy implementations. Patch by Brian Schubert.
  • Fix __init_subclass__() behavior in the presence of multiple inheritance involving an @deprecated-decorated base class. Backport of CPython PR #138210 by Brian Schubert.
  • Raise TypeError when attempting to subclass typing_extensions.ParamSpec on Python 3.9. The typing implementation has always raised an error, and the typing_extensions implementation has raised an error on Python 3.10+ since typing_extensions v4.6.0. Patch by Brian Schubert.
  • Add the bound, covariant, contravariant, and infer_variance parameters to TypeVarTuple.
  • Officially support the bound, covariant, contravariant and infer_variance parameters to ParamSpec. Improve the validation of these parameters at runtime.
  • Rename typing_extensions.Sentinel to typing_extensions.sentinel, following the name that has been adopted for builtins.sentinel on Python 3.15. typing_extensions.Sentinel is retained as a soft-deprecated alias for backwards compatibility.
  • Add support for pickling sentinels.
  • Sentinels now preserve their identity when copied or deep-copied.
  • Deprecate passing name as a keyword argument or repr as a positional argument to the sentinel constructor.
  • The default repr of a sentinel X = sentinel("X") is now X rather than <X>.
  • Deprecate arbitrary attribute assignments to sentinels.
  • Deprecate subclassing sentinels.
  • Add support for Python 3.15.
  • Avoid a DeprecationWarning when deprecated is applied to a coroutine function on Python 3.14.0.
watchfiles (1.2.0 → 1.3.0)

1.3.0: v1.3.0 2026-09-21

Compare source

Source

Source ref: main

What's Changed

New Contributors

Full Changelog: https://github.com/samuelcolvin/watchfiles/compare/v1.2.0...v1.3.0

yarl (1.22.0 → 1.25.1)

Source comparison unavailable: source refs for this transition are not known.

1.23.0

1.24.2

1.24.5

1.25.1

Updates `Python dependencies (uv.lock)`. **Breaking change detected.** Review the release notes before merging. Automerge: Disabled because breaking change release notes were detected ### Updates | Dependency | From | To | Type | Locations | | --- | --- | --- | --- | --- | | <code>aiohappyeyeballs</code> | <code>2.6.1</code> | <code>2.7.1</code> | minor | [1] L19 | | <code>aiohttp</code> | <code>3.13.3</code> | <code>3.14.3</code> | minor | [1] L28 | | <code>anyio</code> | <code>4.14.2</code> | <code>4.15.1</code> | minor | [1] L103 | | <code>attrs</code> | <code>25.4.0</code> | <code>26.1.0</code> | major | [1] L115 | | <code>idna</code> | <code>3.11</code> | <code>3.20</code> | minor | [1] L265 | | <code>multidict</code> | <code>6.7.0</code> | <code>6.9.1</code> | minor; **breaking** | [1] L283 | | <code>packaging</code> | <code>25.0</code> | <code>26.3</code> | major | [1] L328 | | <code>propcache</code> | <code>0.4.1</code> | <code>0.5.4</code> | minor; **breaking** | [1] L364 | | <code>pygments</code> | <code>2.19.2</code> | <code>2.21.0</code> | minor | [1] L447 | | <code>pyrefly</code> | <code>1.2.0</code> | <code>1.3.1</code> | minor | [1] L497 | | <code>ruff</code> | <code>0.14.11</code> | <code>0.16.9</code> | minor; **breaking** | [1] L556 | | <code>typing-extensions</code> | <code>current version</code> | <code>4.16.0</code> | unknown | [1] | | <code>watchfiles</code> | <code>1.2.0</code> | <code>1.3.0</code> | minor | [1] L618 | | <code>yarl</code> | <code>1.22.0</code> | <code>1.25.1</code> | minor | [1] L665 | ### Files - [1] <code>uv.lock</code> ### Release notes <details> <summary>aiohappyeyeballs (2.6.1 → 2.7.1)</summary> ### [`2.6.2`](https://github.com/aio-libs/aiohappyeyeballs/releases/tag/v2.6.2): v2.6.2 [Compare source](https://github.com/aio-libs/aiohappyeyeballs/compare/v2.6.1...v2.6.2) [Source](https://github.com/aio-libs/aiohappyeyeballs) Source ref: <code>main</code> ## v2.6.2 (2026-05-20) ### Bug Fixes - Clear error on empty addr_infos in start_connection ([#222](https://github.com/aio-libs/aiohappyeyeballs/pull/222), [`55dd76a`](https://github.com/aio-libs/aiohappyeyeballs/commit/55dd76aee978ca47a38899b9caf69d058bf41fb3)) ### Refactoring - Optimize obtaining event-loop down to 1 line ([#185](https://github.com/aio-libs/aiohappyeyeballs/pull/185), [`02a7029`](https://github.com/aio-libs/aiohappyeyeballs/commit/02a70296210125b45952c3221db0dfb76d8ea911)) ### Testing - Stop verify_no_lingering_tasks from leaking an event loop ([#221](https://github.com/aio-libs/aiohappyeyeballs/pull/221), [`ce43beb`](https://github.com/aio-libs/aiohappyeyeballs/commit/ce43beb0242007dc57be6e2f4e3bf0b9f4f239d1)) --- **Detailed Changes**: [v2.6.1...v2.6.2](https://github.com/aio-libs/aiohappyeyeballs/compare/v2.6.1...v2.6.2) ### [`v2.7.0`](https://github.com/aio-libs/aiohappyeyeballs/releases/tag/v2.7.0): v2.7.0 [Compare source](https://github.com/aio-libs/aiohappyeyeballs/compare/v2.6.1...v2.7.0) [Source](https://github.com/aio-libs/aiohappyeyeballs) Source ref: <code>main</code> ## v2.7.0 (2026-05-20) ### Features - Add Python 3.14 support ([#224](https://github.com/aio-libs/aiohappyeyeballs/pull/224), [`10e7d43`](https://github.com/aio-libs/aiohappyeyeballs/commit/10e7d4341666605de295dd00da716e30002e78c2)) --- **Detailed Changes**: [v2.6.2...v2.7.0](https://github.com/aio-libs/aiohappyeyeballs/compare/v2.6.2...v2.7.0) ### [`2.7.1`](https://github.com/aio-libs/aiohappyeyeballs/releases/tag/v2.7.1): v2.7.1 [Compare source](https://github.com/aio-libs/aiohappyeyeballs/compare/v2.6.1...v2.7.1) [Source](https://github.com/aio-libs/aiohappyeyeballs) Source ref: <code>main</code> ## v2.7.1 (2026-07-01) ### Performance Improvements - Use defaultdict to help with performance ([#239](https://github.com/aio-libs/aiohappyeyeballs/pull/239), [`e10f335`](https://github.com/aio-libs/aiohappyeyeballs/commit/e10f335ad9630122832e967428ac138992a50bca)) ### Refactoring - Collapse collect-then-remove pattern in utils helpers ([#227](https://github.com/aio-libs/aiohappyeyeballs/pull/227), [`0dd3fd1`](https://github.com/aio-libs/aiohappyeyeballs/commit/0dd3fd16fe394eb8493000dc9b9894fad3ca3190)) - Merge identical except blocks in _connect_sock cleanup ([#229](https://github.com/aio-libs/aiohappyeyeballs/pull/229), [`b7c186e`](https://github.com/aio-libs/aiohappyeyeballs/commit/b7c186e3242eb4d6eaf0918857a99c263b3186fb)) - Simplify _interleave_addrinfos family grouping ([#226](https://github.com/aio-libs/aiohappyeyeballs/pull/226), [`fdf6548`](https://github.com/aio-libs/aiohappyeyeballs/commit/fdf6548a5f8b38e45ad7cee8add3c3a7e34e2805)) --- **Detailed Changes**: [v2.7.0...v2.7.1](https://github.com/aio-libs/aiohappyeyeballs/compare/v2.7.0...v2.7.1) </details> <details> <summary>aiohttp (3.13.3 → 3.14.3)</summary> Source comparison unavailable: source refs for this transition are not known. ### `3.13.4` ### `3.13.5` ### `3.14.0` ### `3.14.1` ### `3.14.2` ### `3.14.3` </details> <details> <summary>anyio (4.14.2 → 4.15.1)</summary> ### [`4.15.0`](https://github.com/agronholm/anyio/releases/tag/4.15.0): 4.15.0 [Compare source](https://github.com/agronholm/anyio/compare/4.14.2...4.15.0) [Source](https://github.com/agronholm/anyio) Source ref: <code>master</code> - Added support for the newer keyword-only arguments on `anyio.Path` methods to match the standard library `pathlib.Path`: - `follow_symlinks` on `exists()` (Python 3.12+) - `follow_symlinks` on `is_dir()` (Python 3.13+) - `follow_symlinks` on `is_file()` (Python 3.13+) - `follow_symlinks` on `owner()` (Python 3.13+) - `follow_symlinks` on `group()` (Python 3.13+) - `newline` on `read_text()` (Python 3.13+) ([\#1286](https://github.com/agronholm/anyio/pull/1286), [\#1293](https://github.com/agronholm/anyio/pull/1293); PR by @jaideeppyne) - Added `amap`, `gather`, and `as_completed` utility functions to simplify common patterns ([\#1173](https://github.com/agronholm/anyio/pull/1173); PR by @Graeme22) - Added `--anyio-mode` command-line option as an alternative to the `anyio_mode` ini setting, and fix the pytest plugin's auto mode detection to recognize the mode when set via either mechanism(e.g: `pytest_asyncio`). ([\#1242](https://github.com/agronholm/anyio/pull/1242); PR by @EmmanuelNiyonshuti) - Added the `anyio.Future` synchronization primitive which behaves similar to `asyncio.Future`, allowing tasks to wait for a value (or exception) from another task ([\#1146](https://github.com/agronholm/anyio/pull/1146); PR by @Vizonex) - Added guidance for managing multiple memory object stream producers and consumers with cloned streams ([\#330](https://github.com/agronholm/anyio/issues/330); PR by @nightcityblade) - Added `StapledObjectStream.send_nowait()` that delegates to the underlying `ObjectSendStream`, if it implements it ([\#1241](https://github.com/agronholm/anyio/pull/1241); PR by @davidbrochart) - Added the `move_on_at()` and `fail_at()` functions to complement `move_on_after()` and `fail_after()` - Changed the default name for a task spawned with `TaskGroup.create_task(func())` to match the default task name for the analogous task spawned with `TaskGroup.start_soon(func)` or `TaskGroup.start(func)` in more situations. Previously, the default name of a `TaskGroup.create_task` task never included the module name. (The default name for a task spawned with `TaskGroup.start_soon` or `TaskGroup.start` typically includes the module name.) ([\#1234](https://github.com/agronholm/anyio/pull/1234); PR by @gschaffner) - Changed the `anyio` and `anyio.abc` modules to lazily (much like `810`) import the necessary submodules. This is done by parsing the AST of the module and building a lookup table from the `if TYPE_CHECKING:` block. A fallback mode has been provided for installations where the source code is unavailable (e.g. PyInstaller). ([\#1169](https://github.com/agronholm/anyio/pull/1169)) - Fixed free-threading compatibility issues arising from the fact that on Python 3.14 free-threading builds, newly created threads inherit the current context by default, causing AnyIO to behave erroneously in relation to `start_blocking_portal()` and `anyio.to_thread.run_sync()` ([\#1224](https://github.com/agronholm/anyio/pull/1224); PR by @EmmanuelNiyonshuti) - Fixed `SpooledTemporaryFile.readinto()` and `readinto1()` reading twice before rollover, so the destination buffer was overwritten by the second read and the file position advanced twice, silently losing data ([\#1215](https://github.com/agronholm/anyio/pull/1215); PR by @c-tonneslan) - Added a `reason` parameter to `fail_after` (and the new `fail_at`) allowing for added exception context when raising `TimeoutError` ([\#1227](https://github.com/agronholm/anyio/pull/1227); PR by @Graeme22) - Fixed the default `TaskHandle.name` missing part of the task name for tasks started with `TaskGroup.start` on Trio ([\#1231](https://github.com/agronholm/anyio/issues/1231); PR by @gschaffner) - Fixed `anyio.run` leaking, or at least, delaying collection of loop and root_task due to the root task being cached in a `RunVar`. ([\#1203](https://github.com/agronholm/anyio/issues/1203); PR by @tapetersen) - Fixed `anyio.Path.with_stem()` silently producing a wrong path (e.g. `Path(".txt")`) instead of raising `ValueError` when given an empty stem on a path with a non-empty suffix, unlike `pathlib.PurePath.with_stem` ([\#1200](https://github.com/agronholm/anyio/pull/1200); PR by @Sanjays2402) - Fixed `UNIXSocketStream.aclose()` raising `asyncio.InvalidStateError` when a concurrent receive or send operation had just been cancelled on the asyncio backend ([\#1267](https://github.com/agronholm/anyio/issues/1267); PR by @alloutflo) - Fixed the pytest plugin importing the deprecated `_pytest.python.CallSpec2` alias, which triggers `PytestRemovedIn10Warning` on `pytest>=9.2` and crashes pytest at startup when `filterwarnings = error` is configured ([\#1271](https://github.com/agronholm/anyio/issues/1271); PR by @matthewfeickert) - Fixed an asyncio worker thread race that could raise `RuntimeError` when the event loop closed between checking its state and scheduling the worker result ([\#1265](https://github.com/agronholm/anyio/issues/1265); PR by @hansu650) - Fixed `CapacityLimiter` on the asyncio backend over-granting tokens when `total_tokens` was raised while the limiter was over-subscribed ([\#1223](https://github.com/agronholm/anyio/pull/1223); PR by @zelinewang) - Fixed asyncio task groups leaking unawaited coroutines when a custom task constructor fails; default task creation is unaffected ([\#1274](https://github.com/agronholm/anyio/issues/1274); PR by @dsfaccini) - Fixed inconsistencies between Trio and asyncio when target `TaskGroup` is cancelled before a task created with `.start()` calls `TaskStatus.started()` - The started task shouldn't get a `CancelledError` until the first checkpoint after the `started()` call. - A value passed to `started()` should be available on the `TaskHandle` and correctly passed back to the caller of start even if cancelled. - The CancelledError shouldn't leak out of the `TaskGroup.start()` call to the calling task. ([\#1197](https://github.com/agronholm/anyio/issues/1197); PR by @tapetersen) - Fixed `TemporaryDirectory` not cleaning up when the host task was cancelled while exiting the context manager, as the cleanup now runs in a shielded cancel scope ([\#1304](https://github.com/agronholm/anyio/pull/1304); PR by @smurfix) ### [`4.15.1`](https://github.com/agronholm/anyio/releases/tag/4.15.1): 4.15.1 [Compare source](https://github.com/agronholm/anyio/compare/4.14.2...4.15.1) [Source](https://github.com/agronholm/anyio) Source ref: <code>master</code> - Implemented a compatibility fix for supporting direct access of `anyio.*` submodules from the main package even when those submodules were not directly imported first (<span class="title-ref">\#1311 \<https://github.com/agronholm/anyio/issues/1311\></span>) </details> <details> <summary>attrs (25.4.0 → 26.1.0)</summary> ### `26.1.0` </details> <details> <summary>idna (3.11 → 3.20)</summary> ### [`3.12`](https://github.com/kjd/idna/releases/tag/v3.12) [Compare source](https://github.com/kjd/idna/compare/v3.11...v3.12) [Source](https://github.com/kjd/idna) Source ref: <code>master</code> ### [`3.13`](https://github.com/kjd/idna/releases/tag/v3.13) [Compare source](https://github.com/kjd/idna/compare/v3.11...v3.13) [Source](https://github.com/kjd/idna) Source ref: <code>master</code> ### [`3.14`](https://github.com/kjd/idna/releases/tag/v3.14) [Compare source](https://github.com/kjd/idna/compare/v3.11...v3.14) [Source](https://github.com/kjd/idna) Source ref: <code>master</code> ### [`3.15`](https://github.com/kjd/idna/releases/tag/v3.15) [Compare source](https://github.com/kjd/idna/compare/v3.11...v3.15) [Source](https://github.com/kjd/idna) Source ref: <code>master</code> ### [`3.16`](https://github.com/kjd/idna/releases/tag/v3.16) [Compare source](https://github.com/kjd/idna/compare/v3.11...v3.16) [Source](https://github.com/kjd/idna) Source ref: <code>master</code> ### [`3.17`](https://github.com/kjd/idna/releases/tag/v3.17) [Compare source](https://github.com/kjd/idna/compare/v3.11...v3.17) [Source](https://github.com/kjd/idna) Source ref: <code>master</code> ### [`3.18`](https://github.com/kjd/idna/releases/tag/v3.18) [Compare source](https://github.com/kjd/idna/compare/v3.11...v3.18) [Source](https://github.com/kjd/idna) Source ref: <code>master</code> ### [`3.19`](https://github.com/kjd/idna/releases/tag/v3.19) [Compare source](https://github.com/kjd/idna/compare/v3.11...v3.19) [Source](https://github.com/kjd/idna) Source ref: <code>master</code> - Restore the `std3_rules` option, which had no effect since changes to UTS #46 processing in Unicode 16. Note that `uts46_remap()` defaults to enabling STD3 rules, so direct callers will see input containing non-LDH ASCII characters rejected again. - Performance improvements to UTS #46 mapping, particularly for ASCII-only domains. - Test on free-threaded CPython with the GIL disabled and document thread safety. - Expose the Unicode version of the generated tables as `idna.unicode_version`, and show it in `idna --version`. - Add `code`, `text`, `codepoint` and `position` attributes to `IDNAError` so that the failed rule and the offending character can be identified without parsing the exception message. - The deprecated `transitional` argument to `encode()` and `uts46_remap()` is now completely ignored, and gives a deprecation warning for the latter. - Reject A-labels that are not the canonical Punycode encoding of their U-label. - Fix CONTEXTJ violations raising `IDNAError` instead of `InvalidCodepointContext`. - Consistently raise `IDNAError` for empty labels and non-ASCII bytes passed to label helper functions and the incremental codec. - Add property-based tests, extended fuzzing targets, coverage measurement, and CI checks that the data tables match the generator output. - Various code quality and tooling improvements. Thanks to stefan6419846, LouieLuNZ, and Salvatore Corvaglia for contributions to this release. ### [`3.20`](https://github.com/kjd/idna/releases/tag/v3.20) [Compare source](https://github.com/kjd/idna/compare/v3.11...v3.20) [Source](https://github.com/kjd/idna) Source ref: <code>master</code> - Update to Unicode 18.0.0. - Better enforcement of the domain length limit in the incremental codec. - Add support for Python 3.15. </details> <details> <summary>multidict (6.7.0 → 6.9.1)</summary> ### [`6.7.1`](https://github.com/aio-libs/multidict/releases/tag/v6.7.1): 6.7.1 [Compare source](https://github.com/aio-libs/multidict/compare/v6.7.0...v6.7.1) [Source](https://github.com/aio-libs/multidict) Source ref: <code>master</code> Bug fixes --------- - Fixed slow memory leak caused by identity by adding ``Py_DECREF`` to identity value before leaving ``md_pop_one`` on success -- by :user:`Vizonex`. *Related issues and pull requests on GitHub:* #1284. ---- ### [`6.8.0`](https://github.com/aio-libs/multidict/releases/tag/v6.8.0): 6.8.0 **Breaking change detected.** [Compare source](https://github.com/aio-libs/multidict/compare/v6.7.0...v6.8.0) [Source](https://github.com/aio-libs/multidict) Source ref: <code>master</code> Bug fixes --------- - A segmentation fault that could be triggered when getting an item is now fixed -- by :user:`Vizonex`. *Related issues and pull requests on GitHub:* #1310. - Fixed reference leak in iterators, views and ``istr`` -- by :user:`Vizonex`. *Related issues and pull requests on GitHub:* #1311. - Fixed the pure-Python :class:`~multidict.MultiDict` constructor and :py:meth:`~multidict.MultiDict.extend`, :py:meth:`~multidict.MultiDict.update`, and :py:meth:`~multidict.MultiDict.merge` methods over-allocating their internal hash table when called with both a positional argument and keyword arguments, because keyword arguments were counted twice in the size estimate -- by :user:`aiolibsbot`. *Related issues and pull requests on GitHub:* #1338. - Fixed ``__repr__`` of :class:`~multidict.MultiDict`, :class:`~multidict.CIMultiDict`, their proxies, and the keys/items views producing invalid output when keys contained quote characters -- keys are now formatted with :func:`repr` so the result is a valid Python string literal -- by :user:`aiolibsbot`. *Related issues and pull requests on GitHub:* #1342. - Fixed a segfault when calling :py:meth:`~multidict.MultiDict.add` with only one of its two required arguments supplied by keyword, e.g. ``d.add(key="k")``. Extra keyword arguments passed to the lookup and removal methods are also now rejected with :exc:`TypeError` instead of being silently ignored. -- by :user:`devdanzin` *Related issues and pull requests on GitHub:* #1376. - Fixed a segfault when constructing a multidict iterator type directly, e.g. ``type(iter(md.keys())).__new__(...)``. Such an iterator had a NULL internal pointer that ``next()`` dereferenced. The iterator types now forbid direct instantiation, the same way the view types were fixed in #1163. -- by :user:`devdanzin` *Related issues and pull requests on GitHub:* #1377. - Fixed a segfault when using a :py:class:`~multidict.MultiDict` or :py:class:`~multidict.CIMultiDict` created via ``__new__`` without calling ``__init__`` (for example a subclass that does not call ``super().__init__()``). The internal state was left as NULL pointers that the first method call dereferenced. ``tp_new`` now initializes the object to a valid empty mapping. -- by :user:`devdanzin` *Related issues and pull requests on GitHub:* #1378. - Fixed two crashes in the C extension caused by holding a raw pointer into a hash table across an operation that could reshape it. Updating a multidict from itself (e.g. ``d.extend(d)``) freed the very table being iterated -- a use-after-free; ``extend(self)`` now doubles the contents and ``update(self)``/``merge(self)`` are no-ops. Building a multidict from a list of pairs whose case-insensitive key ``.lower()`` shrinks that list read past the end of the list; the length is now re-checked on every iteration. -- by :user:`devdanzin` *Related issues and pull requests on GitHub:* #1379. - Fixed three reference/resource leaks on error paths in the C extension: the items-view ``__contains__`` leaked the first element of a candidate pair when reading the second one raised; ``__repr__`` leaked its ``PyUnicodeWriter`` when the multidict was mutated during iteration; and the internal iteration helper leaked the identity reference when key materialization failed under low memory. -- by :user:`devdanzin` *Related issues and pull requests on GitHub:* #1381. - Stopped several feature-detection fallbacks in the C extension from swallowing every exception. When probing an argument (``arg.items()``/``arg.keys()``) or measuring it (``len(other)``) fails, the code now clears only the expected :exc:`TypeError`/:exc:`AttributeError` and lets everything else -- notably :exc:`MemoryError` and :exc:`KeyboardInterrupt` -- propagate, matching the already-correct sites elsewhere in the module. -- by :user:`devdanzin` *Related issues and pull requests on GitHub:* #1382. - Fixed a segmentation fault when extending a multidict with itself -- by :user:`cananoo` and :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1398. - Fixed a memory leak when ``MultiDict`` and ``CIMultiDict`` instances are initialized more than once -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1412. - Fixed a reference leak in items-view set operations -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1413. - Fixed a memory leak when destroying C-extension multidict instances and proxies -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1415. - Fixed a reference leak from repeated ``__init__`` calls on ``MultiDictProxy`` and ``CIMultiDictProxy`` instances -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1419. - Fixed missing decref for :data:`None` on error in :meth:`~multidict.MultiDict.setdefault` -- by :user:`asvetlov` *Related issues and pull requests on GitHub:* #1421. Features -------- - Added :py:func:`reversed` support to the keys, values, and items views of :class:`~multidict.MultiDict`, :class:`~multidict.CIMultiDict`, and their proxies in both the C-extension and pure-Python implementations -- by :user:`aiolibsbot`. *Related issues and pull requests on GitHub:* #448. - Optimized key identity comparison for C Extension. Now it uses fast path that is equal to :c:func:`PyUnicode_Equal` from Python 3.14+ but without redundant type checks. It gives ~15% speed-up on benchmarks with many key comparisons. -- by :user:`asvetlov` *Related issues and pull requests on GitHub:* #1406. - Changed both the pure-Python and C implementations to mark a temporarily removed hash table entry by setting the high bit of its hash instead of overwriting it with a sentinel value, so restoring the entry no longer recomputes the hash; :meth:`~multidict.MultiDict.getall` is faster ~10% now in C version -- by :user:`asvetlov` *Related issues and pull requests on GitHub:* #1426. Removals and backward incompatible breaking changes --------------------------------------------------- - Dropped support for Python 3.9 as it has reached end of life. *Related issues and pull requests on GitHub:* #1316. - Dropped support for free-threaded Python 3.13 -- by :user:`ngoldbaum`. *Related issues and pull requests on GitHub:* #1326. Improved documentation ---------------------- - Fixed ``CIMultiDictProxy`` documentation to state it inherits from ``MultiDictProxy`` (not ``MultiDict``), and fixed missing word in ``istr`` section -- by :user:`veeceey`. *Related issues and pull requests on GitHub:* #1298. - Clarified that ``istr`` preserves the original casing and compares as a regular ``str``; case-insensitive matching is handled by ``CIMultiDict`` -- by :user:`gyanu2507`. *Related issues and pull requests on GitHub:* #1397. - Fixed broken RST markup in ``items()`` docstrings -- by :user:`veeceey`. *Related issues and pull requests on GitHub:* #1299. Packaging updates and notes for downstreams ------------------------------------------- - Dropped support for free-threaded Python 3.13 -- by :user:`ngoldbaum`. *Related issues and pull requests on GitHub:* #1326. - Wheels for iOS and Android (CPython 3.13+) are now published on release-tag builds, so downstreams on those platforms no longer need a local compiler to install ``multidict``; these wheels are build-verified only, since running the test suite on mobile needs a simulator or an emulator -- by :user:`aiolibsbot`. *Related issues and pull requests on GitHub:* #1337. - Added support for building and shipping riscv64 wheels -- by :user:`justeph`. *Related issues and pull requests on GitHub:* #1293. - The ``setuptools`` build dependency lower bound has been restored to be ``>= 47`` after an incorrect automated increase in :pr:`1315` -- by :user:`aiolibsbot`. *Related issues and pull requests on GitHub:* #1400. Contributor-facing changes -------------------------- - Added support for collecting code coverage of isolated multidict tests -- by :user:`Vizonex`. *Related issues and pull requests on GitHub:* #1314. - Switched to ``mirrors-clang-format`` and enabled clang-format in ``pre-commit.ci`` -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #1318. - Added a release-tag-gated CI job that cross-compiles the C extension for iOS and Android through ``cibuildwheel`` -- by :user:`aiolibsbot`. *Related issues and pull requests on GitHub:* #1337. - Added an ``AGENTS.md`` orientation file at the repository root, covering the pull request template, the ``CHANGES/`` news fragment conventions, the draft-PR / human-review workflow, and the dual pure-Python and C-extension parity rule, so LLM contributors land changes that match project style -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #1339. - Added ``init``, ``installable``, ``instantiation``, ``parametrization``, ``parametrized``, ``postfix``, and ``unparseable`` to the docs spelling list so news fragments and docs can use these words without failing the spell check build -- by :user:`pctablet505`. *Related issues and pull requests on GitHub:* #1343. - Documented three common agent failure modes in :file:`AGENTS.md`: the docs spell check (``make doc-spelling``) catches unknown words in news fragments before CI does; coverage runs over the test tree too, so unreachable defensive ``raise`` guards and one-sided cleanup branches in tests will surface as uncovered on the codecov patch report; and branch creation is restricted on ``aio-libs/multidict``, so PRs must be pushed from a fork -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #1343, #1345. - Trimmed the CI test matrix to drop redundant ``Py_DEBUG`` jobs on macOS and Windows and to gate the ``windows-11-arm`` wheel build to release-time only, cutting CI wall-clock by roughly a third without reducing code coverage -- by :user:`aiolibsbot`. *Related issues and pull requests on GitHub:* #1346. - Added a ``CLAUDE.md`` at the repository root that imports :file:`AGENTS.md` via Claude Code's ``@``-syntax, so the project's LLM contributor rules load automatically when working in Claude Code -- by :user:`aiolibsbot`. *Related issues and pull requests on GitHub:* #1347. - Enabled the ``I`` (import sorting) rule in ``[tool.ruff.lint]`` so ``ruff check`` covers import order on top of the existing ``UP`` (pyupgrade) group, and updated the ``ruff-check`` pre-commit hook to run with ``--fix --exit-non-zero-on-fix --show-fixes`` so import-order fixes apply on commit. Sorted imports in four ``tests/`` files to match the new rule -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #1348. - Enabled the ``PLC0415`` (import-outside-top-level) rule in ``[tool.ruff.lint]``. Function-scoped imports must now opt in with ``# noqa: PLC0415`` plus a comment explaining the reason (typically avoiding a heavy optional dependency at import time). This catches a pattern that LLM contributors frequently introduce. There are currently no opt-outs in the tree, so the rule is enforced everywhere ``ruff check`` runs -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #1349. - Switched the ``cibuildwheel`` build frontend to ``build[uv]`` so that ``uv`` provisions every build and test virtual environment in the wheel matrix. Test-dependency installation in particular drops from a multi-second ``pip install`` per ABI to a roughly sub-second ``uv`` resolve -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #1350. - Overrode ``CIBW_BUILD_FRONTEND=build`` for the odd-arch wheel matrix; the upstream ``manylinux``/``musllinux`` images for those arches do not ship ``uv`` -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #1352. - Allowed re-running the deploy job after a partial release failure: the ``Make Release`` step now skips when the GitHub Release already exists, and the PyPI publish step uses ``skip-existing`` so dists that were already uploaded on a prior attempt do not break the retry -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #1353. - Switched the aarch64 and armv7l wheel builds to GitHub's native ARM runners. The aarch64 wheels now build without QEMU emulation, and armv7l runs on aarch64 hosts so its 32-bit ARM execution is far cheaper than the previous aarch64-on-x86_64 path -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #1354. - Documented design principles for pure-Python :class:`~multidict.istr` implementation -- by :user:`asvetlov` *Related issues and pull requests on GitHub:* #1360. - Pinned ``coverage`` to the ``ctrace`` measurement core so the test suite runs on Python 3.14. Coverage picks ``sysmon`` there, which cannot record the dynamic contexts ``pytest-cov`` switches at runtime, and the resulting warning became an error under the suite's ``filterwarnings`` setting -- by :user:`rodrigobnogueira`. *Related issues and pull requests on GitHub:* #1393. - Dependabot has been restricted to the ``requirements`` subdirectory to avoid unintended updates outside dependency requirement files -- by :user:`aiolibsbot`. *Related issues and pull requests on GitHub:* #1400. - Enabled automatic upgrades from ruff after each python version that is dropped -- by :user:`Vizonex`. *Related issues and pull requests on GitHub:* #1325. Miscellaneous internal changes ------------------------------ - Explicitly marked ``empty_htkeys`` as ``const``. Moved the structure to ``.rodata`` linker section. Unexpected modification of the structure will lead to segfault instead of corrupting the data and fail fast. ``.rodata`` is mount as read-only-mapped, it is shared well across multiple threads without cache misses. The change is pretty trivial, it is made for the sake of correctness, not for speedup. -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1405. - Slightly reorganized multidict creating process. 1. Removed unnecessary calculations when ``md_init()`` creates an empty multidict. 2. Now ``tp_alloc`` slot is used in object cloning instead of bare :c:func:`PyType_GenericNew` call. -- by :user:`asvetlov` *Related issues and pull requests on GitHub:* #1420. - Dropped dead code, ``_md_del_at()`` and ``_md_del_at_for_upd()`` never fails -- by :user:`asvetlov` *Related issues and pull requests on GitHub:* #1423. - Fixed a missing space in the :exc:`ValueError` message raised when constructing a multidict from a sequence -- by :user:`veeceey`. *Related issues and pull requests on GitHub:* #1295. - Renamed the benchmark script from ``benchmarks/becnhmark.py`` to ``benchmarks/benchmark.py`` so it matches the invocation documented in :doc:`benchmark` -- by :user:`aiolibsbot`. *Related issues and pull requests on GitHub:* #1335. ---- ### [`6.9.0`](https://github.com/aio-libs/multidict/releases/tag/v6.9.0): 6.9.0 [Compare source](https://github.com/aio-libs/multidict/compare/v6.7.0...v6.9.0) [Source](https://github.com/aio-libs/multidict) Source ref: <code>master</code> Bug fixes --------- - Protected ``repr()`` of ``MultiDict``, ``MultiDictProxy``, and their views in the C extension with a critical section, avoiding data races on the free-threaded build of CPython -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1431. - Guarded ``repr()`` of ``MultiDictProxy`` in the C extension and of ``KeysView`` in both the C extension and the pure-Python implementation against infinite recursion on self-referential containers, matching the existing guard on ``MultiDict``, ``ItemsView``, and ``ValuesView`` -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1431. - Protected ``MultiDict.update()``, ``.extend()``, ``.merge()``, ``.clear()``, ``.copy()``, and the ``MultiDict``/``CIMultiDict`` constructors in the C extension with a critical section, using the two-object form when a second multidict, multidict proxy, or plain ``dict`` instance is involved, avoiding data races and a segmentation fault on the free-threaded build of CPython. ``.clear()`` now also publishes the empty table before releasing any entry's references, so a concurrent caller can never observe a partially-cleared multidict even if releasing a value runs arbitrary Python code that suspends the held critical section -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1433. - Protected ``MultiDict.add()``, ``__setitem__``/``__delitem__``, ``get()``/``getone()``/``__getitem__``, ``__contains__``, ``getall()``, ``setdefault()``, ``pop()``/``popone()``/``popall()``/``popitem()``, ``__eq__``, iteration, and the ``&``/``|``/``-``/``^``/``in``/ ``isdisjoint()`` operations on ``.keys()`` and ``.items()`` views in the C extension with a critical section, avoiding data races and use-after-free crashes on the free-threaded build of CPython -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1438. - Fixed a data race on the free-threaded build where ``MultiDictObject.used`` was written non-atomically while ``len()`` read it with a relaxed atomic load -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1441. - Fixed several pre-existing use-after-free races on the free-threaded build: ``_md_resize()`` and ``md_clone_from_ht()`` could allocate a new hash table, have their critical section transiently suspended during that allocation, and then use a keys-table pointer or size a concurrent operation had already invalidated; ``_md_del_at()`` (plain ``del``/``pop()``) could likewise leave ``self`` in an inconsistent state across a suspending decref -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1441. - Fixed a data race on the free-threaded build where ``md->keys`` was published with a plain store while lock-free readers loaded it atomically, and a false-negative race in ``get()``/``__contains__`` where a hash temporarily marked by a concurrent replace could make a present key look absent -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1441. - Fixed several more pre-existing use-after-free and data-corruption races on the free-threaded build, this time in the ``__setitem__()``/``update()``/ ``extend()``/``merge()`` replace path: a decref suspending the critical section mid-replace could leave a stale table pointer in use, misplace a temporarily-marked entry during a concurrent resize, or let one thread's duplicate-tracking mark get overwritten by an unrelated key's entry sharing the same hash bucket -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1441. - Fixed an unbounded memory leak on the free-threaded build where a retired hash table could sit on ``md->retired`` for the rest of the object's lifetime under sustained concurrent read traffic instead of being freed -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1443. - Fixed a data race on the free-threaded build of the C extension where ``state->global_version``, the version counter shared by every multidict instance and used to derive ``getversion()``, was bumped with a plain increment instead of an atomic op. Two threads mutating different instances at the same time could step on each other's update and hand out a duplicate (or non-monotonic) version number -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1444. - Fixed a data race on the free-threaded build of the C extension where ``getall()``/``popall()`` and ``update()``/``extend()``/``merge()`` temporarily marked and unmarked a matching entry's hash with a plain, non-atomic store, while a lock-free ``__contains__``/``get()`` on another thread could load that same field with an atomic operation and no lock at all -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1448. - Fixed a data race in the pure-Python ``MultiDict``/``CIMultiDict`` fallback where concurrent mutating calls (``add()``, ``__setitem__``, ``__delitem__``, ``setdefault()``, ``pop()``/``popone()``, ``popall()``, ``popitem()``, ``update()``, ``extend()``, ``merge()``, ``clear()``, and re-``__init__``) could corrupt the shared hash table, or silently drop a concurrent write, on a regular, GIL-enabled interpreter. Pure-Python bytecode is not atomic under the GIL, so two threads could interleave mid hash-table insert or deletion, leaving the index table pointing at stale or out-of-range entries and causing an infinite probe loop, an ``AttributeError``, or a lost mutation. Each ``MultiDict``/``CIMultiDict`` instance now holds its own lock for the duration of these operations, with two-object operations locking both instances in a fixed order to avoid deadlock. The C extension already serializes these operations with a critical section and was not affected -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1449. - Fixed a data race on the free-threaded build of the C extension where ``to_dict()`` cleared every entry's temporary "seen" mark with a plain, non-atomic store, while a lock-free ``__contains__``/``get()`` on another thread could load that same field with an atomic operation and no lock at all -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1450. - Fixed a data race on the free-threaded build of the C extension where ``update()``/``extend()``/``merge()`` read ``self``'s module state without holding ``self``'s lock, while a concurrent ``__init__()`` on the same, already-published multidict could rewrite that same field under lock. Rather than routing every read through a lock-free lookup, the field is now written only once, at object construction, and never touched again by ``__init__()``, so it is safe to read unlocked anywhere -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1452. - Fixed ``items()`` set algebra (``&``, ``|``, ``-``, ``in``, ``isdisjoint()``) so it no longer corrupts or hangs when a compared value's ``__eq__()`` re-enters the same :class:`~multidict.MultiDict`, for example by calling ``getall()`` on it. The comparison now runs only after the internal hash-chain walk has been fully materialized and restored, so the callback can no longer observe entries the walk still has marked -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1453. - Fixed a data race on the free-threaded build of the C extension where ``popall()``/``popone()``/``__delitem__``/``add()`` rewrote a hash table index slot with a plain, non-atomic store, while a lock-free ``get()``/``getone()``/``__getitem__``/``__contains__`` on another thread walked that same index array with a plain, non-atomic load and no lock at all -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1454. - Stopped folding the case of :class:`~multidict.istr` keys in the case-sensitive :class:`~multidict.MultiDict`, so both the C and the pure Python implementations now keep such a key exactly as given -- by :user:`youdie006`. *Related issues and pull requests on GitHub:* #1457. - Fixed the C extension's ``update()`` (and ``merge()``, which shares the same code path) silently failing to invalidate an in-progress ``keys()``/ ``items()``/``values()`` iterator when the call only overwrote an already-present key's value in place. Adding a new key already invalidated iterators correctly; only the in-place overwrite branch was missing the version bump -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1458. - Fixed the pure-Python ``MultiDict``/``CIMultiDict`` iterator guard so that mutating the mapping before the first ``next()`` call on an ``items()``, ``keys()``, or ``values()`` iterator (or on ``iter(md)``) now reliably raises ``RuntimeError``, matching the C extension. Previously a mutation that happened before the iterator was ever advanced, such as ``clear()`` or a ``del``/``popone()`` that removed the only remaining entry, could make the iterator silently raise ``StopIteration`` instead -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1459. - Fixed a use-after-free race on the free-threaded build of the C extension where a retired hash table could be freed while a lock-free ``get()``/``getone()``/``__getitem__``/``__contains__`` reader on another thread was still walking it: the coarse "no reader in flight" gate reaching zero did not reliably mean every such reader had also reached its own per-table exit, so a table whose own reader count is still nonzero is now deferred for a later retry instead of freed -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1461. Features -------- - Added a :meth:`~multidict.MultiDict.to_dict` method returning a plain :class:`dict` that maps every key to the list of all its values. Unlike ``dict(md)``, which keeps only the first value per key, and unlike a ``{k: md.getall(k) for k in md}`` comprehension, which emits one entry per spelling of a case-insensitive key, it groups by key identity -- by :user:`rodrigobnogueira`. *Related issues and pull requests on GitHub:* #783. - ``MultiDict``, ``CIMultiDict``, ``MultiDictProxy`` and ``CIMultiDictProxy`` in the C extension implemented the vectorcall calling convention for construction. This sped up ``MultiDict(...)``-style calls by avoiding an intermediate positional-arguments tuple and keyword-arguments dictionary in the common case; the gained burst is ~10. -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1436. - Made ``MultiDict.__contains__()``, ``.get()``, ``.getone()`` and ``__getitem__()`` lock-free on CPython 3.14+'s free-threaded build, instead of taking a critical section like the rest of the C extension's API (on 3.13, which lacks the public API these need to safely read an entry concurrently, they still take the critical section, exactly as before). A resize/shrink/clear no longer frees the outgoing hash table immediately; it is deferred until no lock-free reader could still be walking it -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1441. - Made the pure-Python ``MultiDict``/``CIMultiDict`` implementation safe to use from multiple threads under a free-threaded (no-GIL) build. Every method that touches an instance's hash table now takes that instance's own lock, two-object operations (``update()``, ``extend()``, ``merge()``, ``__eq__()``, copying) lock both objects in a fixed, deadlock-safe order, and the version counter shared by every instance is guarded separately. On a regular (GIL-enabled) interpreter this adds no overhead: the locked methods are the exact same function objects as before -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1447. - Sped up adding many values for the same key to a :class:`~multidict.MultiDict` or :class:`~multidict.CIMultiDict`, each added value no longer gets slower than the one before it -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #1466. Improved documentation ---------------------- - Added the plural form "fallbacks" to the docs spell checker's allowed word list so :file:`CHANGES.rst` builds cleanly -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1439. Contributor-facing changes -------------------------- - Added race tests that iterate and extend a :class:`~multidict.MultiDict` from several threads on a free-threaded build, so a regression in the C extension's locking fails a free-threaded CI leg instead of going unnoticed -- by :user:`rodrigobnogueira`. *Related issues and pull requests on GitHub:* #1317. - Added ``AddressSanitizer``/``UndefinedBehaviorSanitizer`` and ``ThreadSanitizer`` CI jobs. The former runs the suite under a regular CPython with ``MULTIDICT_ASAN_BUILD=1``; the latter builds a free-threaded CPython instrumented with ``--with-thread-sanitizer`` and runs the suite against it via ``MULTIDICT_TSAN_BUILD=1`` -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1455. - Added Hypothesis-based property and stateful fuzz tests covering :class:`~multidict.MultiDict`/:class:`~multidict.CIMultiDict` semantics, views, iterators, and threaded stress scenarios, run against both the C-extension and pure-Python backends -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1460. - Added core dump collection to the AddressSanitizer and ThreadSanitizer CI jobs: a crash now uploads the core file alongside the crashing interpreter binary and the compiled extension as a downloadable artifact, for offline debugging with a matching symbol-carrying binary instead of raw hex offsets -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1462. - Added benchmarks for adding many values for the same key and for creating a multidict with many items -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #1465. - Skipped abstractmethods from coverage leaks report, they are empty placeholders that are never executed -- by :user:`asvetlov` *Related issues and pull requests on GitHub:* #1470. - Add benchmarks for ``__setitem__`` -- by :user:`asvetlov` *Related issues and pull requests on GitHub:* #1471. - The AddressSanitizer and ThreadSanitizer CI jobs were changed to run pytest with ``--capture=no``. Previously a sanitizer abort could exit the process before pytest flushed its per-test output buffer, silently dropping the sanitizer report from the job log -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1472. - Moved the ``hypothesis`` pin out of ``requirements/pytest.txt`` into its own ``requirements/pytest-hypothesis.txt``, installed only by the dedicated Hypothesis CI jobs. ``hypothesis`` now ships a Rust extension with no prebuilt wheel for some emulated architectures (e.g. musllinux i686), which broke wheel-testing jobs that never run the Hypothesis-marked tests in the first place -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1475. Miscellaneous internal changes ------------------------------ - Replaced ``PyIter_Next()`` calls with the newer ``PyIter_NextItem()`` API in the C extension, so the iterator-exhausted and error cases are told apart by the return code instead of an ambiguous ``NULL`` result -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1440. ---- ### [`6.9.1`](https://github.com/aio-libs/multidict/releases/tag/v6.9.1): 6.9.1 [Compare source](https://github.com/aio-libs/multidict/compare/v6.7.0...v6.9.1) [Source](https://github.com/aio-libs/multidict) Source ref: <code>master</code> Bug fixes --------- - Fixed the C extension reading freed memory on free-threaded builds when a list handed to :py:meth:`~multidict.MultiDict.update`, :py:meth:`~multidict.MultiDict.extend`, :py:meth:`~multidict.MultiDict.merge` or the :py:class:`~multidict.MultiDict` and :py:class:`~multidict.CIMultiDict` constructors, a ``[key, value]`` item inside any iterable handed to them, or a list tested with ``in`` against :py:meth:`~multidict.MultiDict.items`, is changed by another thread; a call that catches the list shrinking under it now raises :py:exc:`RuntimeError` -- by :user:`rodrigobnogueira`. *Related issues and pull requests on GitHub:* #1437. - Fixed a data race on the free-threaded build where a retired hash table's reader count used relaxed atomics, letting a lock-free ``get()``/``getone()``/ ``__getitem__()`` read race a concurrent free of that table. The reader-exit decrement and the drain's free check now use release/acquire ordering instead -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1481. - Fixed a free-threaded build bug where two threads calling ``update()``, ``merge()``, or ``__setitem__()`` on the same key at the same time could lose the key entirely instead of just racing on which value wins. A decref of the replaced value could transiently suspend the writer's critical section, letting a second writer for the same key observe the first writer's in-progress entry as absent and, once both settled, mistake it for a stale duplicate and delete it. Every such decref is now deferred until the writer has released its critical section, so the window can no longer open. ``setdefault()`` had an unrelated instance of the same blind spot (it could insert a duplicate rather than recognizing an in-flight key), fixed alongside it -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1483. - Fixed a free-threaded build bug where ``getall()`` and the ``items()``/ ``keys()``/``values()`` equality path could raise ``KeyError`` or report a present, never-deleted key as missing. A concurrent ``update()``/``extend()``/ ``__setitem__()`` call can have its critical section transiently suspended (a decref triggering a blocking allocator call) while an entry is marked as part of its own bookkeeping; a reader landing in that window used to treat the mark as "not found" instead of "still there, in flight" -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1484. - Fixed a reference leak in the C extension where ``operand | md.items()`` and ``md.items() - operand`` leaked one key and one value reference per element of ``operand``, letting a large operand grow memory without bound (:gh:`GHSA-54p9-h82j-f925 <aio-libs/multidict/security/advisories/GHSA-54p9-h82j-f925>`) -- by :user:`asvetlov`. The issue was reported by :user:`waydeshi`. *Related commits on GitHub:* :commit:`350b4a0`. - Fixed a segmentation fault on the standard (non-free-threaded) C extension build when a value type's ``__del__`` released the GIL (for example by calling ``time.sleep()``) while ``update()``, ``merge()``, ``__setitem__()``, ``__delitem__()``, ``pop()``, ``popone()``, or ``popall()`` was dropping a replaced or removed value. ``Py_BEGIN_CRITICAL_SECTION`` compiles to a no-op on this build, so nothing else was stopping a second thread from mutating the very same ``MultiDict`` concurrently once the GIL was released mid-mutation. Every such decref is now deferred until the mutation has fully finished, the same technique already used to close the analogous free-threaded-build race -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1489. - Fixed the C extension reading freed memory while iterating a :py:class:`~multidict.CIMultiDict` whose keys are plain :py:class:`str`. Converting such a key to :py:class:`~multidict.istr` could run Python code (a :py:class:`str` subclass's ``__str__`` or ``__del__``) or, on free-threaded builds, suspend the iterator's critical section, after which the iterator read the entry again even though a concurrent mutation could already have freed it. As part of the fix, :py:meth:`~multidict.MultiDict.copy` and re-initializing from another multidict now assign a new version in the C extension instead of reusing the source's, matching the pure Python implementation -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1496. - Fixed a use-after-free on the free-threaded build where a lock-free ``get()``, ``[]`` or ``in`` could read a hash table that a concurrent resize had just retired and another reader was freeing -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1497. Contributor-facing changes -------------------------- - Removed a redundant ``include`` and a duplicated ``exclude`` line from ``MANIFEST.in``; sdist contents are unchanged -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1478. - Added ``.claudeignore`` file -- by :user:`asvetlov` *Related issues and pull requests on GitHub:* #1479. - Scaled up the pure-Python ``pop()``, ``popitem()``, ``__delitem__()``, ``add()`` and item-insertion benchmarks to do more work per measurement. Repeated CodSpeed runs on the same commit showed these particular benchmarks flagged as dominated by syscalls, understating their real cost and adding noise to the reported values; a larger working set amortizes that overhead -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1485. - Replaced deprecated *instrumentation* codspeed mode with *simulation* -- by :user:`asvetlov` *Related issues and pull requests on GitHub:* #1493. - Reorganized the mutating benchmarks (item insertion, ``update()``, ``add()`` of the same key, ``pop()``, ``popitem()``, ``clear()``, ``__delitem__()`` and ``__setitem__()``) to copy a fresh multidict and apply the operation in a loop, like the ``add()`` and ``extend()`` benchmarks already do. The insertion, ``update()`` and ``clear()`` benchmarks previously mutated a single multidict shared across rounds, so only the first round measured the intended operation; the rest did a single copy per round, letting per-round overhead dominate -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1494. - The ``repr()`` and view inequality benchmarks were updated to repeat their operation in a loop, like the other benchmarks, and the CodSpeed benchmark job was moved to Python 3.14 -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1498. - Dropped ``-I`` from the AddressSanitizer test command in ``AGENTS.md`` and in the CI job. It implies ``-E``, which made Python ignore ``PYTHONMALLOC=malloc``, so small hash tables were still served from ``pymalloc`` arenas where use-after-free went undetected -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1499. - The CI/CD workflow was updated to stop superseded runs of the same pull request when a new commit is pushed; runs on ``master``, release branches, tags, the merge queue, and the daily schedule are never interrupted -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1500. - The release job was changed to upload distributions and their signatures to the GitHub Release one file at a time, skipping assets that were already attached and retrying after a pause, so that a parallel upload burst no longer tripped the GitHub secondary rate limit -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1503. Miscellaneous internal changes ------------------------------ - Corrected several comments in the free-threaded C extension that attributed critical-section suspension to a blocking ``PyMem_Malloc()`` call; allocation alone never suspends an acquired critical section, and the real risk at those sites is a decref running a finalizer or weakref callback. Also dropped a retry loop in ``md_clone_from_ht()`` that guarded against the same, non-existent allocation-triggered suspension -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1486. - Changed the free-threaded build's deferred decref buffer, used by ``update()`` and ``__setitem__()``, to a chain of fixed-size blocks with a large inline first block instead of a small inline array that was reallocated on growth -- by :user:`asvetlov`. *Related issues and pull requests on GitHub:* #1501. ---- </details> <details> <summary>packaging (25.0 → 26.3)</summary> ### [`26.0`](https://github.com/pypa/packaging/releases/tag/26.0): 26.0 [Compare source](https://github.com/pypa/packaging/compare/25.0...26.0) [Source](https://github.com/pypa/packaging) Source ref: <code>main</code> Read about the performance improvements here: <https://iscinumpy.dev/post/packaging-faster>. ## What's Changed Features: * PEP 751: support pylock by @sbidoul in https://github.com/pypa/packaging/pull/900 * PEP 794: import name metadata by @brettcannon in https://github.com/pypa/packaging/pull/948 * Support writing metadata by @henryiii in https://github.com/pypa/packaging/pull/846 * Support `__replace__` for `Version` by @henryiii in https://github.com/pypa/packaging/pull/1003 * Support positional pattern matching for `Version` and `Specifier` by @henryiii in https://github.com/pypa/packaging/pull/1004 Behavior adaptations: * PEP 440 handling of prereleases for `Specifier.contains`, `SpecifierSet.contains`, and `SpecifierSet.filter` by @notatallshaw in https://github.com/pypa/packaging/pull/897 * Handle PEP 440 edge case in `SpecifierSet.filter` by @notatallshaw in https://github.com/pypa/packaging/pull/942 * Adjust arbitrary equality intersection preservation in `SpecifierSet` by @notatallshaw in https://github.com/pypa/packaging/pull/951 * Return `False` instead of raising for `.contains` with invalid version by @Liam-DeVoe in https://github.com/pypa/packaging/pull/932 * Support arbitrary equality on arbitrary strings for `Specifier` and `SpecifierSet`'s `filter` and `contains` method. by @notatallshaw in https://github.com/pypa/packaging/pull/954 * Only try to parse as `Version` on certain marker keys, return `False` on unequal ordered comparsions by @JP-Ellis in https://github.com/pypa/packaging/pull/939 Fixes: * Update `_hash` when unpickling `Tag()` by @dholth in https://github.com/pypa/packaging/pull/860 * Correct comment and simplify implicit prerelease handling in `Specifier.prereleases` by @notatallshaw in https://github.com/pypa/packaging/pull/896 * Use explicit `_GLibCVersion` `NamedTuple` in `_manylinux` by @cthoyt in https://github.com/pypa/packaging/pull/868 * Detect invalid license expressions containing `()` by @bwoodsend in https://github.com/pypa/packaging/pull/879 * Correct regex for metadata `'name'` format by @di in https://github.com/pypa/packaging/pull/925 * Improve the message around expecting a semicolon by @pradyunsg in https://github.com/pypa/packaging/pull/833 * Support nested parens in license expressions by @Liam-DeVoe in https://github.com/pypa/packaging/pull/931 * Add space before at symbol in `Requirements` string by @henryiii in https://github.com/pypa/packaging/pull/953 * A root logger use found by ruff LOG, use `packaging` logger instead by @henryiii in https://github.com/pypa/packaging/pull/965 * Better support for subclassing `Marker` and `Requirement` by @henryiii in https://github.com/pypa/packaging/pull/1022 * Normalize all extras, not just if it comes first by @henryiii in https://github.com/pypa/packaging/pull/1024 * Don't produce a broken repr if `Marker` fails to construct by @henryiii in https://github.com/pypa/packaging/pull/1033 Performance: * Avoid recompiling regexes in the tokenizer for a 3x speedup by @hauntsaninja in https://github.com/pypa/packaging/pull/1019 * Improve performance in `_manylinux.py` by @cthoyt in https://github.com/pypa/packaging/pull/869 * Minor cleanups to `Version` by @bearomorphism in https://github.com/pypa/packaging/pull/913 * Skip redundant creation of `Version`s in specifier comparison by @notatallshaw in https://github.com/pypa/packaging/pull/986 * Cache `Specifier`'s Version by @notatallshaw in https://github.com/pypa/packaging/pull/985 * Make `Version` a little faster by @henryiii in https://github.com/pypa/packaging/pull/987 * Minor `Version` regex cleanup by @henryiii in https://github.com/pypa/packaging/pull/990 * Faster regex on Python 3.11.5+ by @henryiii in https://github.com/pypa/packaging/pull/988 and https://github.com/pypa/packaging/pull/1055 * Lazily calculate `_key` in `Version` by @notatallshaw in https://github.com/pypa/packaging/pull/989 and regression for `packaging_legacy` fixed by @henryiii in https://github.com/pypa/packaging/pull/1048 * Faster `canonicalize_version` by @henryiii in https://github.com/pypa/packaging/pull/993 * Use `fullmatch` in a couple more places by @henryiii in https://github.com/pypa/packaging/pull/992 * Use `fullmatch` for markers too by @henryiii in https://github.com/pypa/packaging/pull/1029 * Use `map` instead of generator by @henryiii in https://github.com/pypa/packaging/pull/996 * Deprecate `._version` (`_Version`, a `NamedTuple`) by @henryiii in https://github.com/pypa/packaging/pull/995 and https://github.com/pypa/packaging/pull/1062 * Avoid duplicate `Version` creation in `canonicalize_version` by @henryiii in https://github.com/pypa/packaging/pull/994 * Add `__slots__` to `Version` by @henryiii in https://github.com/pypa/packaging/pull/1001 * Add `__slots__` to `Specifier`s by @henryiii in https://github.com/pypa/packaging/pull/1002 * Add `__slots__` to `Node`s by @henryiii in https://github.com/pypa/packaging/pull/1032 * Use `version.__replace__` in specifier comparison by @notatallshaw in https://github.com/pypa/packaging/pull/999 * Use `_get_spec_version` in more places in `Specifier` by @notatallshaw in https://github.com/pypa/packaging/pull/1005 * Pull `set` construction out of function by @henryiii in https://github.com/pypa/packaging/pull/1012 * Letter normalization dict for prereleases and the like by @henryiii in https://github.com/pypa/packaging/pull/1014 * Avoid normalizing extras again when comparing by @henryiii in https://github.com/pypa/packaging/pull/1028 * Speed up `Version.__str__` by about 10% by @henryiii in https://github.com/pypa/packaging/pull/997 * Increase the performance of `canonicalize_name` by avoiding a regex by @henryiii in https://github.com/pypa/packaging/pull/1030, https://github.com/pypa/packaging/pull/1047, and https://github.com/pypa/packaging/pull/1064 * Faster zero stripping by @henryiii in https://github.com/pypa/packaging/pull/1058 Type annotations: * Fix a type annotation by @brettcannon in https://github.com/pypa/packaging/pull/907 * Fix tags return type in `parse_wheel_filename` docs by @ncoghlan in https://github.com/pypa/packaging/pull/973 * Add type hint for `_version` in `.version.Version` by @brettcannon in https://github.com/pypa/packaging/pull/927 * Changed static type annotations in prereleases setter method in `specifier.py` by @subhajitsaha01 in https://github.com/pypa/packaging/pull/930 * Statically type the tests by @henryiii in https://github.com/pypa/packaging/pull/982 Internal: * Test and declare support Python 3.14 by @henryiii in https://github.com/pypa/packaging/pull/901 * Modernize and speed up tests on Python 3.14 by @henryiii in https://github.com/pypa/packaging/pull/903 * Change our license metadata to use an SPDX license expression by @cdce8p in https://github.com/pypa/packaging/pull/881 * No need for `license-files` by @DimitriPapadopoulos in https://github.com/pypa/packaging/pull/924 * Update mypy by @hauntsaninja in https://github.com/pypa/packaging/pull/891 * Some config updates by @henryiii in https://github.com/pypa/packaging/pull/902 * Add spell check and rst check by @henryiii in https://github.com/pypa/packaging/pull/904 * Clean up ruff ignores by @henryiii in https://github.com/pypa/packaging/pull/905 * Update example for env marker `python_version` by @trim21 in https://github.com/pypa/packaging/pull/908 * Move codespell configuration into pyproject.toml by @yarikoptic in https://github.com/pypa/packaging/pull/910 * Check warning a little more precisely by @henryiii in https://github.com/pypa/packaging/pull/837 * Speed up mypy a little by @henryiii in https://github.com/pypa/packaging/pull/836 * Apply ruff/flake8-pyi rules (PYI) by @DimitriPapadopoulos in https://github.com/pypa/packaging/pull/835 * Better local runs for codespell by @henryiii in https://github.com/pypa/packaging/pull/911 * Remove outdated/confusing Gist link by @stefan6419846 in https://github.com/pypa/packaging/pull/921 * Fix docs and docs ci after #897 landed by @notatallshaw in https://github.com/pypa/packaging/pull/926 * Run twine-check on push in CI by @EpicWink in https://github.com/pypa/packaging/pull/922 * `ruff` was renamed `ruff-check` in pre-commit by @henryiii in https://github.com/pypa/packaging/pull/933 * Fix incorrectly implicitly concatenated string in specifiers test by @notatallshaw in https://github.com/pypa/packaging/pull/946 * Simplify conditional by @ofek in https://github.com/pypa/packaging/pull/949 * Modernize nox, use dependency-groups for tests by @henryiii in https://github.com/pypa/packaging/pull/952 * Add more checks that don't affect anything by @henryiii in https://github.com/pypa/packaging/pull/957 * Enable Ruff ISC rule by @henryiii in https://github.com/pypa/packaging/pull/959 * Ruff code FLY by @henryiii in https://github.com/pypa/packaging/pull/963 * pytest `log_level` is better than `log_cli_level` by @henryiii in https://github.com/pypa/packaging/pull/956 * Ruff code TRY by @henryiii in https://github.com/pypa/packaging/pull/961 * Add the ruff PL checks by @henryiii in https://github.com/pypa/packaging/pull/964 * Enable Ruff ARG rules by @henryiii in https://github.com/pypa/packaging/pull/958 * Ruff PT code (pytest) by @henryiii in https://github.com/pypa/packaging/pull/960 * Add ruff DTZ by @henryiii in https://github.com/pypa/packaging/pull/968 * Add ruff BLE by @henryiii in https://github.com/pypa/packaging/pull/967 * Add the ruff SIM checks by @henryiii in https://github.com/pypa/packaging/pull/966 * Adding ruff PERF by @henryiii in https://github.com/pypa/packaging/pull/969 * Move some config into coverage config by @henryiii in https://github.com/pypa/packaging/pull/971 * Check ruff C4 by @henryiii in https://github.com/pypa/packaging/pull/962 * Adding ruff T20 by @henryiii in https://github.com/pypa/packaging/pull/972 * Add a tests pass job by @henryiii in https://github.com/pypa/packaging/pull/977 * Add ruff TC by @henryiii in https://github.com/pypa/packaging/pull/980 * Adding part of ruff RET by @henryiii in https://github.com/pypa/packaging/pull/979 * Reorder mypy check by @henryiii in https://github.com/pypa/packaging/pull/983 * Enable ruff ALL by @henryiii in https://github.com/pypa/packaging/pull/984 * Link back to repo/source in furo by @henryiii in https://github.com/pypa/packaging/pull/991 * Add case insensitivity tests for arbitrary equality by @notatallshaw in https://github.com/pypa/packaging/pull/975 * Synchronize documentation and code for markers by @zahlman in https://github.com/pypa/packaging/pull/1008 * Use `partition` in `_parse_project_urls` by @henryiii in https://github.com/pypa/packaging/pull/1013 * auto-skip the dependabot PRs in the release changelog generation by @henryiii in https://github.com/pypa/packaging/pull/1016 * Update unreleased section in changelog by @henryiii in https://github.com/pypa/packaging/pull/1017 * Fix PR role to match extlinks by @hugovk in https://github.com/pypa/packaging/pull/1020 * Mention new parts in README by @henryiii in https://github.com/pypa/packaging/pull/1023 * Replace a couple of asserts with else by @henryiii in https://github.com/pypa/packaging/pull/1027 * Simplify and/or check a little more by @henryiii in https://github.com/pypa/packaging/pull/1031 * Use slim runner for all check by @henryiii in https://github.com/pypa/packaging/pull/1021 * Use typos instead of codespell by @henryiii in https://github.com/pypa/packaging/pull/1015 * Update changelog with recent additions by @henryiii in https://github.com/pypa/packaging/pull/1034 * Publish to PyPI via GitHub CI by @EpicWink in https://github.com/pypa/packaging/pull/893 * Use prek for faster pre-commit lint step by @henryiii in https://github.com/pypa/packaging/pull/1037 * Add help text to noxfile by @henryiii in https://github.com/pypa/packaging/pull/1038 * Update licenses to 3.27 by @henryiii in https://github.com/pypa/packaging/pull/1036 * Use relative import in `packaging.licenses` by @notatallshaw in https://github.com/pypa/packaging/pull/1039 * Add zizmor and tighten up CI by @henryiii in https://github.com/pypa/packaging/pull/1035 * Fix release script by @henryiii in https://github.com/pypa/packaging/pull/1040 * Fix using a dev version (again) by @henryiii in https://github.com/pypa/packaging/pull/1041 * Fix type hint of function used with `contextlib.contextmanager` by @SpecLad in https://github.com/pypa/packaging/pull/1046 * Always run tests by @henryiii in https://github.com/pypa/packaging/pull/1044 * Fix a changelog number by @henryiii in https://github.com/pypa/packaging/pull/1042 * Fix the publish job by @henryiii in https://github.com/pypa/packaging/pull/1043 * Get the correct tag on publish by @henryiii in https://github.com/pypa/packaging/pull/1045 * Test on first public release of CPython 3.11 and newer by @henryiii in https://github.com/pypa/packaging/pull/1056 * Fix publication job (again) by @henryiii in https://github.com/pypa/packaging/pull/1051 * Use `actionlint` to check CI workflows by @miketheman in https://github.com/pypa/packaging/pull/1052 * Fix formatting of distribution types in metadata.rst by @brettcannon in https://github.com/pypa/packaging/pull/1053 ## New Contributors * @cdce8p made their first contribution in https://github.com/pypa/packaging/pull/881 * @dholth made their first contribution in https://github.com/pypa/packaging/pull/860 * @trim21 made their first contribution in https://github.com/pypa/packaging/pull/908 * @yarikoptic made their first contribution in https://github.com/pypa/packaging/pull/910 * @cthoyt made their first contribution in https://github.com/pypa/packaging/pull/868 * @bwoodsend made their first contribution in https://github.com/pypa/packaging/pull/879 * @stefan6419846 made their first contribution in https://github.com/pypa/packaging/pull/921 * @bearomorphism made their first contribution in https://github.com/pypa/packaging/pull/913 * @EpicWink made their first contribution in https://github.com/pypa/packaging/pull/922 * @Liam-DeVoe made their first contribution in https://github.com/pypa/packaging/pull/932 * @subhajitsaha01 made their first contribution in https://github.com/pypa/packaging/pull/930 * @ncoghlan made their first contribution in https://github.com/pypa/packaging/pull/973 * @zahlman made their first contribution in https://github.com/pypa/packaging/pull/1008 * @JP-Ellis made their first contribution in https://github.com/pypa/packaging/pull/939 ## Since last RC Fixes: * Restore `._version` as a compat shim by @henryiii in https://github.com/pypa/packaging/pull/1062 Performance: * Dual replace by @henryiii in https://github.com/pypa/packaging/pull/1064 Documentaiton: * Prepare for 26.0 final by @henryiii in https://github.com/pypa/packaging/pull/1063 **Full Changelog**: https://github.com/pypa/packaging/compare/26.0rc3...26.0 ### [`26.1`](https://github.com/pypa/packaging/releases/tag/26.1): 26.1 [Compare source](https://github.com/pypa/packaging/compare/25.0...26.1) [Source](https://github.com/pypa/packaging) Source ref: <code>main</code> Features: * ~~PEP 783: add handling for Emscripten wheel tags by @hoodmane in https://github.com/pypa/packaging/pull/804~~ (old name used in implementation, will be fixed in next release) * PEP 803: add handling for the `abi3.abi3t` free-threading tag by @ngoldbaum in https://github.com/pypa/packaging/pull/1099 * PEP 723: add `packaging.dependency_groups` module, based on the `dependency-groups` package by @sirosen in https://github.com/pypa/packaging/pull/1065 * Add the `packaging.direct_url` module by @sbidoul in https://github.com/pypa/packaging/pull/944 * Add the `packaging.errors` module by @henryiii in https://github.com/pypa/packaging/pull/1071 * Add `SpecifierSet.is_unsatisfiable` using ranges (new internals that will be expanded in future versions) by @notatallshaw in https://github.com/pypa/packaging/pull/1119 * Add `create_compatible_tags_selector` to select compatible tags by @sbidoul in https://github.com/pypa/packaging/pull/1110 * Add a `key` argument to `SpecifierSet.filter()` by @frostming in https://github.com/pypa/packaging/pull/1068 * Support `&` and `|` for `Marker`'s by @henryiii in https://github.com/pypa/packaging/pull/1146 * Normalize `Version.__replace__` and add `Version.from_parts` by @henryiii in https://github.com/pypa/packaging/pull/1078 * Add an option to validate compressed tag set sort order in `parse_wheel_filename` by @r266-tech in https://github.com/pypa/packaging/pull/1150 Behavior adaptations: * Narrow exclusion of pre-releases for `<V.postN` to match spec by @notatallshaw in https://github.com/pypa/packaging/pull/1140 * Narrow exclusion of post-releases for `>V` to match spec by @notatallshaw in https://github.com/pypa/packaging/pull/1141 * Rename `format_full_version` to `_format_full_version` to make it visibly private by @r266-tech in https://github.com/pypa/packaging/pull/1125 * Restrict local version to ASCII by @henryiii in https://github.com/pypa/packaging/pull/1102 Pylock (PEP 751) updates: * Add pylock `select` function by @sbidoul in https://github.com/pypa/packaging/pull/1092 * Document pylock `select()` method and `PylockSelectError` by @r266-tech in https://github.com/pypa/packaging/pull/1153 * Add `filename` property to `PackageSdist` and `PackageWheel`, more validation by @sbidoul in https://github.com/pypa/packaging/pull/1095 * Give preference to path over url by @sbidoul in https://github.com/pypa/packaging/pull/1128 * Validate name/version consistency in file names by @sbidoul in https://github.com/pypa/packaging/pull/1114 Fixes: * Fix `>` comparison for versions with dev+local segments by @veeceey in https://github.com/pypa/packaging/pull/1097 * Fix incorrect self-comparison for `InfinityType` and `NegativeInfinityType` by @bysiber in https://github.com/pypa/packaging/pull/1093 * Canonicalize when deduplicating specifiers in `SpecifierSet` by @notatallshaw in https://github.com/pypa/packaging/pull/1109 * Fix charset error message formatting by @notatallshaw in https://github.com/pypa/packaging/pull/1121 * Handle the `key` parameter in `SpecifierSet.filter` when specifiers are empty and prerelease is `False` by @notatallshaw in https://github.com/pypa/packaging/pull/1096 * Standardize inner components of `repr` output by @henryiii in https://github.com/pypa/packaging/pull/1090 * `Specifier`'s `===` uses original string, not normalized, when available by @notatallshaw in https://github.com/pypa/packaging/pull/1124 * Propagate int-max-str-digits `ValueError` by @notatallshaw in https://github.com/pypa/packaging/pull/1155 Performance: * Add fast path for parsing simple versions (digits and dots only) by @notatallshaw in https://github.com/pypa/packaging/pull/1082 * Add fast path for `Version` to `Version` comparison by skipping `_key` property by @notatallshaw in https://github.com/pypa/packaging/pull/1083 * Cache `Version` hash value in dedicated slot by @notatallshaw in https://github.com/pypa/packaging/pull/1118 * Overhaul `_cmpkey` to remove use of custom objects by @notatallshaw in https://github.com/pypa/packaging/pull/1116 * Skip `__replace__` in Specifier comparison if not needed by @notatallshaw in https://github.com/pypa/packaging/pull/1081 * `SpecifierSet` use `tuple` instead of `frozenset` for `_specs` by @notatallshaw in https://github.com/pypa/packaging/pull/1108 * Speed up complex `SpecifierSet` filtering by implementing cost-based ordering by @notatallshaw in https://github.com/pypa/packaging/pull/1105 * Speed up wildcard comparison by @notatallshaw in https://github.com/pypa/packaging/pull/1111 * Stream PEP440 filtering in `SpecifierSet.filter` by @notatallshaw in https://github.com/pypa/packaging/pull/1076 * Add `__slots__` to `Marker` by @henryiii in https://github.com/pypa/packaging/pull/1147 * Simply `Specifier` regex by @sirosen in https://github.com/pypa/packaging/pull/1106 * Skip using the hash property internally by @notatallshaw in https://github.com/pypa/packaging/pull/1115 Internal: * Add downstream testing by @henryiii in https://github.com/pypa/packaging/pull/1049 * Benchmarking suite by @henryiii in https://github.com/pypa/packaging/pull/1059 * Benchmark variance reduction by @notatallshaw in https://github.com/pypa/packaging/pull/1107 * Add property-based tests for PEP 440 by @notatallshaw in https://github.com/pypa/packaging/pull/1144 * Clean up a few `collections.namedtuple` in tests by @henryiii in https://github.com/pypa/packaging/pull/1070 * Do not reload the tags module in tests by @henryiii in https://github.com/pypa/packaging/pull/1152 * Limit `dir()` / tab-completion in REPL by @henryiii in https://github.com/pypa/packaging/pull/1011 * Add more `__all__`/`__dir__` by @henryiii in https://github.com/pypa/packaging/pull/1069 * Cleanup pre-commit a bit by @henryiii in https://github.com/pypa/packaging/pull/1080 * Pin pre-commit file, use dependabot by @henryiii in https://github.com/pypa/packaging/pull/1133 * Remove sphinx-toolbox by @henryiii in https://github.com/pypa/packaging/pull/1135 * Use docs group, faster readthedocs by @henryiii in https://github.com/pypa/packaging/pull/1061 * Add free-threaded Python to CI by @henryiii in https://github.com/pypa/packaging/pull/1098 * Simplify combining `SpecifierSet.prereleases` by @notatallshaw in https://github.com/pypa/packaging/pull/1073 * Use direct operator methods in `_compare_compatible` by @notatallshaw in https://github.com/pypa/packaging/pull/1100 * Remove unnecessary if statement in `Specifier.prereleases` by @notatallshaw in https://github.com/pypa/packaging/pull/1074 * Remove unneeded nesting in `Specifier.prereleases` by @notatallshaw in https://github.com/pypa/packaging/pull/1072 Documentation: * Fix documentation: grammar, typos, formatting, and outdated references by @DimitriPapadopoulos in https://github.com/pypa/packaging/pull/1084 * Fix versionadded for `Version.from_parts()` by @Jackenmen in https://github.com/pypa/packaging/pull/1134 * Document `&` and `|` operators for combining `Marker` objects by @r266-tech in https://github.com/pypa/packaging/pull/1151 * Expand and clean up `Version` documentation by @henryiii in https://github.com/pypa/packaging/pull/1089 * Move license docs inline by @henryiii in https://github.com/pypa/packaging/pull/1131 * Move markers inline by @henryiii in https://github.com/pypa/packaging/pull/1104 * Move tags docs to inline by @henryiii in https://github.com/pypa/packaging/pull/1130 * Move utilities inline, like other modules by @henryiii in https://github.com/pypa/packaging/pull/1103 ## Benchmarks Performance improvements since 26.0, from the new integrated benchmark suite: ``` uv run asv run 26.0..HEAD ``` <img width="908" height="965" alt="Screenshot 2026-04-13 at 11 32 14 PM" src="https://github.com/user-attachments/assets/3bf63569-dbbf-4f34-9660-ede3cef1745d" /> <img width="908" height="479" alt="Screenshot 2026-04-13 at 11 32 43 PM" src="https://github.com/user-attachments/assets/f7906800-f6d9-4af6-a3f3-369b654b73e3" /> ## New Contributors * @veeceey made their first contribution in https://github.com/pypa/packaging/pull/1097 * @bysiber made their first contribution in https://github.com/pypa/packaging/pull/1093 * @sirosen made their first contribution in https://github.com/pypa/packaging/pull/1106 * @Jackenmen made their first contribution in https://github.com/pypa/packaging/pull/1134 * @ngoldbaum made their first contribution in https://github.com/pypa/packaging/pull/1099 * @r266-tech made their first contribution in https://github.com/pypa/packaging/pull/1151 * @hoodmane made their first contribution in https://github.com/pypa/packaging/pull/804 **Full Changelog**: https://github.com/pypa/packaging/compare/26.0...26.1 ### [`26.2`](https://github.com/pypa/packaging/releases/tag/26.2): 26.2 [Compare source](https://github.com/pypa/packaging/compare/25.0...26.2) [Source](https://github.com/pypa/packaging) Source ref: <code>main</code> ## What's Changed Fixes: * Fix incorrect sysconfig var name for pyemscripten by @ryanking13 in https://github.com/pypa/packaging/pull/1160 * Make `Version`, `Specifier`, `SpecifierSet`, `Tag`, `Marker`, and `Requirement` pickle-safe and backward-compatible with pickles created in 25.0-26.1 (including references to the removed ``packaging._structures`` module) by @eachimei and @henryiii in https://github.com/pypa/packaging/pull/1163, https://github.com/pypa/packaging/pull/1168, https://github.com/pypa/packaging/pull/1170, and https://github.com/pypa/packaging/pull/1171 * fix: re-export ExceptionGroup for now by @henryiii in https://github.com/pypa/packaging/pull/1164 Documentation: * docs: add errors section and fix missing details by @henryiii in https://github.com/pypa/packaging/pull/1159 * docs(dev): document property-based test suite by @r266-tech in https://github.com/pypa/packaging/pull/1167 * Fix typo in DirectUrl documentation by @sbidoul in https://github.com/pypa/packaging/pull/1169 * docs(specifiers): add is_unsatisfiable() usage example by @r266-tech in https://github.com/pypa/packaging/pull/1166 Internal: * Enable the auditor persona on zizmor by @henryiii in https://github.com/pypa/packaging/pull/1158 * Test new pickle guarantees by @henryiii in https://github.com/pypa/packaging/pull/1174 * Use native uv integration in rtd by @henryiii in https://github.com/pypa/packaging/pull/1175 ## New Contributors * @ryanking13 made their first contribution in https://github.com/pypa/packaging/pull/1160 * @eachimei made their first contribution in https://github.com/pypa/packaging/pull/1163 **Full Changelog**: https://github.com/pypa/packaging/compare/26.1...26.2 ### [`26.3`](https://github.com/pypa/packaging/releases/tag/26.3): 26.3 [Compare source](https://github.com/pypa/packaging/compare/25.0...26.3) [Source](https://github.com/pypa/packaging) Source ref: <code>main</code> <!-- Release notes generated using configuration in .github/release.yml at 26.3 --> ## What's Changed ### Features * Add a public `VersionRange` API and `SpecifierSet.to_range()`, representing the versions a specifier set accepts as an interval set that supports intersection, union, difference, complement, set relations, membership tests, and filtering. `VersionRange.to_specifier_set()` converts a range back to a `SpecifierSet` where a PEP 440 form exists. ([#1267](https://github.com/pypa/packaging/pull/1267), [#1270](https://github.com/pypa/packaging/pull/1270), [#1298](https://github.com/pypa/packaging/pull/1298)) * PEP 808: accept `Metadata-Version: 2.6`. ([#1194](https://github.com/pypa/packaging/pull/1194)) * Add a `limit` argument to `parse_tag()` for compressed tag sets. ([#1220](https://github.com/pypa/packaging/issues/1220)) * Add a `prefer_sdist_predicate` argument to `Pylock.select()` to prefer source distributions over wheels for selected packages. ([#1334](https://github.com/pypa/packaging/pull/1334)) * Add `pure_python_tags()` to generate the pure-Python tags for a Python version without touching the running platform. ([#1346](https://github.com/pypa/packaging/pull/1346)) * Add `SpecifierSet.is_subset()`, `SpecifierSet.is_superset()`, and `SpecifierSet.is_disjoint()`, which compare the versions two specifier sets accept. ([#1313](https://github.com/pypa/packaging/pull/1313)) ### Behavior adaptations * Drop support for Python 3.8; packaging now requires Python 3.9 or later. ([#1157](https://github.com/pypa/packaging/pull/1157)) * Prefer native `linux_*` platform tags over `manylinux` and `musllinux` tags on Linux. ([#160](https://github.com/pypa/packaging/issues/160)) ### Fixes for versions and specifiers * Raise `InvalidVersion` instead of `TypeError` when `Version` is given a non-string. ([#1319](https://github.com/pypa/packaging/pull/1319)) * Raise `InvalidVersion` for non-string pre-release letters passed to `Version.from_parts`. ([#1241](https://github.com/pypa/packaging/pull/1241)) * Fix an `AttributeError` when hashing internally trimmed versions. ([#1242](https://github.com/pypa/packaging/pull/1242)) * Fix `SpecifierSet.is_unsatisfiable` for post-release boundary intersections. ([#1257](https://github.com/pypa/packaging/pull/1257)) ### Fixes for requirements and markers * Make `Requirement.__hash__` consistent with `__eq__` for trailing-zero-equivalent specifiers (e.g. `foo==1.0.0` and `foo==1.0.0.0`), so equal requirements hash equal and deduplicate in sets and dicts. ([#1232](https://github.com/pypa/packaging/pull/1232)) * Normalize requested extra names before comparing or hashing requirements. ([#644](https://github.com/pypa/packaging/issues/644)) * Preserve a `Requirement`'s specifier `prereleases` override across a pickle round trip. ([#1204](https://github.com/pypa/packaging/issues/1204)) * Raise `InvalidRequirement` instead of `InvalidSpecifier` when a requirement contains an invalid specifier. ([#1332](https://github.com/pypa/packaging/pull/1332)) * Clarify the error for post-release prefix wildcards like `==1.0.post1.*`. ([#1299](https://github.com/pypa/packaging/pull/1299)) * Preserve quoting semantics when serializing marker values, so round-tripped markers parse back to the same marker. ([#1213](https://github.com/pypa/packaging/pull/1213)) * Keep the parentheses of a nested group when serializing markers. ([#1316](https://github.com/pypa/packaging/pull/1316)) * Normalize `extra` and `dependency_groups` values in nested markers at parse time. ([#1246](https://github.com/pypa/packaging/pull/1246), [#1310](https://github.com/pypa/packaging/pull/1310)) * Raise `UndefinedComparison` when a set-valued variable like `extras` is used outside the membership form. ([#1265](https://github.com/pypa/packaging/pull/1265)) * Raise `UndefinedEnvironmentName` (a `KeyError` subclass) for missing environment keys during marker evaluation. ([#1276](https://github.com/pypa/packaging/pull/1276)) * Wrap malformed string literal errors in `InvalidMarker` / `InvalidRequirement` instead of leaking a low-level error. ([#1249](https://github.com/pypa/packaging/pull/1249)) * Reject requirements and markers with a trailing line break. ([#1345](https://github.com/pypa/packaging/pull/1345)) ### Fixes for metadata and licenses * Collect all `from_email` validation errors into one `ExceptionGroup` instead of raising the first. ([#1268](https://github.com/pypa/packaging/pull/1268)) * Accept the UTF-8 charset case-insensitively in email payloads. ([#1330](https://github.com/pypa/packaging/pull/1330)) * Reject malformed `Description-Content-Type` values. ([#1329](https://github.com/pypa/packaging/pull/1329)) * Don't rewrite user values that contain `{field}` placeholders in error messages. ([#1327](https://github.com/pypa/packaging/pull/1327)) * Route multipart email payloads to `unparsed` instead of asserting. ([#1247](https://github.com/pypa/packaging/pull/1247)) * Make `InvalidMetadata` and `CyclicDependencyGroup` picklable. ([#1328](https://github.com/pypa/packaging/pull/1328)) * Fold every line boundary `str.splitlines` recognizes when writing a header with `RFC822Message`. ([#1356](https://github.com/pypa/packaging/pull/1356)) * Raise `InvalidLicenseExpression` for misplaced `WITH` clauses and empty `LicenseRef-` names. ([#1266](https://github.com/pypa/packaging/pull/1266)) * Raise `InvalidLicenseExpression` instead of `KeyError` for a `LicenseRef-` with a `+` suffix. ([#1219](https://github.com/pypa/packaging/pull/1219)) ### Fixes for tags and filenames * Raise `InvalidTag` from `parse_tag()` for tags with the wrong number of components. ([#1238](https://github.com/pypa/packaging/pull/1238)) * Reject empty tag components in `parse_wheel_filename()` and `parse_tag()`. ([#1234](https://github.com/pypa/packaging/pull/1234)) * Reject an empty project name in the wheel and sdist filename parsers. ([#1305](https://github.com/pypa/packaging/pull/1305)) * Reject wheel filenames with a trailing newline. ([#1341](https://github.com/pypa/packaging/pull/1341)) * Reject wheel tags whose interpreter component is not an identifier. ([#577](https://github.com/pypa/packaging/issues/577)) * `is_normalized_name` now rejects names with collapsed double hyphens like `a--b`. ([#1230](https://github.com/pypa/packaging/pull/1230)) * Fix duplicate explicit `abi3t` tags. ([#1245](https://github.com/pypa/packaging/pull/1245)) * Forward the `warn` argument to `generic_tags()` in `sys_tags()`. ([#1264](https://github.com/pypa/packaging/pull/1264)) * Raise `SystemError` for an empty or malformed CPython `EXT_SUFFIX`. ([#1271](https://github.com/pypa/packaging/pull/1271), [#1301](https://github.com/pypa/packaging/pull/1301)) * Fix a typo in the macOS `fat3` architecture name (was `fat32`). ([#1199](https://github.com/pypa/packaging/pull/1199)) ### Fixes for pylock, direct URLs, and dependency groups * Percent-decode `pylock` artifact file names derived from a `url` so that local versions (e.g. a wheel with `2.12.1+cu130` encoded as `2.12.1%2Bcu130`) yield a valid file name. ([#1314](https://github.com/pypa/packaging/pull/1314)) * Use an explicitly empty `tags` sequence in `Pylock.select()` instead of falling back to `sys_tags()`. ([#1349](https://github.com/pypa/packaging/pull/1349)) * Fix `Pylock.select()` on Python builds that report a non-PEP 440 `python_full_version` (e.g. `3.15.0+`). ([#1179](https://github.com/pypa/packaging/pull/1179)) * Reject TOML booleans where integers are expected in `pylock` files. ([#1244](https://github.com/pypa/packaging/pull/1244)) * Add `PylockSelectError` to `packaging.pylock.__all__`. ([#1202](https://github.com/pypa/packaging/pull/1202)) * Fix `DirectUrl` credential stripping for passwords containing `@`. ([#1218](https://github.com/pypa/packaging/pull/1218)) * Parse the URL scheme case-insensitively when checking for file URLs in `direct_url`. ([#1240](https://github.com/pypa/packaging/pull/1240)) * Require absolute file URLs for local directories in `direct_url`. ([#1297](https://github.com/pypa/packaging/pull/1297)) * Collect `InvalidRequirement` errors while resolving dependency groups instead of leaking them. ([#1302](https://github.com/pypa/packaging/pull/1302)) * Don't cache malformed dependency group parses. ([#1248](https://github.com/pypa/packaging/pull/1248)) ### Performance * Implement `Specifier` and `SpecifierSet` filtering with the new range engine. ([#1120](https://github.com/pypa/packaging/pull/1120), [#1259](https://github.com/pypa/packaging/pull/1259)) * Cache the default marker environment. ([#1250](https://github.com/pypa/packaging/pull/1250)) * Cache the `_manylinux` module lookup process-wide. ([#1254](https://github.com/pypa/packaging/pull/1254)) * Add `__slots__` to `Requirement` and the token classes. ([#1320](https://github.com/pypa/packaging/pull/1320), [#1258](https://github.com/pypa/packaging/pull/1258)) * Keep range caches across canonicalization, precompile the wheel project-name pattern, simplify `parse_tag()`, and skip `platform.mac_ver()` when the version and arch are given. ([#1253](https://github.com/pypa/packaging/pull/1253), [#1256](https://github.com/pypa/packaging/pull/1256), [#1236](https://github.com/pypa/packaging/pull/1236), [#1255](https://github.com/pypa/packaging/pull/1255)) ### Documentation * Describe the validation scope of `packaging.pylock`. ([#1339](https://github.com/pypa/packaging/pull/1339)) * Explain which `packaging.metadata` fields are validated. ([#1342](https://github.com/pypa/packaging/pull/1342)) * Document `RFC822Policy` in the low-level `packaging.metadata` interface. ([#1222](https://github.com/pypa/packaging/pull/1222)) * Enable nitpicky mode and render missing classes and fields in the API reference. ([#1196](https://github.com/pypa/packaging/pull/1196), [#1225](https://github.com/pypa/packaging/pull/1225), [#1277](https://github.com/pypa/packaging/pull/1277)) * Add missing `versionadded` / `versionchanged` directives and many small docstring fixes across the API reference. ([#1205](https://github.com/pypa/packaging/pull/1205), [#1207](https://github.com/pypa/packaging/pull/1207), [#1208](https://github.com/pypa/packaging/pull/1208), [#1209](https://github.com/pypa/packaging/pull/1209), [#1211](https://github.com/pypa/packaging/pull/1211), [#1216](https://github.com/pypa/packaging/pull/1216), [#1217](https://github.com/pypa/packaging/pull/1217), [#1223](https://github.com/pypa/packaging/pull/1223), [#1272](https://github.com/pypa/packaging/pull/1272), [#1273](https://github.com/pypa/packaging/pull/1273), [#1274](https://github.com/pypa/packaging/pull/1274), [#1291](https://github.com/pypa/packaging/pull/1291), [#1300](https://github.com/pypa/packaging/pull/1300), [#1303](https://github.com/pypa/packaging/pull/1303), [#1317](https://github.com/pypa/packaging/pull/1317), [#1344](https://github.com/pypa/packaging/pull/1344)) ### Internal * Add Python 3.15 to the test matrix. ([#1190](https://github.com/pypa/packaging/pull/1190)) * Add a musl/Alpine test job and make the test suite pass on musl. ([#1226](https://github.com/pypa/packaging/pull/1226), [#1227](https://github.com/pypa/packaging/pull/1227)) * Expand the downstream test matrix by ten projects. ([#1261](https://github.com/pypa/packaging/pull/1261)) * Update to mypy 2. ([#1191](https://github.com/pypa/packaging/pull/1191)) * Use nox's uv integration. ([#1057](https://github.com/pypa/packaging/pull/1057)) ## New Contributors * @Sean-Kenneth-Doherty made their first contribution in https://github.com/pypa/packaging/pull/1187 * @jsirois made their first contribution in https://github.com/pypa/packaging/pull/1199 * @Alan-K-Biju-7 made their first contribution in https://github.com/pypa/packaging/pull/1217 * @facutuesca made their first contribution in https://github.com/pypa/packaging/pull/1218 * @NovaLux12 made their first contribution in https://github.com/pypa/packaging/pull/1317 * @atsuoishimoto made their first contribution in https://github.com/pypa/packaging/pull/1314 * @gaoflow made their first contribution in https://github.com/pypa/packaging/pull/1291 * @jacobdr made their first contribution in https://github.com/pypa/packaging/pull/608 * @deepakganesh78 made their first contribution in https://github.com/pypa/packaging/pull/1351 * @rajath201 made their first contribution in https://github.com/pypa/packaging/pull/1356 **Full Changelog**: https://github.com/pypa/packaging/compare/26.2...26.3 </details> <details> <summary>propcache (0.4.1 → 0.5.4)</summary> ### [`v0.5.1`](https://github.com/aio-libs/propcache/releases/tag/v0.5.1): 0.5.1 [Compare source](https://github.com/aio-libs/propcache/compare/v0.4.1...v0.5.1) [Source](https://github.com/aio-libs/propcache) Source ref: <code>master</code> No significant changes. ---- ### [`0.5.2`](https://github.com/aio-libs/propcache/releases/tag/v0.5.2): 0.5.2 **Breaking change detected.** [Compare source](https://github.com/aio-libs/propcache/compare/v0.4.1...v0.5.2) [Source](https://github.com/aio-libs/propcache) Source ref: <code>master</code> 0.5.0 and 0.5.1 were tagged earlier today but never reached PyPI: 0.5.0's deploy failed at cibuildwheel's post-build pytest on free-threaded armv7l musllinux (SIGBUS under QEMU emulation while importing the C extension), and 0.5.1's deploy hit a transient sigstore Rekor 502 during the attestation step. 0.5.2 is the first of the three to actually publish. Features -------- - Added support for newer type hints and remove ``Optional`` and ``Union`` from all annotations -- by :user:`Vizonex` *Related issues and pull requests on GitHub:* #193. Removals and backward incompatible breaking changes --------------------------------------------------- - Dropped support for Python 3.9 as it has reached end of life. *Related issues and pull requests on GitHub:* #216. Packaging updates and notes for downstreams ------------------------------------------- - Changed the Cython build dependency from ``~= 3.1.0`` to ``>= 3.2.0``, removing the upper version bound to avoid conflicts for downstream packagers -- by :user:`jameshilliard` and :user:`gundalow`. The upstream Cython version is pinned to 3.2.4 in the CI/CD environment. *Related issues and pull requests on GitHub:* #184, #188, #214. - Start building and shipping riscv64 wheels -- by :user:`justeph`. *Related issues and pull requests on GitHub:* #194. - The :pep:`517` build backend now supports a new ``build-inplace`` config setting (and ``PROPCACHE_BUILD_INPLACE`` environment variable) for controlling whether to build the project in-tree or in a temporary directory. It only affects wheels and is set up to build in a temporary directory by default. It does not affect editable wheel builds; they will keep being built in-tree regardless. Here's an example of using this setting: .. code-block:: console $ python -m build --config-setting=build-inplace=true Additionally, when building wheels in an automatically created temporary directory, the build backend now normalizes the respective file system path to a deterministic source checkout directory by injecting the ``-ffile-prefix-map`` compiler option into the ``CFLAGS`` environment variable, as suggested by known `reproducible build practices <https://reproducible-builds.org/docs/build-path/>`__. The effect is that downstreams will get reproducible build results. *Related issues and pull requests on GitHub:* #218. ---- ### [`0.5.3`](https://github.com/aio-libs/propcache/releases/tag/v0.5.3): 0.5.3 **Breaking change detected.** [Compare source](https://github.com/aio-libs/propcache/compare/v0.4.1...v0.5.3) [Source](https://github.com/aio-libs/propcache) Source ref: <code>master</code> Bug fixes --------- - Fixed a possible crash in the C implementation of ``cached_property`` and ``under_cached_property`` on free-threaded Python, where a cached value could be freed by another thread while it was being read; errors raised while looking up the cache are now propagated on all builds, and the computed value is no longer leaked if storing it fails -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #297. Removals and backward incompatible breaking changes --------------------------------------------------- - Dropped support for free-threaded Python 3.13 -- by :user:`Vizonex`. *Related issues and pull requests on GitHub:* #223. Improved documentation ---------------------- - Updated discussion links from the defunct Google Groups forum to GitHub Discussions -- by :user:`gundalow`. *Related issues and pull requests on GitHub:* #217. Packaging updates and notes for downstreams ------------------------------------------- - The ``setuptools`` build dependency lower bound has been restored to be ``>= 47`` after an incorrect automated increase in :pr:`207` -- by :user:`bbhtt`. *Related issues and pull requests on GitHub:* #207. - Dropped support for free-threaded Python 3.13 -- by :user:`Vizonex`. *Related issues and pull requests on GitHub:* #223. - Dropped the deprecated ``License :: OSI Approved :: Apache Software License`` classifier; ``setuptools`` 84 warns about it and the dist build treats warnings as errors, so releases could no longer be built -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #299. Contributor-facing changes -------------------------- - Dependabot has been restricted to the ``requirements`` subdirectory to avoid unintended updates outside dependency requirement files -- by :user:`bbhtt`. *Related issues and pull requests on GitHub:* #207. - Added an ``AGENTS.md`` file with contributor guidance for AI coding agents, adapted from the ``yarl`` equivalent -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #231. - Migrated from standalone ``black`` and ``isort`` pre-commit hooks to ``ruff format`` and the ruff ``I`` lint rule, sharing a new ``[tool.ruff]`` config in ``pyproject.toml``. ``ruff-check`` runs with ``--fix`` so import-order fixes apply on commit, and the orphan ``[isort]`` block in ``setup.cfg`` was removed -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #232. - Switched the ``cibuildwheel`` build frontend to ``build[uv]`` so that ``uv`` provisions every build and test virtual environment in the wheel matrix. Test-dependency installation in particular drops from a multi-second ``pip install`` per ABI to a roughly sub-second ``uv`` resolve -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #234. - Dropped the ``libffi-devel`` install from the ``cibuildwheel`` Linux ``before-all`` step. It was added in :pr:`75` so ``cffi`` could build from source during wheel testing; the current wheel-test chain no longer pulls in ``cffi``, so the header package is dead weight -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #236. - The type preciseness coverage report generated by `MyPy <https://mypy-lang.org>`__ is now uploaded to `Coveralls <https://coveralls.io/github/aio-libs/propcache>`__ and will not be included in the `Codecov views <https://app.codecov.io/gh/aio-libs/propcache>`__ going forward -- by :user:`aiolibsbot`. *Related issues and pull requests on GitHub:* #239. - Switched CI/CD to ``tox-dev/workflow``'s :file:`reusable-tox.yml` driven by an in-tree :file:`tox.ini`. The ``build``, ``metadata-validation`` and ``lint`` (``pre-commit``, ``spellcheck-docs``) jobs all run through the reusable workflow; ``mypy`` coverage uploads to Coveralls from a ``post-tox-job`` hook -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #243. - Overrode ``CIBW_BUILD_FRONTEND=build`` for the QEMU-emulated odd-arch wheel matrix, since the pypa odd-arch container images do not ship ``uv`` preinstalled and the project's :file:`pyproject.toml` sets ``build-frontend = "build[uv]"`` -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #246. - Allowed re-running the deploy job after a partial release failure: the ``Make Release`` step now skips when the GitHub Release already exists, and the PyPI publish step uses ``skip-existing`` so dists that were already uploaded on a prior attempt do not break the retry -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #247. - Switched the aarch64 and armv7l wheel builds to GitHub's native ARM runners. The aarch64 wheels now build without QEMU emulation, and armv7l runs on aarch64 hosts so its 32-bit ARM execution is far cheaper than the previous aarch64-on-x86_64 path -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #248. - Added ``UV_CONSTRAINT`` and ``UV_BUILD_CONSTRAINT`` alongside ``PIP_CONSTRAINT`` and ``PIP_BUILD_CONSTRAINT`` in the ``cibuildwheel`` environment so the :file:`requirements/cython.txt` pin is honored under the ``build[uv]`` frontend; ``uv pip`` ignores the ``PIP_`` variables and reads only the ``UV_`` ones, while the ``PIP_`` variants are kept for the pip fallback path -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #249. - Fixed coverage for testing benchmarks when codspeed is not installed -- by :user:`Vizonex`. *Related issues and pull requests on GitHub:* #251. - Stopped running the test suite inside the wheel build jobs outside of release builds, since the test matrix installs and tests the same wheels, and added Python 3.15 and 3.15t to the test matrix so those wheels stay covered. Off-tag macOS builds are now limited to the architecture the test matrix runs on. Release builds still build every architecture and test every wheel, and all release checks in the CI workflow now use ``github.ref_type`` -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #300. ---- ### [`0.5.4`](https://github.com/aio-libs/propcache/releases/tag/v0.5.4): 0.5.4 [Compare source](https://github.com/aio-libs/propcache/compare/v0.4.1...v0.5.4) [Source](https://github.com/aio-libs/propcache) Source ref: <code>master</code> Packaging updates and notes for downstreams ------------------------------------------- - Fixed the release wheels being compiled without optimization since version 0.5.0. The build backend set ``CFLAGS`` to add ``-ffile-prefix-map``, which replaced the interpreter's own compiler flags instead of extending them, so ``-O3`` and ``-DNDEBUG`` were dropped; the extra flags now go through ``CPPFLAGS``, which is appended. Cached property reads are about 1.5x faster than in 0.5.3 -- by :user:`bdraco`. *Related issues and pull requests on GitHub:* #244, #302. ---- </details> <details> <summary>pygments (2.19.2 → 2.21.0)</summary> ### [`2.20.0`](https://github.com/pygments/pygments/releases/tag/2.20.0): 2.20.0 [Compare source](https://github.com/pygments/pygments/compare/2.19.2...2.20.0) [Source](https://github.com/pygments/pygments) Source ref: <code>master</code> - New lexers: * Rell (#2914) - Updated lexers: * archetype: Fix catastrophic backtracking in GUID and ID patterns (#3064) * ASN.1: Recognize minus sign and fix range operator (#3014, #3060) * C++: Add C++26 keywords (#2955), add integer literal suffixes (#2966) * ComponentPascal: Fix ``analyse_text`` (#3028, #3032) * Coq renamed to Rocq (#2883, #2908) * Cython: Various improvements (#2932, #2933) * Debian control: Improve architecture parsing (#3052) * Devicetree: Add support for overlay/fragments (#3021), add bytestring support (#3022), fix catastrophic backtracking (#3057) * Fennel: Various improvements (#2911) * Haskell: Handle escape sequences in character literals (#3069, #1795) * Java: Add module keywords (#2955) * Lean4: Add operators ``]'``, ``]?``, ``]!`` (#2946) * LESS: Support single-line comments (#3005) * LilyPond: Update to 2.25.29 (#2974) * LLVM: Support C-style comments (#3023, #2978) * Lua(u): Fix catastrophic backtracking (#3047) * Macaulay2: Update to 1.25.05 (#2893), 1.25.11 (#2988) * Mathematica: Various improvements (#2957) * meson: Add additional operators (#2919) * MySQL: Update keywords (#2970) * org-Mode: Support both schedule and deadline (#2899) * PHP: Add ``__PROPERTY__`` magic constant (#2924), add reserved keywords (#3002) * PostgreSQL: Add more keywords (#2985) * protobuf: Fix namespace tokenization (#2929) * Python: Add ``t``-string support (#2973, #3009, #3010) * Tablegen: Fix infinite loop (#2972, #2940) * Tera Term macro: Add commands introduced in v5.3 through v5.6 (#2951) * TOML: Support TOML 1.1.0 (#3026, #3027) * Turtle: Allow empty comment lines (#2980) * XML: Added ``.xbrl`` as file ending (#2890, #2891) - Drop Python 3.8, and add Python 3.14 as a supported version (#2987, #3012) - Various improvements to ``autopygmentize`` (#2894) - Update ``onedark`` style to support more token types (#2977) - Update ``rtt`` style to support more token types (#2895) - Cache entry points to improve performance (#2979) - Fix ``xterm-256`` color table (#3043) - Fix ``kwargs`` dictionary getting mutated on each call (#3044) ### [`2.21.0`](https://github.com/pygments/pygments/releases/tag/2.21.0): 2.21.0 [Compare source](https://github.com/pygments/pygments/compare/2.19.2...2.21.0) [Source](https://github.com/pygments/pygments) Source ref: <code>master</code> - New lexers: * BitBake (#3103) * Caddyfile (#3225) * CEL (#3048) * PureScript (#1077, #3054) - Updated lexers: * Bash: Fix coloured keyword at the beginning of a name (#2926) * Boogie: Add missing Boogie and Civl Verifier keywords (#3156) * C#: - Recognize interpolated verbatim strings with either ``$@`` or ``@$`` prefixes (#2685) - Support dollar-prefixed and multi-quote raw strings (#3129, #2897) - Recognize ``union`` (#3182) * C/C++: - Add C23/C++26 attributes (#3084) - Add more C2Y keywords (#3092) - Highlight a function following a namespace body (#2928) - Fix C/C++ lexer support for multiline pre-processor comments (#3051) - Add ``.ipp`` as a file extension (#3141, #1008) * Clojure: Recognize named, octal and unicode character literals such as ``\space`` and ``\o377`` as a single token (#979) * Csound: Add missing opcode parameter type letter (#3161) * CUDA: Derive from the C++ lexer instead of C to highlight C++ constructs such as ``template``, ``class`` and ``namespace`` (#3127) * D: Allow non-ASCII (Unicode) identifiers (#1088) * Fish: Fix single quote backslash escape (#3138, #2821) * Go: Various lexer improvements (#3199) * GoogleSQL: Require a word break after ``SET`` (#3167) * Hexdump: Only match valid digits (#3200, #2847) * JavaScript: Highlight the ``arguments`` object (#3146) * Jsonnet: Recognize colons in array slice expressions (#2828) * JSX: Allow apostrophes in element text (#2816) * Julia: Fix rstrings backslash (#3140, #2537) * Kotlin: Support companion objects without an explicit name (#2525) * Kotlin: Don't let a nullable type marker (``?``) consume the following character, so ``Foo?,`` and ``a?:b`` tokenize correctly (#2964) * Kusto: Recognize member-access dots in dynamic objects (#2779) * Lua: Various improvements (#3143) * Macaulay2: Update symbols to 1.26.05 (#3120) * Markdown: - Highlight bold-italics (``***...***`` and ``___...___``) (#3067) - Fix mention regex to support hyphens in usernames (#3139, #3135) * Markdown, reStructuredText, TiddlyWiki5: Fix wrong token offsets for embedded code blocks (#3133) * Mathematica: Recognize ``\[Name]`` named-character escapes such as ``\[Nu]`` instead of emitting an ``Error`` token (#3097) * MATLAB, Octave, Scilab: Allow ``...`` line continuations in function definition signatures (#659) * MySQL: Require a word break after ``SET`` (#3110) * PostgreSQL: Add more keywords (#3066) * Python: - Recognize ``sentinel`` (#3114) - Recognize ``frozendict`` (#3119) - Recognize lazy imports (#3115) * reStructuredText: Allow ``.`` and ``+`` in directive/role names (#3085) * Ruby: Don't duplicate the body of an unterminated heredoc (#2998) * Ruby: Treat ``<<`` after ``)``, ``]`` or ``}`` as the shift operator rather than the start of a heredoc (#760) * SCSS: Recognize variable references in property values (#2818) * Shell: Recognize chevron prompts (#3096) * Smithy: Fix text blocks and add missing syntax (#3168) * Swift: Keep ``func`` a keyword in ``class func`` type methods (#1125) * Tcl: Stop ``$name`` variable references at a dash (#1720) * TeX: Recognize LaTeX math environments as math (#3034) * Twig: Allow uppercase letters at the start of identifiers (#3159, #2965) * TypeScript: Only treat ``module`` as a keyword when followed by whitespace, so identifiers like ``modules`` and ``module.exports`` are highlighted correctly (#2823) * Vala: Recognize verbatim strings before ordinary quoted strings (#2861) * Vala: Recognize conditional compilation directives (#2858) * Vim: - Bump the syntax file to vim 9.2 (#3183, #3174) - Small improvements to the VimScript lexer (#3173) * YAML: Add ``yml`` alias (#3169), recognize non-breaking spaces as valid scalar content (#2827) * WebAssembly: Recognize sign-extension operators (#2991, #3160) * XML: Mark SVG files as XML (#3093) - New styles: * Night Owl (#3132) - Fix catastrophic backtracking in ``looks_like_xml`` (#2931, #3112) - Improve monokai theme colors (#3100) - Improve handling of non-string types in ``html_escape`` to fix broken clients (#3090, #3086) - LaTeX formatter: honor the wrapped lexer's ``stripnl`` and other input options when ``escapeinside`` is set, so blank lines are no longer stripped under ``stripnl=false`` (#2975) - RawTokenFormatter: fix a crash when ``error_color`` is set (#3215) - Groff formatter: don't duplicate a character when word-wrapping (``wrap``) a token that is not at the end of a line (#3201) - Add support for Python 3.15 (#3099) - Fix invalid ``-L`` values report success (#3217) - Allow ``transparent`` as a color style definition (#3180, #3170) - HtmlFormatter: ``"`` and ``'`` now render literally (#3185) </details> <details> <summary>pyrefly (1.2.0 → 1.3.1)</summary> ### `1.2.1` ### `1.3.0` ### `1.3.1` </details> <details> <summary>ruff (0.14.11 → 0.16.9)</summary> ### `0.14.12` ### [`0.14.13`](https://github.com/astral-sh/ruff/releases/tag/0.14.13): 0.14.13 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.14.13) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-01-15. This is a follow-up release to 0.14.12. Because of an issue publishing the WASM packages, there is no GitHub release or Git tag for 0.14.12, although the package was published to PyPI. The contents of the 0.14.13 release are identical to 0.14.12. ## 0.14.12 ### Preview features - \[`flake8-blind-except`\] Allow more logging methods (`BLE001`) ([#22057](https://github.com/astral-sh/ruff/pull/22057)) - \[`ruff`\] Respect `lint.pydocstyle.property-decorators` in `RUF066` ([#22515](https://github.com/astral-sh/ruff/pull/22515)) ### Bug fixes - Fix configuration path in `--show-settings` ([#22478](https://github.com/astral-sh/ruff/pull/22478)) - Respect `fmt: skip` for multiple statements on the same logical line ([#22119](https://github.com/astral-sh/ruff/pull/22119)) ### Rule changes - \[`pydocstyle`\] Update Rust crate imperative to v1.0.7 (`D401`) ([#22519](https://github.com/astral-sh/ruff/pull/22519)) - \[`isort`\] Insert imports in alphabetical order (`I002`) ([#22493](https://github.com/astral-sh/ruff/pull/22493)) ### Documentation - Add llms.txt support for documentation ([#22463](https://github.com/astral-sh/ruff/pull/22463)) - Use prek in documentation and CI ([#22505](https://github.com/astral-sh/ruff/pull/22505)) - \[`flake8-pytest-style`\] Add `check` parameter example to `PT017` docs ([#22546](https://github.com/astral-sh/ruff/pull/22546)) - \[`ruff`\] Make example error out-of-the-box (`RUF103`) ([#22558](https://github.com/astral-sh/ruff/pull/22558)) - \[`ruff`\] document `RUF100` trailing comment fix behavior ([#22479](https://github.com/astral-sh/ruff/pull/22479)) ### Other changes - wasm: Require explicit logging initialization ([#22587](https://github.com/astral-sh/ruff/pull/22587)) ### Contributors - [@terror](https://github.com/terror) - [@harupy](https://github.com/harupy) - [@Jkhall81](https://github.com/Jkhall81) - [@dhruvmanila](https://github.com/dhruvmanila) - [@lubaskinc0de](https://github.com/lubaskinc0de) - [@zanieb](https://github.com/zanieb) - [@MeGaGiGaGon](https://github.com/MeGaGiGaGon) - [@charliermarsh](https://github.com/charliermarsh) - [@renovate](https://github.com/renovate) - [@dylwil3](https://github.com/dylwil3) - [@MichaReiser](https://github.com/MichaReiser) - [@11happy](https://github.com/11happy) ## Install ruff 0.14.13 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-installer.ps1 | iex" ``` ## Download ruff 0.14.13 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.13/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ### [`0.14.14`](https://github.com/astral-sh/ruff/releases/tag/0.14.14): 0.14.14 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.14.14) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-01-22. ### Preview features - Preserve required parentheses in lambda bodies ([#22747](https://github.com/astral-sh/ruff/pull/22747)) - Combine range suppression code diagnostics ([#22613](https://github.com/astral-sh/ruff/pull/22613)) - \[`airflow`\] Second positional argument to `Asset`/`Dataset` should not be a dictionary (`AIR303`) ([#22453](https://github.com/astral-sh/ruff/pull/22453)) - \[`ruff`\] Detect duplicate entries in `__all__` (`RUF068`) ([#22114](https://github.com/astral-sh/ruff/pull/22114)) ### Bug fixes - \[`pyupgrade`\] Allow shadowing non-builtin bindings (`UP029`) ([#22749](https://github.com/astral-sh/ruff/pull/22749)) - \[`pyupgrade`\] Apply `UP045` to string arguments of `typing.cast` ([#22320](https://github.com/astral-sh/ruff/pull/22320)) - \[`flake8-pie`\] Detect duplicated declared class fields in `PIE794` ([#22717](https://github.com/astral-sh/ruff/pull/22717)) ### Rule changes - \[`flake8-pyi`\] Fix inconsistent handling of forward references for `__new__`, `__enter__`, `__aenter__` in `PYI034` ([#22798](https://github.com/astral-sh/ruff/pull/22798)) - \[`flake8-pytest-style`\] Support `check` parameter in `PT011` ([#22725](https://github.com/astral-sh/ruff/pull/22725)) - \[`ruff`\] Add exception for `ctypes.Structure._fields_` (`RUF012`) ([#22559](https://github.com/astral-sh/ruff/pull/22559)) - Many fixes are now marked unsafe if they would remove comments: - \[`flake8-bugbear`\] [`B009`](https://github.com/astral-sh/ruff/pull/22656), [`B010`](https://github.com/astral-sh/ruff/pull/22657), [`B013`](https://github.com/astral-sh/ruff/pull/22658), [`B014`](https://github.com/astral-sh/ruff/pull/22659), [`B033`](https://github.com/astral-sh/ruff/pull/22632) - \[`flake8-simplify`\] [`SIM910`](https://github.com/astral-sh/ruff/pull/22662), [`SIM911`](https://github.com/astral-sh/ruff/pull/22661) - \[`pyupgrade`\] [`UP007`](https://github.com/astral-sh/ruff/pull/22772), [`UP039`](https://github.com/astral-sh/ruff/pull/22774), [`UP041`](https://github.com/astral-sh/ruff/pull/22773), [`UP045`](https://github.com/astral-sh/ruff/pull/22772) - \[`refurb`\] [`FURB105`](https://github.com/astral-sh/ruff/pull/22767), [`FURB116`](https://github.com/astral-sh/ruff/pull/22681), [`FURB136`](https://github.com/astral-sh/ruff/pull/22680), [`FURB140`](https://github.com/astral-sh/ruff/pull/22679), [`FURB145`](https://github.com/astral-sh/ruff/pull/22670), [`FURB154`](https://github.com/astral-sh/ruff/pull/22669), [`FURB157`](https://github.com/astral-sh/ruff/pull/22668), [`FURB164`](https://github.com/astral-sh/ruff/pull/22667),[`FURB181`](https://github.com/astral-sh/ruff/pull/22666), [`FURB188`](https://github.com/astral-sh/ruff/pull/22665) - \[`ruff`\] [`RUF019`](https://github.com/astral-sh/ruff/pull/22663), [`RUF020`](https://github.com/astral-sh/ruff/pull/22664) ### Documentation - Add `--exit-non-zero-on-format` to formatter exit codes section ([#22761](https://github.com/astral-sh/ruff/pull/22761)) - Update contributing guide for adding a new rule ([#22779](https://github.com/astral-sh/ruff/pull/22779)) - \[`FastAPI`\] Document fix safety for `FAST001` ([#22655](https://github.com/astral-sh/ruff/pull/22655)) - \[`flake8-async`\] Tweak explanation to focus on latency/efficiency tradeoff (`ASYNC110`) ([#22715](https://github.com/astral-sh/ruff/pull/22715)) - \[`pandas-vet`\] Make example error out-of-the-box (`PD002`) ([#22561](https://github.com/astral-sh/ruff/pull/22561)) - \[`refurb`\] Make the example work out of box (`FURB101`) ([#22770](https://github.com/astral-sh/ruff/pull/22770)) - \[`refurb`\] Make the example work out of box (`FURB103`) ([#22769](https://github.com/astral-sh/ruff/pull/22769)) ### Contributors - [@alejsdev](https://github.com/alejsdev) - [@ntBre](https://github.com/ntBre) - [@caiquejjx](https://github.com/caiquejjx) - [@chirizxc](https://github.com/chirizxc) - [@denyszhak](https://github.com/denyszhak) - [@sjyangkevin](https://github.com/sjyangkevin) - [@MeGaGiGaGon](https://github.com/MeGaGiGaGon) - [@leandrobbraga](https://github.com/leandrobbraga) - [@MichaReiser](https://github.com/MichaReiser) - [@carljm](https://github.com/carljm) - [@amyreese](https://github.com/amyreese) - [@zsol](https://github.com/zsol) - [@harupy](https://github.com/harupy) ## Install ruff 0.14.14 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-installer.ps1 | iex" ``` ## Download ruff 0.14.14 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.14.14/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ### [`0.15.0`](https://github.com/astral-sh/ruff/releases/tag/0.15.0): 0.15.0 **Breaking change detected.** [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.0) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-02-03. Check out the [blog post](https://astral.sh/blog/ruff-v0.15.0) for a migration guide and overview of the changes! ### Breaking changes - Ruff now formats your code according to the 2026 style guide. See the formatter section below or in the blog post for a detailed list of changes. - The linter now supports block suppression comments. For example, to suppress `N803` for all parameters in this function: ```python # ruff: disable[N803] def foo( legacyArg1, legacyArg2, legacyArg3, legacyArg4, ): ... # ruff: enable[N803] ``` See the [documentation](https://docs.astral.sh/ruff/linter/#block-level) for more details. - The `ruff:alpine` Docker image is now based on Alpine 3.23 (up from 3.21). - The `ruff:debian` and `ruff:debian-slim` Docker images are now based on Debian 13 "Trixie" instead of Debian 12 "Bookworm." - Binaries for the `ppc64` (64-bit big-endian PowerPC) architecture are no longer included in our releases. It should still be possible to build Ruff manually for this platform, if needed. - Ruff now resolves all `extend`ed configuration files before falling back on a default Python version. ### Stabilization The following rules have been stabilized and are no longer in preview: - [`blocking-http-call-httpx-in-async-function`](https://docs.astral.sh/ruff/rules/blocking-http-call-httpx-in-async-function) (`ASYNC212`) - [`blocking-path-method-in-async-function`](https://docs.astral.sh/ruff/rules/blocking-path-method-in-async-function) (`ASYNC240`) - [`blocking-input-in-async-function`](https://docs.astral.sh/ruff/rules/blocking-input-in-async-function) (`ASYNC250`) - [`map-without-explicit-strict`](https://docs.astral.sh/ruff/rules/map-without-explicit-strict) (`B912`) - [`if-exp-instead-of-or-operator`](https://docs.astral.sh/ruff/rules/if-exp-instead-of-or-operator) (`FURB110`) - [`single-item-membership-test`](https://docs.astral.sh/ruff/rules/single-item-membership-test) (`FURB171`) - [`missing-maxsplit-arg`](https://docs.astral.sh/ruff/rules/missing-maxsplit-arg) (`PLC0207`) - [`unnecessary-lambda`](https://docs.astral.sh/ruff/rules/unnecessary-lambda) (`PLW0108`) - [`unnecessary-empty-iterable-within-deque-call`](https://docs.astral.sh/ruff/rules/unnecessary-empty-iterable-within-deque-call) (`RUF037`) - [`in-empty-collection`](https://docs.astral.sh/ruff/rules/in-empty-collection) (`RUF060`) - [`legacy-form-pytest-raises`](https://docs.astral.sh/ruff/rules/legacy-form-pytest-raises) (`RUF061`) - [`non-octal-permissions`](https://docs.astral.sh/ruff/rules/non-octal-permissions) (`RUF064`) - [`invalid-rule-code`](https://docs.astral.sh/ruff/rules/invalid-rule-code) (`RUF102`) - [`invalid-suppression-comment`](https://docs.astral.sh/ruff/rules/invalid-suppression-comment) (`RUF103`) - [`unmatched-suppression-comment`](https://docs.astral.sh/ruff/rules/unmatched-suppression-comment) (`RUF104`) - [`replace-str-enum`](https://docs.astral.sh/ruff/rules/replace-str-enum) (`UP042`) The following behaviors have been stabilized: - The `--output-format` flag is now respected when running Ruff in `--watch` mode, and the `full` output format is now used by default, matching the regular CLI output. - [`builtin-attribute-shadowing`](https://docs.astral.sh/ruff/rules/builtin-attribute-shadowing/) (`A003`) now detects the use of shadowed built-in names in additional contexts like decorators, default arguments, and other attribute definitions. - [`duplicate-union-member`](https://docs.astral.sh/ruff/rules/duplicate-union-member/) (`PYI016`) now considers `typing.Optional` when searching for duplicate union members. - [`split-static-string`](https://docs.astral.sh/ruff/rules/split-static-string/) (`SIM905`) now offers an autofix when the `maxsplit` argument is provided, even without a `sep` argument. - [`dict-get-with-none-default`](https://docs.astral.sh/ruff/rules/dict-get-with-none-default/) (`SIM910`) now applies to more types of key expressions. - [`super-call-with-parameters`](https://docs.astral.sh/ruff/rules/super-call-with-parameters/) (`UP008`) now has a safe fix when it will not delete comments. - [`unnecessary-default-type-args`](https://docs.astral.sh/ruff/rules/unnecessary-default-type-args/) (`UP043`) now applies to stub (`.pyi`) files on Python versions before 3.13. ### Formatter This release introduces the new 2026 style guide, with the following changes: - Lambda parameters are now kept on the same line and lambda bodies will be parenthesized to let them break across multiple lines ([#21385](https://github.com/astral-sh/ruff/pull/21385)) - Parentheses around tuples of exceptions in `except` clauses will now be removed on Python 3.14 and later ([#20768](https://github.com/astral-sh/ruff/pull/20768)) - A single empty line is now permitted at the beginning of function bodies ([#21110](https://github.com/astral-sh/ruff/pull/21110)) - Parentheses are avoided for long `as` captures in `match` statements ([#21176](https://github.com/astral-sh/ruff/pull/21176)) - Extra spaces between escaped quotes and ending triple quotes can now be omitted ([#17216](https://github.com/astral-sh/ruff/pull/17216)) - Blank lines are now enforced before classes with decorators in stub files ([#18888](https://github.com/astral-sh/ruff/pull/18888)) ### Preview features - Apply formatting to Markdown code blocks ([#22470](https://github.com/astral-sh/ruff/pull/22470), [#22990](https://github.com/astral-sh/ruff/pull/22990), [#22996](https://github.com/astral-sh/ruff/pull/22996)) See the [documentation](https://docs.astral.sh/ruff/formatter/#markdown-code-formatting) for more details. ### Bug fixes - Fix suppression indentation matching ([#22903](https://github.com/astral-sh/ruff/pull/22903)) ### Rule changes - Customize where the `fix_title` sub-diagnostic appears ([#23044](https://github.com/astral-sh/ruff/pull/23044)) - \[`FastAPI`\] Add sub-diagnostic explaining why a fix was unavailable (`FAST002`) ([#22565](https://github.com/astral-sh/ruff/pull/22565)) - \[`flake8-annotations`\] Don't suggest `NoReturn` for functions raising `NotImplementedError` (`ANN201`, `ANN202`, `ANN205`, `ANN206`) ([#21311](https://github.com/astral-sh/ruff/pull/21311)) - \[`pyupgrade`\] Make fix unsafe if it deletes comments (`UP017`) ([#22873](https://github.com/astral-sh/ruff/pull/22873)) - \[`pyupgrade`\] Make fix unsafe if it deletes comments (`UP020`) ([#22872](https://github.com/astral-sh/ruff/pull/22872)) - \[`pyupgrade`\] Make fix unsafe if it deletes comments (`UP033`) ([#22871](https://github.com/astral-sh/ruff/pull/22871)) - \[`refurb`\] Do not add `abc.ABC` if already present (`FURB180`) ([#22234](https://github.com/astral-sh/ruff/pull/22234)) - \[`refurb`\] Make fix unsafe if it deletes comments (`FURB110`) ([#22768](https://github.com/astral-sh/ruff/pull/22768)) - \[`ruff`\] Add sub-diagnostics with permissions (`RUF064`) ([#22972](https://github.com/astral-sh/ruff/pull/22972)) ### Server - Identify notebooks by LSP `didOpen` instead of `.ipynb` file extension ([#22810](https://github.com/astral-sh/ruff/pull/22810)) ### CLI - Add `--color` CLI option to force colored output ([#22806](https://github.com/astral-sh/ruff/pull/22806)) ### Documentation - Document `-` stdin convention in CLI help text ([#22817](https://github.com/astral-sh/ruff/pull/22817)) - \[`refurb`\] Change example to `re.search` with `^` anchor (`FURB167`) ([#22984](https://github.com/astral-sh/ruff/pull/22984)) - Fix link to Sphinx code block directives ([#23041](https://github.com/astral-sh/ruff/pull/23041)) - \[`pydocstyle`\] Clarify which quote styles are allowed (`D300`) ([#22825](https://github.com/astral-sh/ruff/pull/22825)) - \[`flake8-bugbear`\] Improve docs for `no-explicit-stacklevel` (`B028`) ([#22538](https://github.com/astral-sh/ruff/pull/22538)) ### Other changes - Update MSRV to 1.91 ([#22874](https://github.com/astral-sh/ruff/pull/22874)) ### Contributors - [@danparizher](https://github.com/danparizher) - [@chirizxc](https://github.com/chirizxc) - [@amyreese](https://github.com/amyreese) - [@Jkhall81](https://github.com/Jkhall81) - [@cwkang1998](https://github.com/cwkang1998) - [@manzt](https://github.com/manzt) - [@11happy](https://github.com/11happy) - [@hugovk](https://github.com/hugovk) - [@caiquejjx](https://github.com/caiquejjx) - [@ntBre](https://github.com/ntBre) - [@akawd](https://github.com/akawd) - [@konstin](https://github.com/konstin) ## Install ruff 0.15.0 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.0 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.0/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ### [`0.15.1`](https://github.com/astral-sh/ruff/releases/tag/0.15.1): 0.15.1 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.1) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-02-12. ### Preview features - \[`airflow`\] Add ruff rules to catch deprecated Airflow imports for Airflow 3.1 (`AIR321`) ([#22376](https://github.com/astral-sh/ruff/pull/22376)) - \[`airflow`\] Third positional parameter not named `ti_key` should be flagged for `BaseOperatorLink.get_link` (`AIR303`) ([#22828](https://github.com/astral-sh/ruff/pull/22828)) - \[`flake8-gettext`\] Fix false negatives for plural argument of `ngettext` (`INT001`, `INT002`, `INT003`) ([#21078](https://github.com/astral-sh/ruff/pull/21078)) - \[`pyflakes`\] Fix infinite loop in preview fix for `unused-import` (`F401`) ([#23038](https://github.com/astral-sh/ruff/pull/23038)) - \[`pygrep-hooks`\] Detect non-existent mock methods in standalone expressions (`PGH005`) ([#22830](https://github.com/astral-sh/ruff/pull/22830)) - \[`pylint`\] Allow dunder submodules and improve diagnostic range (`PLC2701`) ([#22804](https://github.com/astral-sh/ruff/pull/22804)) - \[`pyupgrade`\] Improve diagnostic range for tuples (`UP024`) ([#23013](https://github.com/astral-sh/ruff/pull/23013)) - \[`refurb`\] Check subscripts in tuple do not use lambda parameters in `reimplemented-operator` (`FURB118`) ([#23079](https://github.com/astral-sh/ruff/pull/23079)) - \[`ruff`\] Detect mutable defaults in `field` calls (`RUF008`) ([#23046](https://github.com/astral-sh/ruff/pull/23046)) - \[`ruff`\] Ignore std `cmath.inf` (`RUF069`) ([#23120](https://github.com/astral-sh/ruff/pull/23120)) - \[`ruff`\] New rule `float-equality-comparison` (`RUF069`) ([#20585](https://github.com/astral-sh/ruff/pull/20585)) - Don't format unlabeled Markdown code blocks ([#23106](https://github.com/astral-sh/ruff/pull/23106)) - Markdown formatting support in LSP ([#23063](https://github.com/astral-sh/ruff/pull/23063)) - Support Quarto Markdown language markers ([#22947](https://github.com/astral-sh/ruff/pull/22947)) - Support formatting `pycon` Markdown code blocks ([#23112](https://github.com/astral-sh/ruff/pull/23112)) - Use extension mapping to select Markdown code block language ([#22934](https://github.com/astral-sh/ruff/pull/22934)) ### Bug fixes - Avoid false positive for undefined variables in `FAST001` ([#23224](https://github.com/astral-sh/ruff/pull/23224)) - Avoid introducing syntax errors for `FAST003` autofix ([#23227](https://github.com/astral-sh/ruff/pull/23227)) - Avoid suggesting `InitVar` for `__post_init__` that references PEP 695 type parameters ([#23226](https://github.com/astral-sh/ruff/pull/23226)) - Deduplicate type variables in generic functions ([#23225](https://github.com/astral-sh/ruff/pull/23225)) - Fix exception handler parenthesis removal for Python 3.14+ ([#23126](https://github.com/astral-sh/ruff/pull/23126)) - Fix f-string middle panic when parsing t-strings ([#23232](https://github.com/astral-sh/ruff/pull/23232)) - Wrap `RUF020` target for multiline fixes ([#23210](https://github.com/astral-sh/ruff/pull/23210)) - Wrap `UP007` target for multiline fixes ([#23208](https://github.com/astral-sh/ruff/pull/23208)) - Fix missing diagnostics for last range suppression in file ([#23242](https://github.com/astral-sh/ruff/pull/23242)) - \[`pyupgrade`\] Fix syntax error on string with newline escape and comment (`UP037`) ([#22968](https://github.com/astral-sh/ruff/pull/22968)) ### Rule changes - Use `ruff` instead of `Ruff` as the program name in GitHub output format ([#23240](https://github.com/astral-sh/ruff/pull/23240)) - \[`PT006`\] Fix syntax error when unpacking nested tuples in `parametrize` fixes (#22441) ([#22464](https://github.com/astral-sh/ruff/pull/22464)) - \[`airflow`\] Catch deprecated attribute access from context key for Airflow 3.0 (`AIR301`) ([#22850](https://github.com/astral-sh/ruff/pull/22850)) - \[`airflow`\] Capture deprecated arguments and a decorator (`AIR301`) ([#23170](https://github.com/astral-sh/ruff/pull/23170)) - \[`flake8-boolean-trap`\] Add `multiprocessing.Value` to excluded functions for `FBT003` ([#23010](https://github.com/astral-sh/ruff/pull/23010)) - \[`flake8-bugbear`\] Add a secondary annotation showing the previous occurrence (`B033`) ([#22634](https://github.com/astral-sh/ruff/pull/22634)) - \[`flake8-type-checking`\] Add sub-diagnostic showing the runtime use of an annotation (`TC004`) ([#23091](https://github.com/astral-sh/ruff/pull/23091)) - \[`isort`\] Support configurable import section heading comments ([#23151](https://github.com/astral-sh/ruff/pull/23151)) - \[`ruff`\] Improve the diagnostic for `RUF012` ([#23202](https://github.com/astral-sh/ruff/pull/23202)) ### Formatter - Suppress diagnostic output for `format --check --silent` ([#17736](https://github.com/astral-sh/ruff/pull/17736)) ### Documentation - Add tabbed shell completion documentation ([#23169](https://github.com/astral-sh/ruff/pull/23169)) - Explain how to enable Markdown formatting for pre-commit hook ([#23077](https://github.com/astral-sh/ruff/pull/23077)) - Fixed import in `runtime-evaluated-decorators` example ([#23187](https://github.com/astral-sh/ruff/pull/23187)) - Update ruff server contributing guide ([#23060](https://github.com/astral-sh/ruff/pull/23060)) ### Other changes - Exclude WASM artifacts from GitHub releases ([#23221](https://github.com/astral-sh/ruff/pull/23221)) ### Contributors - [@mkniewallner](https://github.com/mkniewallner) - [@bxff](https://github.com/bxff) - [@dylwil3](https://github.com/dylwil3) - [@Avasam](https://github.com/Avasam) - [@amyreese](https://github.com/amyreese) - [@charliermarsh](https://github.com/charliermarsh) - [@Alex-ley-scrub](https://github.com/Alex-ley-scrub) - [@Kalmaegi](https://github.com/Kalmaegi) - [@danparizher](https://github.com/danparizher) - [@AiyionPrime](https://github.com/AiyionPrime) - [@eureka928](https://github.com/eureka928) - [@11happy](https://github.com/11happy) - [@Jkhall81](https://github.com/Jkhall81) - [@chirizxc](https://github.com/chirizxc) - [@leandrobbraga](https://github.com/leandrobbraga) - [@tvatter](https://github.com/tvatter) - [@anishgirianish](https://github.com/anishgirianish) - [@shaanmajid](https://github.com/shaanmajid) - [@ntBre](https://github.com/ntBre) - [@sjyangkevin](https://github.com/sjyangkevin) ## Install ruff 0.15.1 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.1 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.1/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ### [`0.15.2`](https://github.com/astral-sh/ruff/releases/tag/0.15.2): 0.15.2 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.2) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-02-19. ### Preview features - Expand the default rule set ([#23385](https://github.com/astral-sh/ruff/pull/23385)) In preview, Ruff now enables a significantly expanded default rule set of 412 rules, up from the stable default set of 59 rules. The new rules are mostly a superset of the stable defaults, with the exception of these rules, which are removed from the preview defaults: - [`multiple-imports-on-one-line`](https://docs.astral.sh/ruff/rules/multiple-imports-on-one-line) (`E401`) - [`module-import-not-at-top-of-file`](https://docs.astral.sh/ruff/rules/module-import-not-at-top-of-file) (`E402`) - [`module-import-not-at-top-of-file`](https://docs.astral.sh/ruff/rules/module-import-not-at-top-of-file) (`E701`) - [`multiple-statements-on-one-line-semicolon`](https://docs.astral.sh/ruff/rules/multiple-statements-on-one-line-semicolon) (`E702`) - [`useless-semicolon`](https://docs.astral.sh/ruff/rules/useless-semicolon) (`E703`) - [`none-comparison`](https://docs.astral.sh/ruff/rules/none-comparison) (`E711`) - [`true-false-comparison`](https://docs.astral.sh/ruff/rules/true-false-comparison) (`E712`) - [`not-in-test`](https://docs.astral.sh/ruff/rules/not-in-test) (`E713`) - [`not-is-test`](https://docs.astral.sh/ruff/rules/not-is-test) (`E714`) - [`type-comparison`](https://docs.astral.sh/ruff/rules/type-comparison) (`E721`) - [`lambda-assignment`](https://docs.astral.sh/ruff/rules/lambda-assignment) (`E731`) - [`ambiguous-variable-name`](https://docs.astral.sh/ruff/rules/ambiguous-variable-name) (`E741`) - [`ambiguous-class-name`](https://docs.astral.sh/ruff/rules/ambiguous-class-name) (`E742`) - [`ambiguous-function-name`](https://docs.astral.sh/ruff/rules/ambiguous-function-name) (`E743`) - [`undefined-local-with-import-star`](https://docs.astral.sh/ruff/rules/undefined-local-with-import-star) (`F403`) - [`undefined-local-with-import-star-usage`](https://docs.astral.sh/ruff/rules/undefined-local-with-import-star-usage) (`F405`) - [`undefined-local-with-nested-import-star-usage`](https://docs.astral.sh/ruff/rules/undefined-local-with-nested-import-star-usage) (`F406`) - [`forward-annotation-syntax-error`](https://docs.astral.sh/ruff/rules/forward-annotation-syntax-error) (`F722`) If you use preview and prefer the old defaults, you can restore them with configuration like: ```toml # ruff.toml [lint] select = ["E4", "E7", "E9", "F"] # pyproject.toml [tool.ruff.lint] select = ["E4", "E7", "E9", "F"] ``` If you do give them a try, feel free to share your feedback in the [GitHub discussion](https://github.com/astral-sh/ruff/discussions/23203)! - \[`flake8-pyi`\] Also check string annotations (`PYI041`) ([#19023](https://github.com/astral-sh/ruff/pull/19023)) ### Bug fixes - \[`flake8-async`\] Fix `in_async_context` logic ([#23426](https://github.com/astral-sh/ruff/pull/23426)) - \[`ruff`\] Fix for `RUF102` should delete entire comment ([#23380](https://github.com/astral-sh/ruff/pull/23380)) - \[`ruff`\] Suppress diagnostic for strings with backslashes in interpolations before Python 3.12 (`RUF027`) ([#21069](https://github.com/astral-sh/ruff/pull/21069)) - \[`flake8-bugbear`\] Fix `B023` false positive for immediately-invoked lambdas ([#23294](https://github.com/astral-sh/ruff/pull/23294)) - [parser] Fix false syntax error for match-like annotated assignments ([#23297](https://github.com/astral-sh/ruff/pull/23297)) - [parser] Fix indentation tracking after line continuations ([#23417](https://github.com/astral-sh/ruff/pull/23417)) ### Rule changes - \[`flake8-executable`\] Allow global flags in uv shebangs (`EXE003`) ([#22582](https://github.com/astral-sh/ruff/pull/22582)) - \[`pyupgrade`\] Fix handling of `typing.{io,re}` (`UP035`) ([#23131](https://github.com/astral-sh/ruff/pull/23131)) - \[`ruff`\] Detect `PLC0207` on chained `str.split()` calls ([#23275](https://github.com/astral-sh/ruff/pull/23275)) ### CLI - Remove invalid inline `noqa` warning ([#23270](https://github.com/astral-sh/ruff/pull/23270)) ### Configuration - Add extension mapping to configuration file options ([#23384](https://github.com/astral-sh/ruff/pull/23384)) ### Documentation - Add `Q004` to the list of conflicting rules ([#23340](https://github.com/astral-sh/ruff/pull/23340)) - \[`ruff`\] Expand `lint.external` docs and add sub-diagnostic (`RUF100`, `RUF102`) ([#23268](https://github.com/astral-sh/ruff/pull/23268)) ### Contributors - [@dylwil3](https://github.com/dylwil3) - [@Jkhall81](https://github.com/Jkhall81) - [@danparizher](https://github.com/danparizher) - [@dhruvmanila](https://github.com/dhruvmanila) - [@harupy](https://github.com/harupy) - [@ngnpope](https://github.com/ngnpope) - [@amyreese](https://github.com/amyreese) - [@kar-ganap](https://github.com/kar-ganap) - [@robsdedude](https://github.com/robsdedude) - [@shaanmajid](https://github.com/shaanmajid) - [@ntBre](https://github.com/ntBre) - [@toslunar](https://github.com/toslunar) ## Install ruff 0.15.2 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.2 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.2/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.15.3`](https://github.com/astral-sh/ruff/releases/tag/0.15.3): 0.15.3 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.3) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-02-26. ### Preview features - Drop explicit support for `.qmd` file extension ([#23572](https://github.com/astral-sh/ruff/pull/23572)) This can now be enabled instead by setting the [`extension`](https://docs.astral.sh/ruff/settings/#extension) option: ```toml # ruff.toml extension = { qmd = "markdown" } # pyproject.toml [tool.ruff] extension = { qmd = "markdown" } ``` - Include configured extensions in file discovery ([#23400](https://github.com/astral-sh/ruff/pull/23400)) - \[`flake8-bandit`\] Allow suspicious imports in `TYPE_CHECKING` blocks (`S401`-`S415`) ([#23441](https://github.com/astral-sh/ruff/pull/23441)) - \[`flake8-bugbear`\] Allow `B901` in pytest hook wrappers ([#21931](https://github.com/astral-sh/ruff/pull/21931)) - \[`flake8-import-conventions`\] Add missing conventions from upstream (`ICN001`, `ICN002`) ([#21373](https://github.com/astral-sh/ruff/pull/21373)) - \[`pydocstyle`\] Add rule to enforce docstring section ordering (`D420`) ([#23537](https://github.com/astral-sh/ruff/pull/23537)) - \[`pylint`\] Implement `swap-with-temporary-variable` (`PLR1712`) ([#22205](https://github.com/astral-sh/ruff/pull/22205)) - \[`ruff`\] Add `unnecessary-assign-before-yield` (`RUF070`) ([#23300](https://github.com/astral-sh/ruff/pull/23300)) - \[`ruff`\] Support file-level noqa in `RUF102` ([#23535](https://github.com/astral-sh/ruff/pull/23535)) - \[`ruff`\] Suppress diagnostic for invalid f-strings before Python 3.12 (`RUF027`) ([#23480](https://github.com/astral-sh/ruff/pull/23480)) - \[`flake8-bandit`\] Don't flag `BaseLoader`/`CBaseLoader` as unsafe (`S506`) ([#23510](https://github.com/astral-sh/ruff/pull/23510)) ### Bug fixes - Avoid infinite loop between `I002` and `PYI025` ([#23352](https://github.com/astral-sh/ruff/pull/23352)) - \[`pyflakes`\] Fix false positive for `@overload` from `lint.typing-modules` (`F811`) ([#23357](https://github.com/astral-sh/ruff/pull/23357)) - \[`pyupgrade`\] Fix false positive for `TypeVar` default before Python 3.12 (`UP046`) ([#23540](https://github.com/astral-sh/ruff/pull/23540)) - \[`pyupgrade`\] Fix handling of `\N` in raw strings (`UP032`) ([#22149](https://github.com/astral-sh/ruff/pull/22149)) ### Rule changes - Render sub-diagnostics in the GitHub output format ([#23455](https://github.com/astral-sh/ruff/pull/23455)) - \[`flake8-bugbear`\] Tag certain `B007` diagnostics as unnecessary ([#23453](https://github.com/astral-sh/ruff/pull/23453)) - \[`ruff`\] Ignore unknown rule codes in `RUF100` ([#23531](https://github.com/astral-sh/ruff/pull/23531)) These are now flagged by [`RUF102`](https://docs.astral.sh/ruff/rules/invalid-rule-code/) instead. ### Documentation - Fix missing settings links for several linters ([#23519](https://github.com/astral-sh/ruff/pull/23519)) - Update isort action comments heading ([#23515](https://github.com/astral-sh/ruff/pull/23515)) - \[`pydocstyle`\] Fix double comma in description of `D404` ([#23440](https://github.com/astral-sh/ruff/pull/23440)) ### Other changes - Update the Python module (notably `find_ruff_bin`) for parity with uv ([#23406](https://github.com/astral-sh/ruff/pull/23406)) ### Contributors - [@zanieb](https://github.com/zanieb) - [@o1x3](https://github.com/o1x3) - [@assadyousuf](https://github.com/assadyousuf) - [@kar-ganap](https://github.com/kar-ganap) - [@denyszhak](https://github.com/denyszhak) - [@amyreese](https://github.com/amyreese) - [@carljm](https://github.com/carljm) - [@anishgirianish](https://github.com/anishgirianish) - [@Bnyro](https://github.com/Bnyro) - [@danparizher](https://github.com/danparizher) - [@ntBre](https://github.com/ntBre) - [@gcomneno](https://github.com/gcomneno) - [@jaap3](https://github.com/jaap3) - [@stakeswky](https://github.com/stakeswky) ## Install ruff 0.15.3 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.3 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.3/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.15.4`](https://github.com/astral-sh/ruff/releases/tag/0.15.4): 0.15.4 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.4) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-02-26. This is a follow-up release to 0.15.3 that resolves a panic when the new rule `PLR1712` was enabled with any rule that analyzes definitions, such as many of the `ANN` or `D` rules. ### Bug fixes - Fix panic on access to definitions after analyzing definitions ([#23588](https://github.com/astral-sh/ruff/pull/23588)) - \[`pyflakes`\] Suppress false positive in `F821` for names used before `del` in stub files ([#23550](https://github.com/astral-sh/ruff/pull/23550)) ### Documentation - Clarify first-party import detection in Ruff ([#23591](https://github.com/astral-sh/ruff/pull/23591)) - Fix incorrect `import-heading` example ([#23568](https://github.com/astral-sh/ruff/pull/23568)) ### Contributors - [@stakeswky](https://github.com/stakeswky) - [@ntBre](https://github.com/ntBre) - [@thejcannon](https://github.com/thejcannon) - [@GeObts](https://github.com/GeObts) ## Install ruff 0.15.4 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.4 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.4/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.15.5`](https://github.com/astral-sh/ruff/releases/tag/0.15.5): 0.15.5 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.5) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-03-05. ### Preview features - Discover Markdown files by default in preview mode ([#23434](https://github.com/astral-sh/ruff/pull/23434)) - \[`perflint`\] Extend `PERF102` to comprehensions and generators ([#23473](https://github.com/astral-sh/ruff/pull/23473)) - \[`refurb`\] Fix `FURB101` and `FURB103` false positives when I/O variable is used later ([#23542](https://github.com/astral-sh/ruff/pull/23542)) - \[`ruff`\] Add fix for `none-not-at-end-of-union` (`RUF036`) ([#22829](https://github.com/astral-sh/ruff/pull/22829)) - \[`ruff`\] Fix false positive for `re.split` with empty string pattern (`RUF055`) ([#23634](https://github.com/astral-sh/ruff/pull/23634)) ### Bug fixes - \[`fastapi`\] Handle callable class dependencies with `__call__` method (`FAST003`) ([#23553](https://github.com/astral-sh/ruff/pull/23553)) - \[`pydocstyle`\] Fix numpy section ordering (`D420`) ([#23685](https://github.com/astral-sh/ruff/pull/23685)) - \[`pyflakes`\] Fix false positive for names shadowing re-exports (`F811`) ([#23356](https://github.com/astral-sh/ruff/pull/23356)) - \[`pyupgrade`\] Avoid inserting redundant `None` elements in `UP045` ([#23459](https://github.com/astral-sh/ruff/pull/23459)) ### Documentation - Document extension mapping for Markdown code formatting ([#23574](https://github.com/astral-sh/ruff/pull/23574)) - Update default Python version examples ([#23605](https://github.com/astral-sh/ruff/pull/23605)) ### Other changes - Publish releases to Astral mirror ([#23616](https://github.com/astral-sh/ruff/pull/23616)) ### Contributors - [@amyreese](https://github.com/amyreese) - [@stakeswky](https://github.com/stakeswky) - [@chirizxc](https://github.com/chirizxc) - [@anishgirianish](https://github.com/anishgirianish) - [@bxff](https://github.com/bxff) - [@zsol](https://github.com/zsol) - [@charliermarsh](https://github.com/charliermarsh) - [@ntBre](https://github.com/ntBre) - [@kar-ganap](https://github.com/kar-ganap) ## Install ruff 0.15.5 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.5 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://github.com/astral-sh/ruff/releases/download/0.15.5/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.15.6`](https://github.com/astral-sh/ruff/releases/tag/0.15.6): 0.15.6 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.6) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-03-12. ### Preview features - Add support for `lazy` import parsing ([#23755](https://github.com/astral-sh/ruff/pull/23755)) - Add support for star-unpacking of comprehensions (PEP 798) ([#23788](https://github.com/astral-sh/ruff/pull/23788)) - Reject semantic syntax errors for lazy imports ([#23757](https://github.com/astral-sh/ruff/pull/23757)) - Drop a few rules from the preview default set ([#23879](https://github.com/astral-sh/ruff/pull/23879)) - \[`airflow`\] Flag `Variable.get()` calls outside of task execution context (`AIR003`) ([#23584](https://github.com/astral-sh/ruff/pull/23584)) - \[`airflow`\] Flag runtime-varying values in DAG/task constructor arguments (`AIR304`) ([#23631](https://github.com/astral-sh/ruff/pull/23631)) - \[`flake8-bugbear`\] Implement `delattr-with-constant` (`B043`) ([#23737](https://github.com/astral-sh/ruff/pull/23737)) - \[`flake8-tidy-imports`\] Add `TID254` to enforce lazy imports ([#23777](https://github.com/astral-sh/ruff/pull/23777)) - \[`flake8-tidy-imports`\] Allow users to ban lazy imports with `TID254` ([#23847](https://github.com/astral-sh/ruff/pull/23847)) - \[`isort`\] Retain `lazy` keyword when sorting imports ([#23762](https://github.com/astral-sh/ruff/pull/23762)) - \[`pyupgrade`\] Add `from __future__ import annotations` automatically (`UP006`) ([#23260](https://github.com/astral-sh/ruff/pull/23260)) - \[`refurb`\] Support `newline` parameter in `FURB101` for Python 3.13+ ([#23754](https://github.com/astral-sh/ruff/pull/23754)) - \[`ruff`\] Add `os-path-commonprefix` (`RUF071`) ([#23814](https://github.com/astral-sh/ruff/pull/23814)) - \[`ruff`\] Add unsafe fix for os-path-commonprefix (`RUF071`) ([#23852](https://github.com/astral-sh/ruff/pull/23852)) - \[`ruff`\] Limit `RUF036` to typing contexts; make it unsafe for non-typing-only ([#23765](https://github.com/astral-sh/ruff/pull/23765)) - \[`ruff`\] Use starred unpacking for `RUF017` in Python 3.15+ ([#23789](https://github.com/astral-sh/ruff/pull/23789)) ### Bug fixes - Fix `--add-noqa` creating unwanted leading whitespace ([#23773](https://github.com/astral-sh/ruff/pull/23773)) - Fix `--add-noqa` breaking shebangs ([#23577](https://github.com/astral-sh/ruff/pull/23577)) - [formatter] Fix lambda body formatting for multiline calls and subscripts ([#23866](https://github.com/astral-sh/ruff/pull/23866)) - [formatter] Preserve required annotation parentheses in annotated assignments ([#23865](https://github.com/astral-sh/ruff/pull/23865)) - [formatter] Preserve type-expression parentheses in the formatter ([#23867](https://github.com/astral-sh/ruff/pull/23867)) - \[`flake8-annotations`\] Fix stack overflow in `ANN401` on quoted annotations with escape sequences ([#23912](https://github.com/astral-sh/ruff/pull/23912)) - \[`pep8-naming`\] Check naming conventions in `match` pattern bindings (`N806`, `N815`, `N816`) ([#23899](https://github.com/astral-sh/ruff/pull/23899)) - \[`perflint`\] Fix comment duplication in fixes (`PERF401`, `PERF403`) ([#23729](https://github.com/astral-sh/ruff/pull/23729)) - \[`pyupgrade`\] Properly trigger `super` change in nested class (`UP008`) ([#22677](https://github.com/astral-sh/ruff/pull/22677)) - \[`ruff`\] Avoid syntax errors in `RUF036` fixes ([#23764](https://github.com/astral-sh/ruff/pull/23764)) ### Rule changes - \[`flake8-bandit`\] Flag `S501` with `requests.request` ([#23873](https://github.com/astral-sh/ruff/pull/23873)) - \[`flake8-executable`\] Fix WSL detection in non-Docker containers ([#22879](https://github.com/astral-sh/ruff/pull/22879)) - \[`flake8-print`\] Ignore `pprint` calls with `stream=` ([#23787](https://github.com/astral-sh/ruff/pull/23787)) ### Documentation - Update docs for Markdown code block formatting ([#23871](https://github.com/astral-sh/ruff/pull/23871)) - \[`flake8-bugbear`\] Fix misleading description for `B904` ([#23731](https://github.com/astral-sh/ruff/pull/23731)) ### Contributors - [@zsol](https://github.com/zsol) - [@carljm](https://github.com/carljm) - [@ntBre](https://github.com/ntBre) - [@Bortlesboat](https://github.com/Bortlesboat) - [@sososonia-cyber](https://github.com/sososonia-cyber) - [@chirizxc](https://github.com/chirizxc) - [@leandrobbraga](https://github.com/leandrobbraga) - [@11happy](https://github.com/11happy) - [@Acelogic](https://github.com/Acelogic) - [@anishgirianish](https://github.com/anishgirianish) - [@amyreese](https://github.com/amyreese) - [@xvchris](https://github.com/xvchris) - [@charliermarsh](https://github.com/charliermarsh) - [@getehen](https://github.com/getehen) - [@Dev-iL](https://github.com/Dev-iL) ## Install ruff 0.15.6 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.6 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.6/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.15.7`](https://github.com/astral-sh/ruff/releases/tag/0.15.7): 0.15.7 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.7) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-03-19. ### Preview features - Display output severity in preview ([#23845](https://github.com/astral-sh/ruff/pull/23845)) - Don't show `noqa` hover for non-Python documents ([#24040](https://github.com/astral-sh/ruff/pull/24040)) ### Rule changes - \[`pycodestyle`\] Recognize `pyrefly:` as a pragma comment (`E501`) ([#24019](https://github.com/astral-sh/ruff/pull/24019)) ### Server - Don't return code actions for non-Python documents ([#23905](https://github.com/astral-sh/ruff/pull/23905)) ### Documentation - Add company AI policy to contributing guide ([#24021](https://github.com/astral-sh/ruff/pull/24021)) - Document editor features for Markdown code formatting ([#23924](https://github.com/astral-sh/ruff/pull/23924)) - \[`pylint`\] Improve phrasing (`PLC0208`) ([#24033](https://github.com/astral-sh/ruff/pull/24033)) ### Other changes - Use PEP 639 license information ([#19661](https://github.com/astral-sh/ruff/pull/19661)) ### Contributors - [@tmimmanuel](https://github.com/tmimmanuel) - [@DimitriPapadopoulos](https://github.com/DimitriPapadopoulos) - [@amyreese](https://github.com/amyreese) - [@statxc](https://github.com/statxc) - [@dylwil3](https://github.com/dylwil3) - [@hunterhogan](https://github.com/hunterhogan) - [@renovate](https://github.com/renovate) ## Install ruff 0.15.7 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.7 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.7/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.15.8`](https://github.com/astral-sh/ruff/releases/tag/0.15.8): 0.15.8 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.8) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-03-26. ### Preview features - \[`ruff`\] New rule `unnecessary-if` (`RUF050`) ([#24114](https://github.com/astral-sh/ruff/pull/24114)) - \[`ruff`\] New rule `useless-finally` (`RUF072`) ([#24165](https://github.com/astral-sh/ruff/pull/24165)) - \[`ruff`\] New rule `f-string-percent-format` (`RUF073`): warn when using `%` operator on an f-string ([#24162](https://github.com/astral-sh/ruff/pull/24162)) - \[`pyflakes`\] Recognize `frozendict` as a builtin for Python 3.15+ ([#24100](https://github.com/astral-sh/ruff/pull/24100)) ### Bug fixes - \[`flake8-async`\] Use fully-qualified `anyio.lowlevel` import in autofix (`ASYNC115`) ([#24166](https://github.com/astral-sh/ruff/pull/24166)) - \[`flake8-bandit`\] Check tuple arguments for partial paths in `S607` ([#24080](https://github.com/astral-sh/ruff/pull/24080)) - \[`pyflakes`\] Skip `undefined-name` (`F821`) for conditionally deleted variables ([#24088](https://github.com/astral-sh/ruff/pull/24088)) - `E501`/`W505`/formatter: Exclude nested pragma comments from line width calculation ([#24071](https://github.com/astral-sh/ruff/pull/24071)) - Fix `%foo?` parsing in IPython assignment expressions ([#24152](https://github.com/astral-sh/ruff/pull/24152)) - `analyze graph`: resolve string imports that reference attributes, not just modules ([#24058](https://github.com/astral-sh/ruff/pull/24058)) ### Rule changes - \[`eradicate`\] ignore `ty: ignore` comments in `ERA001` ([#24192](https://github.com/astral-sh/ruff/pull/24192)) - \[`flake8-bandit`\] Treat `sys.executable` as trusted input in `S603` ([#24106](https://github.com/astral-sh/ruff/pull/24106)) - \[`flake8-self`\] Recognize `Self` annotation and `self` assignment in `SLF001` ([#24144](https://github.com/astral-sh/ruff/pull/24144)) - \[`pyflakes`\] `F507`: Fix false negative for non-tuple RHS in `%`-formatting ([#24142](https://github.com/astral-sh/ruff/pull/24142)) - \[`refurb`\] Parenthesize generator arguments in `FURB142` fixer ([#24200](https://github.com/astral-sh/ruff/pull/24200)) ### Performance - Speed up diagnostic rendering ([#24146](https://github.com/astral-sh/ruff/pull/24146)) ### Server - Warn when Markdown files are skipped due to preview being disabled ([#24150](https://github.com/astral-sh/ruff/pull/24150)) ### Documentation - Clarify `extend-ignore` and `extend-select` settings documentation ([#24064](https://github.com/astral-sh/ruff/pull/24064)) - Mention AI policy in PR template ([#24198](https://github.com/astral-sh/ruff/pull/24198)) ### Other changes - Use trusted publishing for NPM packages ([#24171](https://github.com/astral-sh/ruff/pull/24171)) ### Contributors - [@bitloi](https://github.com/bitloi) - [@Sim-hu](https://github.com/Sim-hu) - [@mvanhorn](https://github.com/mvanhorn) - [@chinar-amrutkar](https://github.com/chinar-amrutkar) - [@markjm](https://github.com/markjm) - [@RenzoMXD](https://github.com/RenzoMXD) - [@vivekkhimani](https://github.com/vivekkhimani) - [@seroperson](https://github.com/seroperson) - [@moktamd](https://github.com/moktamd) - [@charliermarsh](https://github.com/charliermarsh) - [@ntBre](https://github.com/ntBre) - [@zanieb](https://github.com/zanieb) - [@dylwil3](https://github.com/dylwil3) - [@MichaReiser](https://github.com/MichaReiser) ## Install ruff 0.15.8 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.8 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.8/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.15.9`](https://github.com/astral-sh/ruff/releases/tag/0.15.9): 0.15.9 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.9) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-04-02. ### Preview features - \[`pyflakes`\] Flag annotated variable redeclarations as `F811` in preview mode ([#24244](https://github.com/astral-sh/ruff/pull/24244)) - \[`ruff`\] Allow dunder-named assignments in non-strict mode for `RUF067` ([#24089](https://github.com/astral-sh/ruff/pull/24089)) ### Bug fixes - \[`flake8-errmsg`\] Avoid shadowing existing `msg` in fix for `EM101` ([#24363](https://github.com/astral-sh/ruff/pull/24363)) - \[`flake8-simplify`\] Ignore pre-initialization references in `SIM113` ([#24235](https://github.com/astral-sh/ruff/pull/24235)) - \[`pycodestyle`\] Fix `W391` fixes for consecutive empty notebook cells ([#24236](https://github.com/astral-sh/ruff/pull/24236)) - \[`pyupgrade`\] Fix `UP008` nested class matching ([#24273](https://github.com/astral-sh/ruff/pull/24273)) - \[`pyupgrade`\] Ignore strings with string-only escapes (`UP012`) ([#16058](https://github.com/astral-sh/ruff/pull/16058)) - \[`ruff`\] `RUF072`: skip formfeeds on dedent ([#24308](https://github.com/astral-sh/ruff/pull/24308)) - \[`ruff`\] Avoid re-using symbol in `RUF024` fix ([#24316](https://github.com/astral-sh/ruff/pull/24316)) - \[`ruff`\] Parenthesize expression in `RUF050` fix ([#24234](https://github.com/astral-sh/ruff/pull/24234)) - Disallow starred expressions as values of starred expressions ([#24280](https://github.com/astral-sh/ruff/pull/24280)) ### Rule changes - \[`flake8-simplify`\] Suppress `SIM105` for `except*` before Python 3.12 ([#23869](https://github.com/astral-sh/ruff/pull/23869)) - \[`pyflakes`\] Extend `F507` to flag `%`-format strings with zero placeholders ([#24215](https://github.com/astral-sh/ruff/pull/24215)) - \[`pyupgrade`\] `UP018` should detect more unnecessarily wrapped literals (UP018) ([#24093](https://github.com/astral-sh/ruff/pull/24093)) - \[`pyupgrade`\] Fix `UP008` callable scope handling to support lambdas ([#24274](https://github.com/astral-sh/ruff/pull/24274)) - \[`ruff`\] `RUF010`: Mark fix as unsafe when it deletes a comment ([#24270](https://github.com/astral-sh/ruff/pull/24270)) ### Formatter - Add `nested-string-quote-style` formatting option ([#24312](https://github.com/astral-sh/ruff/pull/24312)) ### Documentation - \[`flake8-bugbear`\] Clarify RUF071 fix safety for non-path string comparisons ([#24149](https://github.com/astral-sh/ruff/pull/24149)) - \[`flake8-type-checking`\] Clarify import cycle wording for `TC001`/`TC002`/`TC003` ([#24322](https://github.com/astral-sh/ruff/pull/24322)) ### Other changes - Avoid rendering fix lines with trailing whitespace after `|` ([#24343](https://github.com/astral-sh/ruff/pull/24343)) ### Contributors - [@charliermarsh](https://github.com/charliermarsh) - [@MichaReiser](https://github.com/MichaReiser) - [@tranhoangtu-it](https://github.com/tranhoangtu-it) - [@dylwil3](https://github.com/dylwil3) - [@zsol](https://github.com/zsol) - [@renovate](https://github.com/renovate) - [@bitloi](https://github.com/bitloi) - [@danparizher](https://github.com/danparizher) - [@chinar-amrutkar](https://github.com/chinar-amrutkar) - [@second-ed](https://github.com/second-ed) - [@getehen](https://github.com/getehen) - [@Redovo1](https://github.com/Redovo1) - [@matthewlloyd](https://github.com/matthewlloyd) - [@zanieb](https://github.com/zanieb) - [@InSyncWithFoo](https://github.com/InSyncWithFoo) - [@RenzoMXD](https://github.com/RenzoMXD) ## Install ruff 0.15.9 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.9 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.9/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.15.10`](https://github.com/astral-sh/ruff/releases/tag/0.15.10): 0.15.10 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.10) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-04-09. ### Preview features - \[`flake8-logging`\] Allow closures in except handlers (`LOG004`) ([#24464](https://github.com/astral-sh/ruff/pull/24464)) - \[`flake8-self`\] Make `SLF` diagnostics robust to non-self-named variables ([#24281](https://github.com/astral-sh/ruff/pull/24281)) - \[`flake8-simplify`\] Make the fix for `collapsible-if` safe in `preview` (`SIM102`) ([#24371](https://github.com/astral-sh/ruff/pull/24371)) ### Bug fixes - Avoid emitting multi-line f-string elements before Python 3.12 ([#24377](https://github.com/astral-sh/ruff/pull/24377)) - Avoid syntax error from `E502` fixes in f-strings and t-strings ([#24410](https://github.com/astral-sh/ruff/pull/24410)) - Strip form feeds from indent passed to `dedent_to` ([#24381](https://github.com/astral-sh/ruff/pull/24381)) - \[`pyupgrade`\] Fix panic caused by handling of octals (`UP012`) ([#24390](https://github.com/astral-sh/ruff/pull/24390)) - Reject multi-line f-string elements before Python 3.12 ([#24355](https://github.com/astral-sh/ruff/pull/24355)) ### Rule changes - \[`ruff`\] Treat f-string interpolation as potential side effect (`RUF019`) ([#24426](https://github.com/astral-sh/ruff/pull/24426)) ### Server - Add support for custom file extensions ([#24463](https://github.com/astral-sh/ruff/pull/24463)) ### Documentation - Document adding fixes in CONTRIBUTING.md ([#24393](https://github.com/astral-sh/ruff/pull/24393)) - Fix JSON typo in settings example ([#24517](https://github.com/astral-sh/ruff/pull/24517)) ### Contributors - [@charliermarsh](https://github.com/charliermarsh) - [@dylwil3](https://github.com/dylwil3) - [@silverstein](https://github.com/silverstein) - [@anishgirianish](https://github.com/anishgirianish) - [@shizukushq](https://github.com/shizukushq) - [@zanieb](https://github.com/zanieb) - [@AlexWaygood](https://github.com/AlexWaygood) ## Install ruff 0.15.10 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.10 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.10/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.15.11`](https://github.com/astral-sh/ruff/releases/tag/0.15.11): 0.15.11 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.11) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-04-16. ### Preview features - \[`ruff`\] Ignore `RUF029` when function is decorated with `asynccontextmanager` ([#24642](https://github.com/astral-sh/ruff/pull/24642)) - \[`airflow`\] Implement `airflow-xcom-pull-in-template-string` (`AIR201`) ([#23583](https://github.com/astral-sh/ruff/pull/23583)) - \[`flake8-bandit`\] Fix `S103` false positives and negatives in mask analysis ([#24424](https://github.com/astral-sh/ruff/pull/24424)) ### Bug fixes - \[`flake8-async`\] Omit overridden methods for `ASYNC109` ([#24648](https://github.com/astral-sh/ruff/pull/24648)) ### Documentation - \[`flake8-async`\] Add override mention to `ASYNC109` docs ([#24666](https://github.com/astral-sh/ruff/pull/24666)) - Update Neovim config examples to use `vim.lsp.config` ([#24577](https://github.com/astral-sh/ruff/pull/24577)) ### Contributors - [@augustelalande](https://github.com/augustelalande) - [@anishgirianish](https://github.com/anishgirianish) - [@benberryallwood](https://github.com/benberryallwood) - [@charliermarsh](https://github.com/charliermarsh) - [@Dev-iL](https://github.com/Dev-iL) ## Install ruff 0.15.11 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.11 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.11/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.15.12`](https://github.com/astral-sh/ruff/releases/tag/0.15.12): 0.15.12 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.12) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-04-24. ### Preview features - Implement `#ruff:file-ignore` file-level suppressions ([#23599](https://github.com/astral-sh/ruff/pull/23599)) - Implement `#ruff:ignore` logical-line suppressions ([#23404](https://github.com/astral-sh/ruff/pull/23404)) - Revert preview changes to displayed diagnostic severity in LSP ([#24789](https://github.com/astral-sh/ruff/pull/24789)) - \[`airflow`\] Implement `task-branch-as-short-circuit` (`AIR004`) ([#23579](https://github.com/astral-sh/ruff/pull/23579)) - \[`flake8-bugbear`\] Fix `break`/`continue` handling in `loop-iterator-mutation` (`B909`) ([#24440](https://github.com/astral-sh/ruff/pull/24440)) - \[`pylint`\] Fix `PLC2701` for type parameter scopes ([#24576](https://github.com/astral-sh/ruff/pull/24576)) ### Rule changes - \[`pandas-vet`\] Suggest `.array` as well in `PD011` ([#24805](https://github.com/astral-sh/ruff/pull/24805)) ### CLI - Respect default Unix permissions for cache files ([#24794](https://github.com/astral-sh/ruff/pull/24794)) ### Documentation - \[`pylint`\] Fix `PLR0124` description not to claim self-comparison always returns the same value ([#24749](https://github.com/astral-sh/ruff/pull/24749)) - \[`pyupgrade`\] Expand docs on reusable `TypeVar`s and scoping (`UP046`) ([#24153](https://github.com/astral-sh/ruff/pull/24153)) - Improve rules table accessibility ([#24711](https://github.com/astral-sh/ruff/pull/24711)) ### Contributors - [@dylwil3](https://github.com/dylwil3) - [@AlexWaygood](https://github.com/AlexWaygood) - [@woodruffw](https://github.com/woodruffw) - [@avasis-ai](https://github.com/avasis-ai) - [@Dev-iL](https://github.com/Dev-iL) - [@denyszhak](https://github.com/denyszhak) - [@ShipItAndPray](https://github.com/ShipItAndPray) - [@anishgirianish](https://github.com/anishgirianish) - [@augustelalande](https://github.com/augustelalande) - [@amyreese](https://github.com/amyreese) - [@majiayu000](https://github.com/majiayu000) ## Install ruff 0.15.12 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.12 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.12/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.15.13`](https://github.com/astral-sh/ruff/releases/tag/0.15.13): 0.15.13 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.13) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-05-14. ### Preview features - Add a rule to flag lazy imports that are eagerly evaluated ([#25016](https://github.com/astral-sh/ruff/pull/25016)) - \[`pylint`\] Standardize diagnostic message (`PLR0914`, `PLR0917`) ([#24996](https://github.com/astral-sh/ruff/pull/24996)) ### Bug fixes - Fix `F811` false positive for class methods ([#24933](https://github.com/astral-sh/ruff/pull/24933)) - Fix setting selection for multi-folder workspace ([#24819](https://github.com/astral-sh/ruff/pull/24819)) - \[`eradicate`\] Fix false positive for lines with leading whitespace (`ERA001`) ([#25122](https://github.com/astral-sh/ruff/pull/25122)) - \[`flake8-pyi`\] Fix false positive for f-string debug specifier (`PYI016`) ([#24098](https://github.com/astral-sh/ruff/pull/24098)) ### Rule changes - Always include panic payload in panic diagnostic message ([#24873](https://github.com/astral-sh/ruff/pull/24873)) - Restrict `PYI034` for in-place operations to enclosing class ([#24511](https://github.com/astral-sh/ruff/pull/24511)) - Improve error message for parameters that are declared `global` ([#24902](https://github.com/astral-sh/ruff/pull/24902)) - Update known stdlib ([#25103](https://github.com/astral-sh/ruff/pull/25103)) ### Performance - \[`isort`\] Avoid constructing `glob::Pattern`s for literal known modules ([#25123](https://github.com/astral-sh/ruff/pull/25123)) ### CLI - Add TOML examples to `--config` help text ([#25013](https://github.com/astral-sh/ruff/pull/25013)) - Colorize ruff check 'All checks passed' ([#25085](https://github.com/astral-sh/ruff/pull/25085)) ### Configuration - Increase max allowed value of `line-length` setting ([#24962](https://github.com/astral-sh/ruff/pull/24962)) ### Documentation - Add `D203` to rules that conflict with the formatter ([#25044](https://github.com/astral-sh/ruff/pull/25044)) - Clarify `COM819` and formatter interaction ([#25045](https://github.com/astral-sh/ruff/pull/25045)) - Clarify that `NotImplemented` is a value, not an exception (`F901`) ([#25054](https://github.com/astral-sh/ruff/pull/25054)) - Update number of lint rules supported ([#24942](https://github.com/astral-sh/ruff/pull/24942)) ### Other changes - Simplify the playground's markdown template ([#24924](https://github.com/astral-sh/ruff/pull/24924)) ### Contributors - [@MichaReiser](https://github.com/MichaReiser) - [@brian-c11](https://github.com/brian-c11) - [@Andrej730](https://github.com/Andrej730) - [@denyszhak](https://github.com/denyszhak) - [@darestack](https://github.com/darestack) - [@sharkdp](https://github.com/sharkdp) - [@charliermarsh](https://github.com/charliermarsh) - [@EkriirkE](https://github.com/EkriirkE) - [@eyupcanakman](https://github.com/eyupcanakman) - [@Hrk84ya](https://github.com/Hrk84ya) - [@thernstig](https://github.com/thernstig) - [@ntBre](https://github.com/ntBre) ## Install ruff 0.15.13 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.13 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.13/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.15.14`](https://github.com/astral-sh/ruff/releases/tag/0.15.14): 0.15.14 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.14) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-05-21. ### Preview features - \[`airflow`\] Implement `airflow-task-implicit-multiple-outputs` (`AIR202`) ([#25152](https://github.com/astral-sh/ruff/pull/25152)) - \[`flake8-use-pathlib`\] Mark `PTH101` fix as unsafe when first argument is a class attribute annotated as `int` ([#25086](https://github.com/astral-sh/ruff/pull/25086)) - \[`pylint`\] Implement `too-many-try-statements` (`W0717`) ([#23970](https://github.com/astral-sh/ruff/pull/23970)) - \[`ruff`\] Add `incorrect-decorator-order` (`RUF074`) ([#23461](https://github.com/astral-sh/ruff/pull/23461)) - \[`ruff`\] Add `fallible-context-manager` (`RUF075`) ([#22844](https://github.com/astral-sh/ruff/pull/22844)) ### Bug fixes - Fix lambda formatting in interpolated string expressions ([#25144](https://github.com/astral-sh/ruff/pull/25144)) - Treat generic `frozenset` annotations as immutable ([#25251](https://github.com/astral-sh/ruff/pull/25251)) - \[`flake8-type-checking`\] Avoid `strict` behavior when `future-annotations` are enabled (`TC001`, `TC002`, `TC003`) ([#25035](https://github.com/astral-sh/ruff/pull/25035)) - \[`pylint`\] Avoid false positives in `else` clause (`PLR1733`) ([#25177](https://github.com/astral-sh/ruff/pull/25177)) ### Rule changes - \[`flake8-comprehensions`\] Skip `C417` for lambdas with positional-only parameters ([#25272](https://github.com/astral-sh/ruff/pull/25272)) - \[`flake8-simplify`\] Preserve f-string source verbatim in `SIM101` fix ([#25061](https://github.com/astral-sh/ruff/pull/25061)) ### Performance - Avoid unnecessary parser lookahead for operators ([#25290](https://github.com/astral-sh/ruff/pull/25290)) ### Documentation - Update code example setting Neovim LSP log level ([#25284](https://github.com/astral-sh/ruff/pull/25284)) ### Other changes - Add full PEP 798 support ([#25104](https://github.com/astral-sh/ruff/pull/25104)) - Add a parser recursion limit ([#24810](https://github.com/astral-sh/ruff/pull/24810)) - Update various `ruff_python_stdlib` APIs ([#25273](https://github.com/astral-sh/ruff/pull/25273)) ### Contributors - [@ocaballeror](https://github.com/ocaballeror) - [@lerebear](https://github.com/lerebear) - [@samuelcolvin](https://github.com/samuelcolvin) - [@baltasarblanco](https://github.com/baltasarblanco) - [@aconal-com](https://github.com/aconal-com) - [@anishgirianish](https://github.com/anishgirianish) - [@JelleZijlstra](https://github.com/JelleZijlstra) - [@AlexWaygood](https://github.com/AlexWaygood) - [@ntBre](https://github.com/ntBre) - [@adityasingh2400](https://github.com/adityasingh2400) - [@charliermarsh](https://github.com/charliermarsh) - [@Dev-iL](https://github.com/Dev-iL) - [@neutrinoceros](https://github.com/neutrinoceros) - [@shivamtiwari3](https://github.com/shivamtiwari3) - [@Dev-X25874](https://github.com/Dev-X25874) ## Install ruff 0.15.14 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.14 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.14/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.15.15`](https://github.com/astral-sh/ruff/releases/tag/0.15.15): 0.15.15 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.15) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-05-28. ### Preview features - Fix Markdown closing fence handling ([#25310](https://github.com/astral-sh/ruff/pull/25310)) - \[`pyflakes`\] Report duplicate imports in `typing.TYPE_CHECKING` block (`F811`) ([#22560](https://github.com/astral-sh/ruff/pull/22560)) ### Bug fixes - \[`pyflakes`\] Treat function-scope bare annotations as locals per PEP 526 (`F821`) ([#21540](https://github.com/astral-sh/ruff/pull/21540)) ### Performance - Avoid redundant `TokenValue` drops in the lexer ([#25300](https://github.com/astral-sh/ruff/pull/25300)) - Reduce memory usage by dropping token-excess capacity and improve performance by approximating the initial tokens `Vec` size ([#25354](https://github.com/astral-sh/ruff/pull/25354)) - Use `ThinVec` in AST to shrink `Stmt` ([#25361](https://github.com/astral-sh/ruff/pull/25361)) ### Documentation - Fix `line-length` example for `--config` option ([#25389](https://github.com/astral-sh/ruff/pull/25389)) - \[`flake8-comprehensions`\] Document `RecursionError` edge case in `__len__` (`C416`) ([#25286](https://github.com/astral-sh/ruff/pull/25286)) - \[`mccabe`\] Improve example (`C901`) ([#25287](https://github.com/astral-sh/ruff/pull/25287)) - \[`pyupgrade`\] Clarify fix safety docs (`UP007`, `UP045`) ([#25288](https://github.com/astral-sh/ruff/pull/25288)) - \[`refurb`\] Document `FURB192` exception change for empty sequences ([#25317](https://github.com/astral-sh/ruff/pull/25317)) - \[`ruff`\] Document false negative for user-defined types (`RUF013`) ([#25289](https://github.com/astral-sh/ruff/pull/25289)) ### Formatter - Fix formatting of lambdas nested within f-strings ([#25398](https://github.com/astral-sh/ruff/pull/25398)) ### Server - Return code action for `codeAction/resolve` requests that contain no or no valid URL ([#25365](https://github.com/astral-sh/ruff/pull/25365)) ### Other changes - Expand semantic syntax errors for invalid walruses ([#25415](https://github.com/astral-sh/ruff/pull/25415)) ### Contributors - [@chirizxc](https://github.com/chirizxc) - [@ntBre](https://github.com/ntBre) - [@adityasingh2400](https://github.com/adityasingh2400) - [@charliermarsh](https://github.com/charliermarsh) - [@fallintoplace](https://github.com/fallintoplace) - [@martin-schlossarek](https://github.com/martin-schlossarek) - [@MichaReiser](https://github.com/MichaReiser) - [@Ruchir28](https://github.com/Ruchir28) ## Install ruff 0.15.15 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.15 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.15/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.15.16`](https://github.com/astral-sh/ruff/releases/tag/0.15.16): 0.15.16 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.16) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-06-04. ### Preview features - \[`flake8-async`\] Implement `yield-in-context-manager-in-async-generator` (`ASYNC119`) ([#24644](https://github.com/astral-sh/ruff/pull/24644)) - \[`pylint`\] Narrow diagnostic range and exclude cases without exception handlers (`PLW0717`) ([#25440](https://github.com/astral-sh/ruff/pull/25440)) - \[`ruff`\] Treat `yield` before `break` from a terminal loop as terminal (`RUF075`) ([#25447](https://github.com/astral-sh/ruff/pull/25447)) ### Bug fixes - \[`eradicate`\] Avoid flagging `ruff:ignore` comments as code (`ERA001`) ([#25537](https://github.com/astral-sh/ruff/pull/25537)) - \[`eradicate`\] Fix `ERA001`/`RUF100` conflict when `noqa` is on commented-out code ([#25414](https://github.com/astral-sh/ruff/pull/25414)) - \[`pyflakes`\] Avoid removing the `format` call when it would change behavior (`F523`) ([#25320](https://github.com/astral-sh/ruff/pull/25320)) - \[`pylint`\] Avoid syntax errors in invalid character replacements in f-strings before Python 3.12 (`PLE2510`, `PLE2512`, `PLE2513`, `PLE2514`, `PLE2515`) ([#25544](https://github.com/astral-sh/ruff/pull/25544)) - \[`pyupgrade`\] Avoid converting `format` calls with more kinds of side effects (`UP032`) ([#25484](https://github.com/astral-sh/ruff/pull/25484)) ### Rule changes - \[`flake8-pytest-style`\] Avoid fixes for ambiguous `argnames` and `argvalues` combinations (`PT006`) ([#24776](https://github.com/astral-sh/ruff/pull/24776)) ### Performance - Drop excess capacity from statement suites during parsing ([#25368](https://github.com/astral-sh/ruff/pull/25368)) ### Documentation - \[`pydocstyle`\] Improve discoverability of rules enabled for each convention ([#24973](https://github.com/astral-sh/ruff/pull/24973)) - \[`ruff`\] Restore example code for Python versions before 3.15 (`RUF017`) ([#25439](https://github.com/astral-sh/ruff/pull/25439)) - Fix typo `bin/active` → `bin/activate` in tutorial ([#25473](https://github.com/astral-sh/ruff/pull/25473)) ### Other changes - Shrink additional parser AST collections ([#25465](https://github.com/astral-sh/ruff/pull/25465)) ### Contributors - [@Redslayer112](https://github.com/Redslayer112) - [@koriyoshi2041](https://github.com/koriyoshi2041) - [@George-Ogden](https://github.com/George-Ogden) - [@TejasAmle](https://github.com/TejasAmle) - [@anishgirianish](https://github.com/anishgirianish) - [@ntBre](https://github.com/ntBre) - [@MichaReiser](https://github.com/MichaReiser) - [@loganrosen](https://github.com/loganrosen) - [@RafaelJohn9](https://github.com/RafaelJohn9) - [@adityasingh2400](https://github.com/adityasingh2400) ## Install ruff 0.15.16 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.16 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.16/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.15.17`](https://github.com/astral-sh/ruff/releases/tag/0.15.17): 0.15.17 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.17) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-06-11. ### Preview features - Allow human-readable names in suppression comments ([#25614](https://github.com/astral-sh/ruff/pull/25614)) - Fix handling of `ignore` comments within a `disable`/`enable` pair ([#25845](https://github.com/astral-sh/ruff/pull/25845)) - Prioritize human-readable names in CLI output ([#25869](https://github.com/astral-sh/ruff/pull/25869)) - Respect diagnostic start and parent ranges and trailing comments in `ruff:ignore` suppressions ([#25673](https://github.com/astral-sh/ruff/pull/25673)) - \[`flake8-async`\] Add `trio.as_safe_channel` to safe decorators (`ASYNC119`) ([#25775](https://github.com/astral-sh/ruff/pull/25775)) - \[`flake8-pytest-style`\] Also check `pytest_asyncio` fixtures ([#25375](https://github.com/astral-sh/ruff/pull/25375)) - \[`ruff`\] Ban `pytest` autouse fixtures (`RUF076`) ([#25477](https://github.com/astral-sh/ruff/pull/25477)) - \[`pyupgrade`\] Add `from __future__ import annotations` automatically (`UP007`, `UP045`) ([#23259](https://github.com/astral-sh/ruff/pull/23259)) ### Bug fixes - Fix diagnostic when `ruff:enable` or `ruff:disable` appears where `ruff:ignore` is expected ([#25700](https://github.com/astral-sh/ruff/pull/25700)) - \[`pyupgrade`\] Preserve leading empty literals to avoid syntax errors (`UP032`) ([#25491](https://github.com/astral-sh/ruff/pull/25491)) ### Rule changes - \[`flake8-pytest-style`\] Clarify diagnostic message for single parameters (`PT007`) ([#25592](https://github.com/astral-sh/ruff/pull/25592)) - \[`numpy`\] Drop autofix for `np.in1d` (`NPY201`) ([#25612](https://github.com/astral-sh/ruff/pull/25612)) - \[`pylint`\] Exempt Python version comparisons (`PLR2004`) ([#25743](https://github.com/astral-sh/ruff/pull/25743)) ### Performance - Reserve AST `Vec`s with correct capacity for common cases ([#25451](https://github.com/astral-sh/ruff/pull/25451)) ### Formatter - Preserve whitespace for Quarto cell option comments ([#25641](https://github.com/astral-sh/ruff/pull/25641)) ### CLI - Allow rule names in `ruff rule` ([#25640](https://github.com/astral-sh/ruff/pull/25640)) ### Other changes - Fix playground diagnostics scrollbars ([#25642](https://github.com/astral-sh/ruff/pull/25642)) ### Contributors - [@SuryanshSS1011](https://github.com/SuryanshSS1011) - [@anishgirianish](https://github.com/anishgirianish) - [@romero-deshaw](https://github.com/romero-deshaw) - [@karlhillx](https://github.com/karlhillx) - [@carljm](https://github.com/carljm) - [@ntBre](https://github.com/ntBre) - [@11happy](https://github.com/11happy) - [@Kilo59](https://github.com/Kilo59) - [@oconnor663](https://github.com/oconnor663) - [@LeonidasZhak](https://github.com/LeonidasZhak) - [@DavisVaughan](https://github.com/DavisVaughan) - [@MeGaGiGaGon](https://github.com/MeGaGiGaGon) - [@jonathandung](https://github.com/jonathandung) - [@MichaReiser](https://github.com/MichaReiser) - [@brianmego](https://github.com/brianmego) ## Install ruff 0.15.17 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.17 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.17/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.15.18`](https://github.com/astral-sh/ruff/releases/tag/0.15.18): 0.15.18 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.18) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-06-18. ### Preview features - Handle nested `ruff:ignore` comments ([#25791](https://github.com/astral-sh/ruff/pull/25791)) - Stop displaying severity in output ([#26050](https://github.com/astral-sh/ruff/pull/26050)) - Use human-readable names in CLI output ([#25937](https://github.com/astral-sh/ruff/pull/25937)) - Use human-readable names in LSP and playground diagnostics ([#26058](https://github.com/astral-sh/ruff/pull/26058)) - \[`pydocstyle`\] Prevent property docstrings starting with verbs (`D421`) ([#23775](https://github.com/astral-sh/ruff/pull/23775)) - \[`flake8-pyi`\] Extend `PYI033` to Python files ([#26129](https://github.com/astral-sh/ruff/pull/26129)) ### Bug fixes - Detect equivalent numeric mapping keys ([#26009](https://github.com/astral-sh/ruff/pull/26009)) - Detect mapping keys equivalent to booleans ([#25982](https://github.com/astral-sh/ruff/pull/25982)) - Detect repeated signed and complex dictionary keys ([#26007](https://github.com/astral-sh/ruff/pull/26007)) ### Rule changes - \[`flake8-pyi`\] Rename `PYI033` to `legacy-type-comment` ([#26131](https://github.com/astral-sh/ruff/pull/26131)) ### Performance - Use `ThinVec` for call keywords ([#25999](https://github.com/astral-sh/ruff/pull/25999)) - Inline parser recovery context checks ([#26038](https://github.com/astral-sh/ruff/pull/26038)) - Match parser keywords as bytes ([#26037](https://github.com/astral-sh/ruff/pull/26037)) - Move value parsing out of lexing ([#25360](https://github.com/astral-sh/ruff/pull/25360)) ### Server - Render subdiagnostics and secondary annotations as related information ([#26011](https://github.com/astral-sh/ruff/pull/26011)) ### Documentation - Update fix availability for always-fixable rules ([#26091](https://github.com/astral-sh/ruff/pull/26091)) - \[`flake8-tidy-imports`\] Add fix safety section (`TID252`) ([#17491](https://github.com/astral-sh/ruff/pull/17491)) ### Parser - Reject `__debug__` lambda parameters ([#26022](https://github.com/astral-sh/ruff/pull/26022)) - Reject `_` as a match-pattern target ([#25977](https://github.com/astral-sh/ruff/pull/25977)) - Reject multiple starred names in sequence patterns ([#25976](https://github.com/astral-sh/ruff/pull/25976)) - Reject parenthesized star imports ([#26021](https://github.com/astral-sh/ruff/pull/26021)) - Reject starred comprehension targets ([#26023](https://github.com/astral-sh/ruff/pull/26023)) - Reject unparenthesized generator expressions in class bases ([#25978](https://github.com/astral-sh/ruff/pull/25978)) - Reject `yield` expressions after commas ([#26024](https://github.com/astral-sh/ruff/pull/26024)) - Validate function type parameter default order ([#25981](https://github.com/astral-sh/ruff/pull/25981)) ### Playground - Make diagnostic links clickable ([#26104](https://github.com/astral-sh/ruff/pull/26104)) - Use diagnostic tags ([#26105](https://github.com/astral-sh/ruff/pull/26105)) ### Contributors - [@AlexWaygood](https://github.com/AlexWaygood) - [@ntBre](https://github.com/ntBre) - [@gtkacz](https://github.com/gtkacz) - [@MichaReiser](https://github.com/MichaReiser) - [@charliermarsh](https://github.com/charliermarsh) - [@Kalmaegi](https://github.com/Kalmaegi) ## Install ruff 0.15.18 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.18 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.18/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.15.19`](https://github.com/astral-sh/ruff/releases/tag/0.15.19): 0.15.19 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.19) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-06-23. ### Preview features - Support human-readable names when hovering suppression comments and in code actions ([#26114](https://github.com/astral-sh/ruff/pull/26114)) ### Bug fixes - Fall back to default settings when editor-only settings are invalid ([#26244](https://github.com/astral-sh/ruff/pull/26244)) - Fix panic when inserting text at a notebook cell boundary ([#26111](https://github.com/astral-sh/ruff/pull/26111)) ### Rule changes - \[`pylint`\] Update fix suggestions for `__floor__`, `__trunc__`, `__length_hint__`, and `__matmul__` variants (`PLC2801`) ([#26239](https://github.com/astral-sh/ruff/pull/26239)) ### Performance - Avoid allocating when parsing single string literals ([#26200](https://github.com/astral-sh/ruff/pull/26200)) - Avoid reallocating singleton call arguments ([#26223](https://github.com/astral-sh/ruff/pull/26223)) - Lazily create source files for lint diagnostics ([#26226](https://github.com/astral-sh/ruff/pull/26226)) - Optimize formatter text width and indentation ([#26236](https://github.com/astral-sh/ruff/pull/26236)) - Reserve capacity for builtin bindings ([#26229](https://github.com/astral-sh/ruff/pull/26229)) - Skip repeated-key checks for singleton dictionaries ([#26228](https://github.com/astral-sh/ruff/pull/26228)) - Use ArrayVec for qualified name segments ([#26224](https://github.com/astral-sh/ruff/pull/26224)) ### Documentation - \[`flake8-pyi`\] Note that `PYI051` is an opinionated stylistic rule ([#26179](https://github.com/astral-sh/ruff/pull/26179)) - \[`pyupgrade`\] Clarify `UP029` as a Python 2 compatibility rule ([#26243](https://github.com/astral-sh/ruff/pull/26243)) ### Other changes - Publish Ruff crates to crates.io ([#26271](https://github.com/astral-sh/ruff/pull/26271)) ### Contributors - [@MakenRosa](https://github.com/MakenRosa) - [@MichaReiser](https://github.com/MichaReiser) - [@trilamsr](https://github.com/trilamsr) - [@ntBre](https://github.com/ntBre) - [@sanjibani](https://github.com/sanjibani) - [@charliermarsh](https://github.com/charliermarsh) ## Install ruff 0.15.19 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.19 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.19/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.15.20`](https://github.com/astral-sh/ruff/releases/tag/0.15.20): 0.15.20 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.20) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-06-25. ### Preview features - Allow human-readable names in rule selectors ([#25887](https://github.com/astral-sh/ruff/pull/25887)) - Emit a warning instead of an error for unknown rule selectors ([#26113](https://github.com/astral-sh/ruff/pull/26113)) - Match `noqa` shebang handling in `ruff:ignore` comments ([#26286](https://github.com/astral-sh/ruff/pull/26286)) - \[`ruff`\] Remove `pytest-fixture-autouse` (`RUF076`) ([#26240](https://github.com/astral-sh/ruff/pull/26240), [#26371](https://github.com/astral-sh/ruff/pull/26371)) ### Documentation - Add versioning sections to custom crate READMEs ([#26317](https://github.com/astral-sh/ruff/pull/26317)) - Update `ruff_python_parser` README for crates.io ([#26315](https://github.com/astral-sh/ruff/pull/26315)) - \[`perflint`\] Clarify that `PERF402` applies to any iterable ([#26242](https://github.com/astral-sh/ruff/pull/26242)) ### Contributors - [@dhruvmanila](https://github.com/dhruvmanila) - [@MichaReiser](https://github.com/MichaReiser) - [@ntBre](https://github.com/ntBre) - [@trilamsr](https://github.com/trilamsr) ## Install ruff 0.15.20 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.20 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.20/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.15.21`](https://github.com/astral-sh/ruff/releases/tag/0.15.21): 0.15.21 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.21) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-07-09. ### Preview features - Add `--add-ignore` for adding `ruff:ignore` comments ([#26346](https://github.com/astral-sh/ruff/pull/26346)) - \[`flake8-comprehensions`\] Drop `C409` tuple comprehension preview behavior ([#25707](https://github.com/astral-sh/ruff/pull/25707)) - Avoid whitespace normalization when formatting comments ([#26455](https://github.com/astral-sh/ruff/pull/26455)) - \[`pyupgrade`\] Lint and fix use of deprecated `abc` decorators (`UP051`) ([#26417](https://github.com/astral-sh/ruff/pull/26417)) ### Bug fixes - Refine non-empty f-string detection ([#26526](https://github.com/astral-sh/ruff/pull/26526)) - Detect syntax errors in individual notebook cells ([#26419](https://github.com/astral-sh/ruff/pull/26419)) - \[`flake8-implicit-str-concat`\] Fix `ISC003` autofix incorrectly stripping `+` from comments ([#26554](https://github.com/astral-sh/ruff/pull/26554)) ### Rule changes - \[`flake8-executable`\] Mark `EXE004` fix as unsafe ([#26033](https://github.com/astral-sh/ruff/pull/26033)) - \[`flake8-pyi`\] Mark `PYI061` fixes as unsafe in Python files ([#26533](https://github.com/astral-sh/ruff/pull/26533)) - \[`pydocstyle`\] Skip `overload-with-docstring` in stub files (`D418`) ([#26318](https://github.com/astral-sh/ruff/pull/26318)) ### Performance - Avoid per-token source index visitor calls ([#26506](https://github.com/astral-sh/ruff/pull/26506)) - Cache parenthesized expression boundaries in the formatter ([#26344](https://github.com/astral-sh/ruff/pull/26344)) - Improve performance of rendering edits in preview mode ([#26565](https://github.com/astral-sh/ruff/pull/26565)) - Inline `fits_element` in formatter ([#26429](https://github.com/astral-sh/ruff/pull/26429)) - Inline formatter printing hot paths ([#26504](https://github.com/astral-sh/ruff/pull/26504)) - Lazily create builtin bindings ([#26510](https://github.com/astral-sh/ruff/pull/26510)) - Skip empty trivia scans in the source indexer ([#26507](https://github.com/astral-sh/ruff/pull/26507)) - Use ICF for macOS release builds ([#25780](https://github.com/astral-sh/ruff/pull/25780)) ### Formatter - Add `--extend-exclude` to `ruff format` ([#26372](https://github.com/astral-sh/ruff/pull/26372)) ### Documentation - Add "How does Ruff's import sorting compare to isort?" link to README ([#26530](https://github.com/astral-sh/ruff/pull/26530)) - Fix Mozilla Firefox repository link in README ([#26537](https://github.com/astral-sh/ruff/pull/26537)) - \[`flake8-bandit`\] Fix misleading docstring for `mako-templates` (`S702`) ([#26432](https://github.com/astral-sh/ruff/pull/26432)) - \[`ruff`\] Fix non-triggering example for `if-key-in-dict-del` (`RUF051`) ([#26433](https://github.com/astral-sh/ruff/pull/26433)) ### Contributors - [@EkriirkE](https://github.com/EkriirkE) - [@tingerrr](https://github.com/tingerrr) - [@s-rigaud](https://github.com/s-rigaud) - [@nikolauspschuetz](https://github.com/nikolauspschuetz) - [@Avasam](https://github.com/Avasam) - [@ntBre](https://github.com/ntBre) - [@omar-y-abdi](https://github.com/omar-y-abdi) - [@AlexWaygood](https://github.com/AlexWaygood) - [@sylvestre](https://github.com/sylvestre) - [@shaanmajid](https://github.com/shaanmajid) - [@lerebear](https://github.com/lerebear) - [@baltasarblanco](https://github.com/baltasarblanco) - [@Sanjays2402](https://github.com/Sanjays2402) - [@ZedThree](https://github.com/ZedThree) - [@servusdei2018](https://github.com/servusdei2018) - [@charliermarsh](https://github.com/charliermarsh) - [@jesco-absolute](https://github.com/jesco-absolut) - [@velikodniy](https://github.com/velikodniy) - [@zaniebot](https://github.com/zaniebot) - [@epage](https://github.com/epage) ## Install ruff 0.15.21 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.21 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.21/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.15.22`](https://github.com/astral-sh/ruff/releases/tag/0.15.22): 0.15.22 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.15.22) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-07-16. ### Preview features - \[`pycodestyle`\] Add an autofix for `E402` ([#22212](https://github.com/astral-sh/ruff/pull/22212)) - \[`refurb`\] Allow subclassing builtins in stub files (`FURB189`) ([#26812](https://github.com/astral-sh/ruff/pull/26812)) - \[`ruff`\] Add rule to replace `noqa` comments with `ruff:ignore` (`RUF105`) ([#26423](https://github.com/astral-sh/ruff/pull/26423)) - \[`ruff`\] Add rule to use human-readable names in `ruff:ignore` comments (`RUF106`) ([#26682](https://github.com/astral-sh/ruff/pull/26682)) - \[`ruff`\] Add rule to use human-readable names in configuration selectors (`RUF201`) ([#26772](https://github.com/astral-sh/ruff/pull/26772)) ### Bug fixes - \[`flake8-pyi`\] Fix false positive in `__all__` (`PYI053`) ([#26872](https://github.com/astral-sh/ruff/pull/26872)) ### Rule changes - \[`pylint`\] Ignore mutable type updates in `redefined-loop-name` (`PLW2901`) ([#25733](https://github.com/astral-sh/ruff/pull/25733)) ### Performance - Avoid redundant lexer token bookkeeping ([#26765](https://github.com/astral-sh/ruff/pull/26765)) - Avoid redundant pending-indentation writes ([#26774](https://github.com/astral-sh/ruff/pull/26774)) - Avoid unnecessary identifier lookahead ([#26525](https://github.com/astral-sh/ruff/pull/26525)) - Reuse parser scratch buffers ([#26798](https://github.com/astral-sh/ruff/pull/26798)) ### Documentation - Document argfile support ([#26803](https://github.com/astral-sh/ruff/pull/26803)) - \[`flake8-datetimez`\] Clarify naming guidance for `datetime.today` (`DTZ002`) ([#26658](https://github.com/astral-sh/ruff/pull/26658)) - \[`pycodestyle`\] Document `E731` fix safety ([#26847](https://github.com/astral-sh/ruff/pull/26847)) - \[`ruff`\] Clarify intentional async contexts for `unused-async` (`RUF029`) ([#26641](https://github.com/astral-sh/ruff/pull/26641)) ### Contributors - [@dwego](https://github.com/dwego) - [@MichaReiser](https://github.com/MichaReiser) - [@Joosboy](https://github.com/Joosboy) - [@KaufmanDmitriy](https://github.com/KaufmanDmitriy) - [@PeterJCLaw](https://github.com/PeterJCLaw) - [@ntBre](https://github.com/ntBre) - [@charliermarsh](https://github.com/charliermarsh) ## Install ruff 0.15.22 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-installer.ps1 | iex" ``` ## Download ruff 0.15.22 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.15.22/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.16.0`](https://github.com/astral-sh/ruff/releases/tag/0.16.0): 0.16.0 **Breaking change detected.** [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.16.0) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-07-23. Check out the [blog post](https://astral.sh/blog/ruff-v0.16.0) for a migration guide and overview of the changes! ### Breaking changes - Ruff now enables a much larger set of rules by default (413, up from 59). See the blog post for more details and the new [Default Rules](https://docs.astral.sh/ruff/default-rules/) page for a full listing of the enabled rules. Note that this is primarily an expansion, but 18 of the more opinionated pycodestyle (`E`) and pyflakes (`F`) rules have been removed from the default set: `E401`, `E402`, `E701`, `E702`, `E703`, `E711`, `E712`, `E713`, `E714`, `E721`, `E731`, `E741`, `E742`, `E743`, `F403`, `F405`, `F406`, and `F722`. - Ruff can now format Python code blocks in Markdown files and will do this by default. See the [documentation](https://docs.astral.sh/ruff/formatter/#markdown-code-formatting) for more details. - Ruff now supports `ruff: ignore` comments at the ends of lines, like `noqa` comments, or on the line preceding a diagnostic. For example, these both suppress an [`unused-import`](https://docs.astral.sh/ruff/rules/unused-import/) (`F401`) diagnostic: ```py import math # ruff: ignore[F401] # ruff: ignore[F401] import os ``` - Fixes are now shown in `check` and `format --check` output: ````console ❯ ruff format --check . unformatted: File would be reformatted --> try.md:1:1 | 1 | ```python - import math 2 + import math 3 | ``` | 1 file would be reformatted ```` This example also shows off the Markdown formatting. - `format --check` now supports the same output formats as the linter, including the `github` and `gitlab` outputs for rendering annotations in CI: ```console ❯ ruff format --check --output-format github . ::error title=ruff (unformatted),file=try.md,line=2,col=8,endLine=2,endColumn=10::try.md:2:8: unformatted: File would be reformatted ``` See the CLI help or [documentation](https://docs.astral.sh/ruff/settings/#output-format) for the full list of supported formats. - The `filename`, `location`, `end_location`, `fix.edits[].location`, and `fix.edits[].end_location` fields in the JSON output format may now be `null` rather than defaulting to the empty string and row 1, column 1, respectively. ### Stabilization The following rules have been stabilized and are no longer in preview: - [`airflow3-incompatible-function-signature`](https://docs.astral.sh/ruff/rules/airflow3-incompatible-function-signature) (`AIR303`) - [`missing-copyright-notice`](https://docs.astral.sh/ruff/rules/missing-copyright-notice) (`CPY001`) - [`unnecessary-from-float`](https://docs.astral.sh/ruff/rules/unnecessary-from-float) (`FURB164`) - [`sorted-min-max`](https://docs.astral.sh/ruff/rules/sorted-min-max) (`FURB192`) - [`implicit-string-concatenation-in-collection-literal`](https://docs.astral.sh/ruff/rules/implicit-string-concatenation-in-collection-literal) (`ISC004`) - [`log-exception-outside-except-handler`](https://docs.astral.sh/ruff/rules/log-exception-outside-except-handler) (`LOG004`) - [`invalid-bool-return-type`](https://docs.astral.sh/ruff/rules/invalid-bool-return-type) (`PLE0304`) - [`too-many-positional-arguments`](https://docs.astral.sh/ruff/rules/too-many-positional-arguments) (`PLR0917`) - [`stop-iteration-return`](https://docs.astral.sh/ruff/rules/stop-iteration-return) (`PLR1708`) - [`none-not-at-end-of-union`](https://docs.astral.sh/ruff/rules/none-not-at-end-of-union) (`RUF036`) - [`access-annotations-from-class-dict`](https://docs.astral.sh/ruff/rules/access-annotations-from-class-dict) (`RUF063`) - [`duplicate-entry-in-dunder-all`](https://docs.astral.sh/ruff/rules/duplicate-entry-in-dunder-all) (`RUF068`) The following behaviors have been stabilized: - [`blind-except`](https://docs.astral.sh/ruff/rules/blind-except) (`BLE001`) is now suppressed when the exception is logged via `logging` methods other than `critical`, `error` and `exception`. - [`future-required-type-annotation`](https://docs.astral.sh/ruff/rules/future-required-type-annotation) (`FA102`) now checks for additional [PEP 585](https://peps.python.org/pep-0585/)-compatible APIs, such as those from `collections.abc`. - [`f-string-in-get-text-func-call`](https://docs.astral.sh/ruff/rules/f-string-in-get-text-func-call) (`INT001`), [`format-in-get-text-func-call`](https://docs.astral.sh/ruff/rules/format-in-get-text-func-call) (`INT002`), and [`printf-in-get-text-func-call`](https://docs.astral.sh/ruff/rules/printf-in-get-text-func-call) (`INT003`) now check for additional common ways of using the `gettext` module, such as assigning it to `builtins._`. - [`suspicious-url-open-usage`](https://docs.astral.sh/ruff/rules/suspicious-url-open-usage) (`S310`) now resolves local string literal bindings to avoid more false positives. - [`snmp-insecure-version`](https://docs.astral.sh/ruff/rules/snmp-insecure-version) (`S508`) and [`snmp-weak-cryptography`](https://docs.astral.sh/ruff/rules/snmp-weak-cryptography) (`S509`) now support the recommended API from newer versions of PySNMP. - [`typing-text-str-alias`](https://docs.astral.sh/ruff/rules/typing-text-str-alias) (`UP019`) now recognizes `typing_extensions.Text` in addition to `typing.Text`. ### Preview features - \[`pyupgrade`\] Fix false positive with `TypeVar` default before Python 3.13 (`UP040`) ([#26888](https://github.com/astral-sh/ruff/pull/26888)) ### Bug fixes - \[`ruff`\] Fix missing check on unrecognized early bound (`RUF016`) ([#26986](https://github.com/astral-sh/ruff/pull/26986)) ### Rule changes - Insert a space after the colon in Ruff suppression comments ([#27123](https://github.com/astral-sh/ruff/pull/27123)) ### Performance - \[`pyupgrade`\] Speed up `unnecessary-future-import` (`UP010`) ([#27047](https://github.com/astral-sh/ruff/pull/27047)) ### Documentation - \[`ruff`\] Add missing period in "Why is this bad?" section (`RUF200`) ([#26930](https://github.com/astral-sh/ruff/pull/26930)) - \[`flake8-simplify`\] Clarify `os.environ` behavior on Windows (`SIM112`) ([#26972](https://github.com/astral-sh/ruff/pull/26972)) - \[`pydocstyle`\] Document fix safety (`D400`) ([#26971](https://github.com/astral-sh/ruff/pull/26971)) ### Contributors - [@jonathandung](https://github.com/jonathandung) - [@Joosboy](https://github.com/Joosboy) - [@MichaReiser](https://github.com/MichaReiser) - [@Andrej730](https://github.com/Andrej730) - [@ntBre](https://github.com/ntBre) - [@zaniebot](https://github.com/zaniebot) ## Install ruff 0.16.0 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-installer.ps1 | iex" ``` ## Download ruff 0.16.0 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.0/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.16.1`](https://github.com/astral-sh/ruff/releases/tag/0.16.1): 0.16.1 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.16.1) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-07-30. ### Preview features - Add an option to opt out of human-readable names ([#27160](https://github.com/astral-sh/ruff/pull/27160)) - \[`flake8-pytest-style`\] Make fixes safe by default and unsafe only when comments are present (`PT018`) ([#27201](https://github.com/astral-sh/ruff/pull/27201)) - \[`pyupgrade`\] Skip fix when a defaulted `TypeVar` precedes a non-defaulted one (`UP040`, `UP046`, `UP047`) ([#27133](https://github.com/astral-sh/ruff/pull/27133)) - \[`ruff`\] Fix false positive with unpacked arguments (`RUF065`) ([#26959](https://github.com/astral-sh/ruff/pull/26959)) ### Bug fixes - Bump `gen-lsp-types` to gracefully handle unknown enumeration values in LSP messages ([#27230](https://github.com/astral-sh/ruff/pull/27230)) - \[`flake8-bugbear`\] Mark `range` as immutable (`B008`) ([#27247](https://github.com/astral-sh/ruff/pull/27247)) - \[`flake8-comprehensions`\] NFKC-normalize keyword names in `C408` fix ([#26813](https://github.com/astral-sh/ruff/pull/26813)) - \[`flake8-return`\] Fix false positive when variable is read in `finally` clause (`RET504`) ([#25441](https://github.com/astral-sh/ruff/pull/25441)) - \[`pydocstyle`\] Skip section detection inside RST directive bodies (`D214`, `D405`, `D413`) ([#23635](https://github.com/astral-sh/ruff/pull/23635)) - \[`refurb`\] Parenthesize `yield` arguments in the `FURB192` fix ([#27192](https://github.com/astral-sh/ruff/pull/27192)) ### Rule changes - \[`flake8-pytest-style`\] Mark `PT022` fixes as unsafe ([#26440](https://github.com/astral-sh/ruff/pull/26440)) - \[`refurb`\] Mark fixes that remove unknown separators as unsafe (`FURB105`) ([#27200](https://github.com/astral-sh/ruff/pull/27200)) ### Server - Fix indexing of excluded nested Ruff workspaces ([#27303](https://github.com/astral-sh/ruff/pull/27303)) - Lint TOML files in the LSP ([#26862](https://github.com/astral-sh/ruff/pull/26862)) ### Documentation - Cover `pycon` Markdown formatting ([#27153](https://github.com/astral-sh/ruff/pull/27153)) - \[`flake8-bandit`\] Document `TYPE_CHECKING` exception (`S101`) ([#27004](https://github.com/astral-sh/ruff/pull/27004)) - \[`flake8-import-conventions`\] Document that `extend-aliases` can override default aliases ([#27191](https://github.com/astral-sh/ruff/pull/27191)) - \[`pylint`\] Add missing fix safety gotchas for `non-augmented-assignment` (`PLR6104`) ([#27250](https://github.com/astral-sh/ruff/pull/27250)) ### Other changes - Reduce syntax error noise by swallowing dedents like indents ([#27170](https://github.com/astral-sh/ruff/pull/27170)) - Vendor latest annotate-snippets ([#27033](https://github.com/astral-sh/ruff/pull/27033)) ### Contributors - [@bxff](https://github.com/bxff) - [@anishgirianish](https://github.com/anishgirianish) - [@Avasam](https://github.com/Avasam) - [@epage](https://github.com/epage) - [@LHMQ878](https://github.com/LHMQ878) - [@MichaReiser](https://github.com/MichaReiser) - [@ntBre](https://github.com/ntBre) - [@HarshalPatel1972](https://github.com/HarshalPatel1972) - [@mjpieters](https://github.com/mjpieters) - [@joshuavetos](https://github.com/joshuavetos) - [@jesco-absolute](https://github.com/jesco-absolut) - [@vidigoat](https://github.com/vidigoat) - [@baltasarblanco](https://github.com/baltasarblanco) - [@ribru17](https://github.com/ribru17) - [@oh-summy](https://github.com/oh-summy) - [@Jayashanker-Padishala](https://github.com/Jayashanker-Padishala) ## Install ruff 0.16.1 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-installer.ps1 | iex" ``` ## Download ruff 0.16.1 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.1/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.16.2`](https://github.com/astral-sh/ruff/releases/tag/0.16.2): 0.16.2 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.16.2) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-08-06. ### Bug fixes - \[`flake8-pyi`\] Avoid false positives on `singledispatch` functions (`PYI041`) ([#27335](https://github.com/astral-sh/ruff/pull/27335)) ### Server - Register formatting capabilities dynamically to exclude TOML files ([#27332](https://github.com/astral-sh/ruff/pull/27332)) ### Contributors - [@MeGaGiGaGon](https://github.com/MeGaGiGaGon) - [@charliermarsh](https://github.com/charliermarsh) - [@epage](https://github.com/epage) - [@sharkdp](https://github.com/sharkdp) - [@ntBre](https://github.com/ntBre) ## Install ruff 0.16.2 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-installer.ps1 | iex" ``` ## Download ruff 0.16.2 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.16.3`](https://github.com/astral-sh/ruff/releases/tag/0.16.3): 0.16.3 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.16.3) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-08-13. ### Preview features - \[`pylint`\] Fix false negatives on negative numbers (`PLR6104`) ([#27251](https://github.com/astral-sh/ruff/pull/27251)) - \[`pyupgrade`\] Add rule to replace `while 1` with `while True` (`UP048`) ([#27190](https://github.com/astral-sh/ruff/pull/27190)) ### Bug fixes - \[`flake8-bandit`\] Also check keyword arguments (`S602`, `S603`, `S607`, `S609`) ([#27687](https://github.com/astral-sh/ruff/pull/27687)) - \[`pylint`\] Allow `continue` in `finally` on Python 3.8 ([#27626](https://github.com/astral-sh/ruff/pull/27626)) - \[`pylint`\] Fix `PLE1307` false positive with bools ([#27651](https://github.com/astral-sh/ruff/pull/27651)) - \[`pylint`\] Fix false positives and negatives with `%b` format character (`PLE1300`, `PLE1307`) ([#27560](https://github.com/astral-sh/ruff/pull/27560)) - \[`pylint`\] Improve handling of concatenated strings (`PLE1300`) ([#27659](https://github.com/astral-sh/ruff/pull/27659)) ### Rule changes - \[`numpy`\] Make `np.chararray` autofix backwards-compatible (`NPY201`) ([#27527](https://github.com/astral-sh/ruff/pull/27527)) ### Performance - Enable PGO for Linux x86-64 Ruff releases ([#27570](https://github.com/astral-sh/ruff/pull/27570)) - Enable PGO for Linux ARM64 Ruff releases ([#27574](https://github.com/astral-sh/ruff/pull/27574)) - Enable PGO for Windows x86-64 Ruff releases ([#27573](https://github.com/astral-sh/ruff/pull/27573)) - Enable PGO for macOS ARM64 Ruff releases ([#27572](https://github.com/astral-sh/ruff/pull/27572)) - Reduce `Expr` size to 64 bytes ([#27591](https://github.com/astral-sh/ruff/pull/27591)) ### CLI - Hyperlink rule codes in `ruff check --statistics` output ([#27646](https://github.com/astral-sh/ruff/pull/27646)) ### Documentation - \[`ruff`\] Also suggest `asyncio.TaskGroup` (`RUF006`) ([#27461](https://github.com/astral-sh/ruff/pull/27461)) ### Other changes - Use mimalloc v3 ([#27586](https://github.com/astral-sh/ruff/pull/27586)) ### Contributors - [@Andrej730](https://github.com/Andrej730) - [@alonfaraj](https://github.com/alonfaraj) - [@romero-deshaw](https://github.com/romero-deshaw) - [@Avasam](https://github.com/Avasam) - [@tjkuson](https://github.com/tjkuson) - [@charliermarsh](https://github.com/charliermarsh) - [@chirizxc](https://github.com/chirizxc) - [@saberoueslati](https://github.com/saberoueslati) - [@MichaReiser](https://github.com/MichaReiser) ## Install ruff 0.16.3 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-installer.ps1 | iex" ``` ## Download ruff 0.16.3 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.3/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.16.4`](https://github.com/astral-sh/ruff/releases/tag/0.16.4): 0.16.4 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.16.4) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-08-20. ### Preview features - \[`flake8-use-pathlib`\] Add autofix for `PTH116` ([#26460](https://github.com/astral-sh/ruff/pull/26460)) - \[`refurb`\] Restrict `delete-full-slice` to lists (`FURB131`) ([#27711](https://github.com/astral-sh/ruff/pull/27711)) - \[`refurb`\] Skip `FURB101` and `FURB103` when the `open` argument is a file descriptor ([#27643](https://github.com/astral-sh/ruff/pull/27643)) ### Bug fixes - Fix `InvalidInstruction` on Windows CPUs that do not support `POPCNT` ([#27803](https://github.com/astral-sh/ruff/pull/27803)) - \[`pyflakes`\] Emit semantic syntax errors in string type definitions as `F722` ([#27835](https://github.com/astral-sh/ruff/pull/27835)) - \[`pylint`\] Allow `os._exit` imports in `import-private-name` (`PLC2701`) ([#27738](https://github.com/astral-sh/ruff/pull/27738)) ### Rule changes - [syntax-errors] Align mixed t-string/bytes error message with CPython 3.14 ([#27766](https://github.com/astral-sh/ruff/pull/27766)) - \[`ruff`\] Add `ctypes.LittleEndianStructure` and related types to existing exception (`RUF012`) ([#27753](https://github.com/astral-sh/ruff/pull/27753)) - [syntax-errors] Detect duplicate keyword arguments ([#17804](https://github.com/astral-sh/ruff/pull/17804)) - [syntax-errors] Detect parameters declared `nonlocal` ([#27628](https://github.com/astral-sh/ruff/pull/27628)) ### Server - Offer display-only fixes and mark safe fixes preferred ([#27807](https://github.com/astral-sh/ruff/pull/27807)) - Support pull diagnostics for notebook cells ([#27779](https://github.com/astral-sh/ruff/pull/27779)) ### Documentation - Add default indicator to rules table ([#27724](https://github.com/astral-sh/ruff/pull/27724)) - Fix broken link to Python docs ([#27757](https://github.com/astral-sh/ruff/pull/27757)) ### Other changes - Fix s390x stacker assembly in release builds ([#27776](https://github.com/astral-sh/ruff/pull/27776)) - Guarantee minimum stack size when parsing a module, standalone expression, and suites ([#25464](https://github.com/astral-sh/ruff/pull/25464)) - Reduce configuration deserialization code size ([#27924](https://github.com/astral-sh/ruff/pull/27924)) - Check packed AST index bounds ([#27849](https://github.com/astral-sh/ruff/pull/27849)) ### Contributors - [@AbhinavMir](https://github.com/AbhinavMir) - [@eduardorittner](https://github.com/eduardorittner) - [@royb3](https://github.com/royb3) - [@MichaReiser](https://github.com/MichaReiser) - [@carljm](https://github.com/carljm) - [@rosstitmarsh](https://github.com/rosstitmarsh) - [@ntBre](https://github.com/ntBre) - [@zaniebot](https://github.com/zaniebot) - [@ewdurbin](https://github.com/ewdurbin) - [@woodruffw](https://github.com/woodruffw) - [@Sacrimento](https://github.com/Sacrimento) - [@lakshayxi](https://github.com/lakshayxi) - [@WhiteFox0-0](https://github.com/WhiteFox0-0) - [@baltasarblanco](https://github.com/baltasarblanco) ## Install ruff 0.16.4 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-installer.ps1 | iex" ``` ## Download ruff 0.16.4 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.4/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.16.5`](https://github.com/astral-sh/ruff/releases/tag/0.16.5): 0.16.5 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.16.5) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-08-27. ### Preview features - Allow rules without codes ([#28049](https://github.com/astral-sh/ruff/pull/28049)) - Introduce category selectors ([#27666](https://github.com/astral-sh/ruff/pull/27666)) - Update preview default rules and categories ([#27877](https://github.com/astral-sh/ruff/pull/27877)) ### Bug fixes - \[`flake8-async`\] Detect blocking generic HTTP requests (`ASYNC210`) ([#28024](https://github.com/astral-sh/ruff/pull/28024)) - \[`flake8-datetimez`\] Allow timezone-safe `strptime` chains (`DTZ007`) ([#28023](https://github.com/astral-sh/ruff/pull/28023)) - \[`flake8-simplify`\] Respect side effects in `lambda` defaults (`SIM401`) ([#28000](https://github.com/astral-sh/ruff/pull/28000)) ### Server - Fix duplicated "of" in `ClientOptions` doc comment ([#27978](https://github.com/astral-sh/ruff/pull/27978)) ### Documentation - Document rule acceptance guidelines ([#27910](https://github.com/astral-sh/ruff/pull/27910)) - Document the new category selectors ([#27906](https://github.com/astral-sh/ruff/pull/27906)) ### Contributors - [@AlexWaygood](https://github.com/AlexWaygood) - [@sharkdp](https://github.com/sharkdp) - [@jelle-openai](https://github.com/jelle-openai) - [@charliermarsh](https://github.com/charliermarsh) - [@ntBre](https://github.com/ntBre) - [@aarushkandukoori](https://github.com/aarushkandukoori) ## Install ruff 0.16.5 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-installer.ps1 | iex" ``` ## Download ruff 0.16.5 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.5/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.16.6`](https://github.com/astral-sh/ruff/releases/tag/0.16.6): 0.16.6 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.16.6) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-09-03. ### Preview features - Move `pytest-fixture-autouse` to the `restriction` category ([#28219](https://github.com/astral-sh/ruff/pull/28219)) - \[`flake8-pytest-style`\] Add an autofix for `PT020` ([#27993](https://github.com/astral-sh/ruff/pull/27993)) - \[`flake8-tidy-imports`\] Prevent fix loop between `TID254` and `TID255` ([#28262](https://github.com/astral-sh/ruff/pull/28262)) - \[`isort`\] Exclude pragma comments from line length calculation (`I001`) ([#27313](https://github.com/astral-sh/ruff/pull/27313)) ### Bug fixes - Validate unary expressions when parsing ([#28233](https://github.com/astral-sh/ruff/pull/28233)) - \[`flake8-async`, `pylint`\] Recognize `builtins.open` (`ASYNC230`, `PLW1514`) ([#28021](https://github.com/astral-sh/ruff/pull/28021)) - \[`flake8-bugbear`\] Fix panic on `match` subjects (`B031`) ([#27781](https://github.com/astral-sh/ruff/pull/27781)) - \[`flake8-datetimez`\] Reject `tzinfo=None` for `datetime` bounds (`DTZ901`) ([#28022](https://github.com/astral-sh/ruff/pull/28022)) - \[`flake8-pytest-style`\] Avoid duplicate `PT017` diagnostics ([#27918](https://github.com/astral-sh/ruff/pull/27918)) - \[`ruff`\] Remove `lint.external` hint for Ruff-specific suppressions (`RUF102`) ([#27923](https://github.com/astral-sh/ruff/pull/27923)) ### Rule changes - \[`flake8-use-pathlib`\] Add display-only fix for `os.listdir` (`PTH208`) ([#28027](https://github.com/astral-sh/ruff/pull/28027)) ### Documentation - Add another example and glob reference for `lint.per-file-ignores` ([#28106](https://github.com/astral-sh/ruff/pull/28106)) - Add duplicate work guidance ([#28229](https://github.com/astral-sh/ruff/pull/28229)) - \[`flake8-async`\] Document thread offloading (`ASYNC240`) ([#28008](https://github.com/astral-sh/ruff/pull/28008)) - \[`pyupgrade`\] Clarify default `encoding` argument handling (`UP012`) ([#27315](https://github.com/astral-sh/ruff/pull/27315)) ### Other changes - Allow unary plus in match patterns on Python 3.15 ([#28231](https://github.com/astral-sh/ruff/pull/28231)) ### Contributors - [@flying-sheep](https://github.com/flying-sheep) - [@pikammmmm](https://github.com/pikammmmm) - [@fly1d](https://github.com/fly1d) - [@waterWang](https://github.com/waterWang) - [@Pierre-Sassoulas](https://github.com/Pierre-Sassoulas) - [@ntBre](https://github.com/ntBre) - [@jelle-openai](https://github.com/jelle-openai) - [@ericbuehl](https://github.com/ericbuehl) - [@tjkuson](https://github.com/tjkuson) - [@AbhinavMir](https://github.com/AbhinavMir) - [@Whning0513](https://github.com/Whning0513) - [@chirizxc](https://github.com/chirizxc) ## Install ruff 0.16.6 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-installer.ps1 | iex" ``` ## Download ruff 0.16.6 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.6/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.16.7`](https://github.com/astral-sh/ruff/releases/tag/0.16.7): 0.16.7 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.16.7) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-09-10. ### Preview features - \[`ruff`\] Add rule for default values on method receivers (`RUF077`) ([#26700](https://github.com/astral-sh/ruff/pull/26700)) - \[`ruff`\] Recognize `re.prefixmatch` (`RUF039`, `RUF055`) ([#28311](https://github.com/astral-sh/ruff/pull/28311)) ### Bug fixes - Alternate nested quotes inside format spec interpolations ([#28259](https://github.com/astral-sh/ruff/pull/28259)) - \[`flake8-implicit-str-concat`\] Mark fix unsafe when it creates a docstring (`ISC003`) ([#27981](https://github.com/astral-sh/ruff/pull/27981)) - \[`flake8-tidy-imports`\] Skip fixes for multi-member imports (`TID254`) ([#26584](https://github.com/astral-sh/ruff/pull/26584)) - \[`pylint`\] Gate `ImportCycleError` on Python 3.15 (`PLW0133`) ([#28310](https://github.com/astral-sh/ruff/pull/28310)) ### Rule changes - Correct `D211` and `D203` rule conflict diagnostic ([#28444](https://github.com/astral-sh/ruff/pull/28444)) - Recognize `slice` and `frozendict` generics ([#28477](https://github.com/astral-sh/ruff/pull/28477)) - Stop defining `__cached__` for Python 3.15 ([#28476](https://github.com/astral-sh/ruff/pull/28476)) - \[`pyupgrade`\] Stop recommending removed `typing.no_type_check_decorator` (`UP035`) ([#28475](https://github.com/astral-sh/ruff/pull/28475)) ### Performance - Reuse parser name lookups when interning ([#28399](https://github.com/astral-sh/ruff/pull/28399)) - Speed up inherited configuration resolution ([#28299](https://github.com/astral-sh/ruff/pull/28299)) ### Documentation - Fix `line-length` path in `--config` example ([#28392](https://github.com/astral-sh/ruff/pull/28392)) - Remove the "Who’s Using Ruff?" list ([#28455](https://github.com/astral-sh/ruff/pull/28455)) ### Other changes - Embed archive checksums in the shell installer ([#28281](https://github.com/astral-sh/ruff/pull/28281)) ### Contributors - [@The-Compiler](https://github.com/The-Compiler) - [@mdiniz97](https://github.com/mdiniz97) - [@zsol](https://github.com/zsol) - [@gorewilliams](https://github.com/gorewilliams) - [@RafaelJohn9](https://github.com/RafaelJohn9) - [@qatcod](https://github.com/qatcod) - [@zanieb](https://github.com/zanieb) - [@MichaReiser](https://github.com/MichaReiser) - [@ntBre](https://github.com/ntBre) - [@charliermarsh](https://github.com/charliermarsh) - [@nightt5879](https://github.com/nightt5879) - [@jonathandung](https://github.com/jonathandung) - [@jogo-openai](https://github.com/jogo-openai) ## Install ruff 0.16.7 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-installer.ps1 | iex" ``` ## Download ruff 0.16.7 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.7/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.16.8`](https://github.com/astral-sh/ruff/releases/tag/0.16.8): 0.16.8 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.16.8) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-09-16. ### Bug fixes - Visit functional `TypedDict` keyword arguments correctly ([#28584](https://github.com/astral-sh/ruff/pull/28584)) - \[`flake8-simplify`\] Detect nested `async with` under sync parent (`SIM117`) ([#27821](https://github.com/astral-sh/ruff/pull/27821)) - \[`flake8-simplify`\] Preserve operand order in `SIM109` fix ([#27824](https://github.com/astral-sh/ruff/pull/27824)) - \[`pyupgrade`\] Preserve required parentheses in multiline `UP040` fixes ([#28164](https://github.com/astral-sh/ruff/pull/28164)) - \[`pyupgrade`\] Skip `TypeVarTuple` and `ParamSpec` conversions with bounds or constraints (`UP040`, `UP046`, `UP047`) ([#28505](https://github.com/astral-sh/ruff/pull/28505)) ### Rule changes - Add support for `__lazy_modules__` ([#28459](https://github.com/astral-sh/ruff/pull/28459)) - Recognize PEP-728 `TypedDict` class keywords ([#28533](https://github.com/astral-sh/ruff/pull/28533)) - Recognize quoted types in `typing.TypeForm` ([#28507](https://github.com/astral-sh/ruff/pull/28507)) - Support conditional assignment to `__lazy_modules__` ([#28491](https://github.com/astral-sh/ruff/pull/28491)) - \[`flake8-type-checking`\] Prefer lazy imports over `TYPE_CHECKING` on Python 3.15 and later (`TC001`, `TC002`, `TC003`) ([#28541](https://github.com/astral-sh/ruff/pull/28541)) - \[`pyupgrade`\] Make the fix for `UP040` always unsafe ([#28526](https://github.com/astral-sh/ruff/pull/28526)) - \[`pyupgrade`\] Stop recommending deprecated `ByteString` aliases (`UP035`) ([#28498](https://github.com/astral-sh/ruff/pull/28498)) - \[`ruff`, `flake8-use-pathlib`\] Recognize the `parent_mode` argument (`RUF064`, `PTH103`) ([#28528](https://github.com/astral-sh/ruff/pull/28528)) - \[`ruff`\] Detect `\Z` in `pytest.raises()` match patterns (`RUF043`) ([#28598](https://github.com/astral-sh/ruff/pull/28598)) ### CLI - Use rule name and code in formatter incompatibility warnings ([#28571](https://github.com/astral-sh/ruff/pull/28571)) ### Configuration - \[`flake8-tidy-imports`\] Add `extend-banned-api` ([#28644](https://github.com/astral-sh/ruff/pull/28644)) ### Contributors - [@VedantMadane](https://github.com/VedantMadane) - [@alzeph](https://github.com/alzeph) - [@charliermarsh](https://github.com/charliermarsh) - [@fredrikblau](https://github.com/fredrikblau) - [@ntBre](https://github.com/ntBre) - [@zsol](https://github.com/zsol) - [@Aniket-a14](https://github.com/Aniket-a14) - [@r-b-1](https://github.com/r-b-1) ## Install ruff 0.16.8 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-installer.ps1 | iex" ``` ## Download ruff 0.16.8 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.8/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` ### [`0.16.9`](https://github.com/astral-sh/ruff/releases/tag/0.16.9): 0.16.9 [Compare source](https://github.com/astral-sh/ruff/compare/0.14.11...0.16.9) [Source](https://github.com/astral-sh/ruff) ## Release Notes Released on 2026-09-24. ### Preview features - \[`ruff`\] Avoid false positives for overloaded division (`RUF069`) ([#28309](https://github.com/astral-sh/ruff/pull/28309)) ### Bug fixes - \[`flake8-bugbear`\] Avoid false positives for calls with keyword arguments (`B009`, `B010`, `B043`) ([#28776](https://github.com/astral-sh/ruff/pull/28776)) - \[`flake8-tidy-imports`\] Allow lazy imports to be used in deferred annotations (`TID255`) ([#28767](https://github.com/astral-sh/ruff/pull/28767)) ### Rule changes - Update LibCST-based fixes for Python 3.15 ([#28616](https://github.com/astral-sh/ruff/pull/28616)) - \[`flake8-pyi`\] Mention stubs in the diagnostic message (`PYI002`) ([#28542](https://github.com/astral-sh/ruff/pull/28542)) ### Documentation - Fix horizontal overflow on the rules documentation page ([#28699](https://github.com/astral-sh/ruff/pull/28699)) - Update rules table with category information ([#28651](https://github.com/astral-sh/ruff/pull/28651)) - \[`flake8-annotations`\] Clarify that `ANN401` checks return types in addition to arguments ([#28334](https://github.com/astral-sh/ruff/pull/28334)) - \[`flake8-bugbear`\] Document type-checker interaction (`B010`) ([#28509](https://github.com/astral-sh/ruff/pull/28509)) - \[`flake8-comprehensions`\] Document `map`/generator exception behavior (`C417`) ([#27794](https://github.com/astral-sh/ruff/pull/27794)) - \[`ruff`\] Mention related isort settings (`RUF022`) ([#28719](https://github.com/astral-sh/ruff/pull/28719)) ### Contributors - [@qinpei-dev](https://github.com/qinpei-dev) - [@sanjayrohith](https://github.com/sanjayrohith) - [@ntBre](https://github.com/ntBre) - [@webdevsamran](https://github.com/webdevsamran) - [@zaniebot](https://github.com/zaniebot) - [@ewdurbin](https://github.com/ewdurbin) - [@MichaReiser](https://github.com/MichaReiser) - [@spaceone](https://github.com/spaceone) - [@IbrahimKhan12](https://github.com/IbrahimKhan12) - [@devtechedge](https://github.com/devtechedge) - [@GruffElixir](https://github.com/GruffElixir) ## Install ruff 0.16.9 ### Install prebuilt binaries via shell script ```sh curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-installer.sh | sh ``` ### Install prebuilt binaries via powershell script ```sh powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-installer.ps1 | iex" ``` ## Download ruff 0.16.9 | File | Platform | Checksum | |--------|----------|----------| | [ruff-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-aarch64-apple-darwin.tar.gz.sha256) | | [ruff-x86_64-apple-darwin.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-x86_64-apple-darwin.tar.gz.sha256) | | [ruff-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-aarch64-pc-windows-msvc.zip) | ARM64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-aarch64-pc-windows-msvc.zip.sha256) | | [ruff-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-i686-pc-windows-msvc.zip) | x86 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-i686-pc-windows-msvc.zip.sha256) | | [ruff-x86_64-pc-windows-msvc.zip](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-x86_64-pc-windows-msvc.zip.sha256) | | [ruff-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-aarch64-unknown-linux-gnu.tar.gz) | ARM64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-i686-unknown-linux-gnu.tar.gz) | x86 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-i686-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-powerpc64-unknown-linux-gnu.tar.gz) | PPC64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-powerpc64le-unknown-linux-gnu.tar.gz) | PPC64LE Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256) | | [ruff-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-riscv64gc-unknown-linux-gnu.tar.gz) | RISCV Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256) | | [ruff-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-s390x-unknown-linux-gnu.tar.gz) | S390x Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-s390x-unknown-linux-gnu.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-x86_64-unknown-linux-gnu.tar.gz.sha256) | | [ruff-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-armv7-unknown-linux-gnueabihf.tar.gz) | ARMv7 Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-armv7-unknown-linux-gnueabihf.tar.gz.sha256) | | [ruff-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-aarch64-unknown-linux-musl.tar.gz) | ARM64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-aarch64-unknown-linux-musl.tar.gz.sha256) | | [ruff-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-i686-unknown-linux-musl.tar.gz) | x86 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-i686-unknown-linux-musl.tar.gz.sha256) | | [ruff-x86_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-x86_64-unknown-linux-musl.tar.gz) | x64 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-x86_64-unknown-linux-musl.tar.gz.sha256) | | [ruff-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-arm-unknown-linux-musleabihf.tar.gz) | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-arm-unknown-linux-musleabihf.tar.gz.sha256) | | [ruff-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux | [checksum](https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-armv7-unknown-linux-musleabihf.tar.gz.sha256) | ## Verifying GitHub Artifact Attestations The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify): ```sh gh attestation verify <file-path of downloaded artifact> --repo astral-sh/ruff ``` You can also download the attestation from [GitHub](https://github.com/astral-sh/ruff/attestations) and verify against that directly: ```sh gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation> ``` </details> <details> <summary>typing-extensions (current version → 4.16.0)</summary> Source comparison unavailable: source refs for this transition are not known. ### `3.6.2` ### `3.6.2.1` ### `3.6.5` ### `3.6.6` ### `3.7.2` ### `3.7.4` ### `3.7.4.1` ### `3.7.4.2` ### `3.7.4.3` ### `3.10.0.0` ### `3.10.0.1` ### `3.10.0.2` ### `4.0.0` ### `4.0.1` ### `4.1.0` ### `4.1.1` ### `4.2.0` ### `4.3.0` ### `4.4.0` ### `4.5.0` ### `4.6.0` ### `4.6.1` ### `4.6.2` ### `4.6.3` ### [`4.7.0`](https://github.com/python/typing_extensions/releases/tag/4.7.0): 4.7.0 [Source](https://github.com/python/typing_extensions) Source ref: <code>main</code> This is a feature release. Major changes include: - All non-deprecated names from `typing` are now re-exported by `typing_extensions` for convenience - Add `typing_extensions.get_protocol_members` and `typing_extensions.is_protocol` - Declare support for Python 3.12 - This will be the last feature release to support Python 3.7, which recently reached its end-of-life Full changelog of versions 4.7.0 and 4.7.0rc1: # Release 4.7.0 (June 28, 2023) - This is expected to be the last feature release supporting Python 3.7, which reaches its end of life on June 27, 2023. Version 4.8.0 will support only Python 3.8.0 and up. - Fix bug where a `typing_extensions.Protocol` class that had one or more non-callable members would raise `TypeError` when `issubclass()` was called against it, even if it defined a custom `__subclasshook__` method. The correct behaviour -- which has now been restored -- is not to raise `TypeError` in these situations if a custom `__subclasshook__` method is defined. Patch by Alex Waygood (backporting https://github.com/python/cpython/pull/105976). # Release 4.7.0rc1 (June 21, 2023) - Add `typing_extensions.get_protocol_members` and `typing_extensions.is_protocol` (backport of CPython PR #104878). Patch by Jelle Zijlstra. - `typing_extensions` now re-exports all names in the standard library's `typing` module, except the deprecated `ByteString`. Patch by Jelle Zijlstra. - Due to changes in the implementation of `typing_extensions.Protocol`, `typing.runtime_checkable` can now be used on `typing_extensions.Protocol` (previously, users had to use `typing_extensions.runtime_checkable` if they were using `typing_extensions.Protocol`). - Align the implementation of `TypedDict` with the implementation in the standard library on Python 3.9 and higher. `typing_extensions.TypedDict` is now a function instead of a class. The private functions `_check_fails`, `_dict_new`, and `_typeddict_new` have been removed. `is_typeddict` now returns `False` when called with `TypedDict` itself as the argument. Patch by Jelle Zijlstra. - Declare support for Python 3.12. Patch by Jelle Zijlstra. - Fix tests on Python 3.13, which removes support for creating `TypedDict` classes through the keyword-argument syntax. Patch by Jelle Zijlstra. - Fix a regression introduced in v4.6.3 that meant that ``issubclass(object, typing_extensions.Protocol)`` would erroneously raise ``TypeError``. Patch by Alex Waygood (backporting the CPython PR https://github.com/python/cpython/pull/105239). - Allow `Protocol` classes to inherit from `typing_extensions.Buffer` or `collections.abc.Buffer`. Patch by Alex Waygood (backporting https://github.com/python/cpython/pull/104827, by Jelle Zijlstra). - Allow classes to inherit from both `typing.Protocol` and `typing_extensions.Protocol` simultaneously. Since v4.6.0, this caused `TypeError` to be raised due to a metaclass conflict. Patch by Alex Waygood. - Backport several deprecations from CPython relating to unusual ways to create `TypedDict`s and `NamedTuple`s. CPython PRs #105609 and #105780 by Alex Waygood; `typing_extensions` backport by Jelle Zijlstra. - Creating a `NamedTuple` using the functional syntax with keyword arguments (`NT = NamedTuple("NT", a=int)`) is now deprecated. - Creating a `NamedTuple` with zero fields using the syntax `NT = NamedTuple("NT")` or `NT = NamedTuple("NT", None)` is now deprecated. - Creating a `TypedDict` with zero fields using the syntax `TD = TypedDict("TD")` or `TD = TypedDict("TD", None)` is now deprecated. - Fix bug on Python 3.7 where a protocol `X` that had a member `a` would not be considered an implicit subclass of an unrelated protocol `Y` that only has a member `a`. Where the members of `X` are a superset of the members of `Y`, `X` should always be considered a subclass of `Y` iff `Y` is a runtime-checkable protocol that only has callable members. Patch by Alex Waygood (backporting CPython PR https://github.com/python/cpython/pull/105835). ### [`4.7.1`](https://github.com/python/typing_extensions/releases/tag/4.7.1): 4.7.1 [Source](https://github.com/python/typing_extensions) Source ref: <code>main</code> - Fix support for `TypedDict`, `NamedTuple` and `is_protocol` on PyPy-3.7 and PyPy-3.8. Patch by Alex Waygood. Note that PyPy-3.7 and PyPy-3.8 are unsupported by the PyPy project. The next feature release of typing-extensions will drop support for PyPy-3.7 and may also drop support for PyPy-3.8. ### [`4.8.0`](https://github.com/python/typing_extensions/releases/tag/4.8.0): 4.8.0 [Source](https://github.com/python/typing_extensions) Source ref: <code>main</code> Changes since 4.7.1: - Add `typing_extensions.Doc`, as proposed by PEP 727. Patch by Sebastián Ramírez. - Drop support for Python 3.7 (including PyPy-3.7). Patch by Alex Waygood. - Fix bug where `get_original_bases()` would return incorrect results when called on a concrete subclass of a generic class. Patch by Alex Waygood (backporting https://github.com/python/cpython/pull/107584, by James Hilton-Balfe). - Fix bug where `ParamSpec(default=...)` would raise a `TypeError` on Python versions <3.11. Patch by James Hilton-Balfe No changes since 4.8.0rc1. ### [`4.9.0`](https://github.com/python/typing_extensions/releases/tag/4.9.0): 4.9.0 [Source](https://github.com/python/typing_extensions) Source ref: <code>main</code> This feature release adds `typing_extensions.ReadOnly`, as specified by PEP 705, and makes various other improvements, especially to `@typing_extensions.deprecated()`. There are no changes since 4.9.0rc1. ### [`4.10.0`](https://github.com/python/typing_extensions/releases/tag/4.10.0) [Source](https://github.com/python/typing_extensions) Source ref: <code>main</code> # Release 4.10.0 (February 25, 2024) This feature release adds support for PEP 728 (TypedDict with extra items) and PEP 742 (``TypeIs``). There are no changes since 4.10.0rc1. ### [`4.11.0`](https://github.com/python/typing_extensions/releases/tag/4.11.0): 4.11.0 [Source](https://github.com/python/typing_extensions) Source ref: <code>main</code> # Release 4.11.0 (April 5, 2024) This feature release provides improvements to various recently added features, most importantly type parameter defaults (PEP 696). There are no changes since 4.11.0rc1. Changes since 4.10.0: - Fix tests on Python 3.13.0a5. Patch by Jelle Zijlstra. - Fix the runtime behavior of type parameters with defaults (PEP 696). Patch by Nadir Chowdhury. - Fix minor discrepancy between error messages produced by `typing` and `typing_extensions` on Python 3.10. Patch by Jelle Zijlstra. - When `include_extra=False`, `get_type_hints()` now strips `ReadOnly` from the annotation. ### [`4.12.0`](https://github.com/python/typing_extensions/releases/tag/4.12.0): 4.12.0 [Source](https://github.com/python/typing_extensions) Source ref: <code>main</code> This release focuses on compatibility with the upcoming release of Python 3.13. Most changes are related to the implementation of type parameter defaults (PEP 696). Thanks to all of the people who contributed patches, especially Alex Waygood, who did most of the work adapting typing-extensions to the CPython PEP 696 implementation. There is a single change since 4.12.0rc1: - Fix incorrect behaviour of `typing_extensions.ParamSpec` on Python 3.8 and 3.9 that meant that `isinstance(typing_extensions.ParamSpec("P"), typing.TypeVar)` would have a different result in some situations depending on whether or not a profiling function had been set using `sys.setprofile`. Patch by Alex Waygood. Changes included in 4.12.0rc1: - Improve the implementation of type parameter defaults (PEP 696) - Backport the `typing.NoDefault` sentinel object from Python 3.13. TypeVars, ParamSpecs and TypeVarTuples without default values now have their `__default__` attribute set to this sentinel value. - TypeVars, ParamSpecs and TypeVarTuples now have a `has_default()` method, matching `typing.TypeVar`, `typing.ParamSpec` and `typing.TypeVarTuple` on Python 3.13+. - TypeVars, ParamSpecs and TypeVarTuples with `default=None` passed to their constructors now have their `__default__` attribute set to `None` at runtime rather than `types.NoneType`. - Fix most tests for `TypeVar`, `ParamSpec` and `TypeVarTuple` on Python 3.13.0b1 and newer. - Backport CPython PR [#118774](https://github.com/python/cpython/pull/118774), allowing type parameters without default values to follow those with default values in some type parameter lists. Patch by Alex Waygood, backporting a CPython PR by Jelle Zijlstra. - It is now disallowed to use a `TypeVar` with a default value after a `TypeVarTuple` in a type parameter list. This matches the CPython implementation of PEP 696 on Python 3.13+. - Fix bug in PEP-696 implementation where a default value for a `ParamSpec` would be cast to a tuple if a list was provided. Patch by Alex Waygood. - Fix `Protocol` tests on Python 3.13.0a6 and newer. 3.13.0a6 adds a new `__static_attributes__` attribute to all classes in Python, which broke some assumptions made by the implementation of `typing_extensions.Protocol`. Similarly, 3.13.0b1 adds the new `__firstlineno__` attribute to all classes. - Fix `AttributeError` when using `typing_extensions.runtime_checkable` in combination with `typing.Protocol` on Python 3.12.2 or newer. Patch by Alex Waygood. - At runtime, `assert_never` now includes the repr of the argument in the `AssertionError`. Patch by Hashem, backporting of the original fix https://github.com/python/cpython/pull/91720 by Jelle Zijlstra. - The second and third parameters of `typing_extensions.Generator`, and the second parameter of `typing_extensions.AsyncGenerator`, now default to `None`. This matches the behaviour of `typing.Generator` and `typing.AsyncGenerator` on Python 3.13+. - `typing_extensions.ContextManager` and `typing_extensions.AsyncContextManager` now have an optional second parameter, which defaults to `Optional[bool]`. The new parameter signifies the return type of the `__(a)exit__` method, matching `typing.ContextManager` and `typing.AsyncContextManager` on Python 3.13+. - Backport `types.CapsuleType` from Python 3.13. - Releases are now made using [Trusted Publishers](https://docs.pypi.org/trusted-publishers/) improving the security of the release process. Patch by Jelle Zijlstra. ### [`4.12.1`](https://github.com/python/typing_extensions/releases/tag/4.12.1): 4.12.1 [Source](https://github.com/python/typing_extensions) Source ref: <code>main</code> - Preliminary changes for compatibility with the draft implementation of PEP 649 in Python 3.14. Patch by Jelle Zijlstra. - Fix regression in v4.12.0 where nested `Annotated` types would cause `TypeError` to be raised if the nested `Annotated` type had unhashable metadata. Patch by Alex Waygood. ### [`4.12.2`](https://github.com/python/typing_extensions/releases/tag/4.12.2): 4.12.2 [Source](https://github.com/python/typing_extensions) Source ref: <code>main</code> - Fix regression in v4.12.0 where specialization of certain generics with an overridden `__eq__` method would raise errors. Patch by Jelle Zijlstra. - Fix tests so they pass on 3.13.0b2 ### [`4.13.0`](https://github.com/python/typing_extensions/releases/tag/4.13.0) [Source](https://github.com/python/typing_extensions) Source ref: <code>main</code> New features: - Add `typing_extensions.TypeForm` from PEP 747. Patch by Jelle Zijlstra. - Add `typing_extensions.get_annotations`, a backport of `inspect.get_annotations` that adds features specified by PEP 649. Patches by Jelle Zijlstra and Alex Waygood. - Backport `evaluate_forward_ref` from CPython PR [#119891](https://github.com/python/cpython/pull/119891) to evaluate `ForwardRef`s. Patch by [Daraan](https://github.com/Daraan), backporting a CPython PR by Jelle Zijlstra. Bugfixes and changed features: - Update PEP 728 implementation to a newer version of the PEP. Patch by Jelle Zijlstra. - Copy the coroutine status of functions and methods wrapped with `@typing_extensions.deprecated`. Patch by Sebastian Rittau. - Fix bug where `TypeAliasType` instances could be subscripted even where they were not generic. Patch by [Daraan](https://github.com/Daraan). - Fix bug where a subscripted `TypeAliasType` instance did not have all attributes of the original `TypeAliasType` instance on older Python versions. Patch by [Daraan](https://github.com/Daraan) and Alex Waygood. - Fix bug where subscripted `TypeAliasType` instances (and some other subscripted objects) had wrong parameters if they were directly subscripted with an `Unpack` object. Patch by [Daraan](https://github.com/Daraan). - Backport to Python 3.10 the ability to substitute `...` in generic `Callable` aliases that have a `Concatenate` special form as their argument. Patch by [Daraan](https://github.com/Daraan). - Extended the `Concatenate` backport for Python 3.8-3.10 to now accept `Ellipsis` as an argument. Patch by [Daraan](https://github.com/Daraan). - Fix backport of `get_type_hints` to reflect Python 3.11+ behavior which does not add `Union[..., NoneType]` to annotations that have a `None` default value anymore. This fixes wrapping of `Annotated` in an unwanted `Optional` in such cases. Patch by [Daraan](https://github.com/Daraan). - Fix error in subscription of `Unpack` aliases causing nested Unpacks to not be resolved correctly. Patch by [Daraan](https://github.com/Daraan). - Backport CPython PR [#124795](https://github.com/python/cpython/pull/124795): fix `TypeAliasType` not raising an error on non-tuple inputs for `type_params`. Patch by [Daraan](https://github.com/Daraan). - Fix that lists and `...` could not be used for parameter expressions for `TypeAliasType` instances before Python 3.11. Patch by [Daraan](https://github.com/Daraan). - Fix error on Python 3.10 when using `typing.Concatenate` and `typing_extensions.Concatenate` together. Patch by [Daraan](https://github.com/Daraan). - Backport of CPython PR [#109544](https://github.com/python/cpython/pull/109544) to reflect Python 3.13+ behavior: A value assigned to `__total__` in the class body of a `TypedDict` will be overwritten by the `total` argument of the `TypedDict` constructor. Patch by [Daraan](https://github.com/Daraan), backporting a CPython PR by Jelle Zijlstra. - `isinstance(typing_extensions.Unpack[...], TypeVar)` now evaluates to `False` on Python 3.11 and newer, but remains `True` on versions before 3.11. Patch by [Daraan](https://github.com/Daraan). ### [`4.13.1`](https://github.com/python/typing_extensions/releases/tag/4.13.1) [Source](https://github.com/python/typing_extensions) Source ref: <code>main</code> This is a bugfix release fixing two edge cases that appear on old bugfix releases of CPython. Bugfixes: - Fix regression in 4.13.0 on Python 3.10.2 causing a `TypeError` when using `Concatenate`. Patch by [Daraan](https://github.com/Daraan). - Fix `TypeError` when using `evaluate_forward_ref` on Python 3.10.1-2 and 3.9.8-10. Patch by [Daraan](https://github.com/Daraan). ### [`4.13.2`](https://github.com/python/typing_extensions/releases/tag/4.13.2) [Source](https://github.com/python/typing_extensions) Source ref: <code>main</code> - Fix `TypeError` when taking the union of `typing_extensions.TypeAliasType` and a `typing.TypeAliasType` on Python 3.12 and 3.13. Patch by [Joren Hammudoglu](https://github.com/jorenham). - Backport from CPython PR [#132160](https://github.com/python/cpython/pull/132160) to avoid having user arguments shadowed in generated `__new__` by `@typing_extensions.deprecated`. Patch by [Victorien Plot](https://github.com/Viicos). ### [`4.14.0`](https://github.com/python/typing_extensions/releases/tag/4.14.0) [Source](https://github.com/python/typing_extensions) Source ref: <code>main</code> This release adds several new features, including experimental support for inline typed dictionaries ([PEP 764](https://peps.python.org/pep-0764/)) and sentinels ([PEP 661](https://peps.python.org/pep-0661/)), and support for changes in Python 3.14. In addition, Python 3.8 is no longer supported. Changes since 4.14.0rc1: - Remove `__or__` and `__ror__` methods from `typing_extensions.Sentinel` on Python versions <3.10. PEP 604 was introduced in Python 3.10, and `typing_extensions` does not generally attempt to backport PEP-604 methods to prior versions. - Further update `typing_extensions.evaluate_forward_ref` with changes in Python 3.14. Changes included in 4.14.0rc1: - Drop support for Python 3.8 (including PyPy-3.8). Patch by [Victorien Plot](https://github.com/Viicos). - Do not attempt to re-export names that have been removed from `typing`, anticipating the removal of `typing.no_type_check_decorator` in Python 3.15. Patch by Jelle Zijlstra. - Update `typing_extensions.Format`, `typing_extensions.evaluate_forward_ref`, and `typing_extensions.TypedDict` to align with changes in Python 3.14. Patches by Jelle Zijlstra. - Fix tests for Python 3.14 and 3.15. Patches by Jelle Zijlstra. New features: - Add support for inline typed dictionaries ([PEP 764](https://peps.python.org/pep-0764/)). Patch by [Victorien Plot](https://github.com/Viicos). - Add `typing_extensions.Reader` and `typing_extensions.Writer`. Patch by Sebastian Rittau. - Add support for sentinels ([PEP 661](https://peps.python.org/pep-0661/)). Patch by [Victorien Plot](https://github.com/Viicos). ### [`4.14.1`](https://github.com/python/typing_extensions/releases/tag/4.14.1) [Source](https://github.com/python/typing_extensions) Source ref: <code>main</code> # Release 4.14.1 (July 4, 2025) - Fix usage of `typing_extensions.TypedDict` nested inside other types (e.g., `typing.Type[typing_extensions.TypedDict]`). This is not allowed by the type system but worked on older versions, so we maintain support. ### [`4.15.0`](https://github.com/python/typing_extensions/releases/tag/4.15.0): 4.15.0 [Source](https://github.com/python/typing_extensions) Source ref: <code>main</code> No user-facing changes since 4.15.0rc1. New features since 4.14.1: - Add the `@typing_extensions.disjoint_base` decorator, as specified in PEP 800. Patch by Jelle Zijlstra. - Add `typing_extensions.type_repr`, a backport of [`annotationlib.type_repr`](https://docs.python.org/3.14/library/annotationlib.html#annotationlib.type_repr), introduced in Python 3.14 (CPython PR [#124551](https://github.com/python/cpython/pull/124551), originally by Jelle Zijlstra). Patch by Semyon Moroz. - Fix behavior of type params in `typing_extensions.evaluate_forward_ref`. Backport of CPython PR [#137227](https://github.com/python/cpython/pull/137227) by Jelle Zijlstra. ### [`4.16.0`](https://github.com/python/typing_extensions/releases/tag/4.16.0): 4.16.0 [Source](https://github.com/python/typing_extensions) Source ref: <code>main</code> No changes since 4.16.0rc2. Changes since 4.15.0: - Make `typing_extensions.TypeAliasType`'s `__module__` attribute writable. Backport of CPython PR [#149172](https://github.com/python/cpython/pull/149172). - Fix setting of `__required_keys__` and `__optional_keys__` when inheriting keys with the same name. - Add support for `AsyncIterator`, `io.Reader`, `io.Writer` and `os.PathLike` protocols as bases for other protocols. - Fix incorrect behaviour on Python 3.9 and Python 3.10 that meant that calling `isinstance` with `typing_extensions.Concatenate[...]` or `typing_extensions.Unpack[...]` as the first argument could have a different result in some situations depending on whether or not a profiling function had been set using `sys.setprofile`. This affected both CPython and PyPy implementations. Patch by Brian Schubert. - Fix `__init_subclass__()` behavior in the presence of multiple inheritance involving an `@deprecated`-decorated base class. Backport of CPython PR [#138210](https://github.com/python/cpython/pull/138210) by Brian Schubert. - Raise `TypeError` when attempting to subclass `typing_extensions.ParamSpec` on Python 3.9. The `typing` implementation has always raised an error, and the `typing_extensions` implementation has raised an error on Python 3.10+ since `typing_extensions` v4.6.0. Patch by Brian Schubert. - Add the `bound`, `covariant`, `contravariant`, and `infer_variance` parameters to `TypeVarTuple`. - Officially support the `bound`, `covariant`, `contravariant` and `infer_variance` parameters to `ParamSpec`. Improve the validation of these parameters at runtime. - Rename `typing_extensions.Sentinel` to `typing_extensions.sentinel`, following the name that has been adopted for `builtins.sentinel` on Python 3.15. `typing_extensions.Sentinel` is retained as a soft-deprecated alias for backwards compatibility. - Add support for pickling sentinels. - Sentinels now preserve their identity when copied or deep-copied. - Deprecate passing `name` as a keyword argument or `repr` as a positional argument to the `sentinel` constructor. - The default repr of a sentinel `X = sentinel("X")` is now `X` rather than `<X>`. - Deprecate arbitrary attribute assignments to sentinels. - Deprecate subclassing sentinels. - Add support for Python 3.15. - Avoid a `DeprecationWarning` when `deprecated` is applied to a coroutine function on Python 3.14.0. </details> <details> <summary>watchfiles (1.2.0 → 1.3.0)</summary> ### [`1.3.0`](https://github.com/samuelcolvin/watchfiles/releases/tag/v1.3.0): v1.3.0 2026-09-21 [Compare source](https://github.com/samuelcolvin/watchfiles/compare/v1.2.0...v1.3.0) [Source](https://github.com/samuelcolvin/watchfiles) Source ref: <code>main</code> ## What's Changed * Bump pyo3 from 0.28.3 to 0.29.0 by @dependabot[bot] in https://github.com/samuelcolvin/watchfiles/pull/382 * Add Python 3.14t to Windows wheel builds by @1998LJ in https://github.com/samuelcolvin/watchfiles/pull/393 * Build abi3 wheels for CPython by @samuelcolvin in https://github.com/samuelcolvin/watchfiles/pull/396 * prep v1.3.0 release by @samuelcolvin in https://github.com/samuelcolvin/watchfiles/pull/397 ## New Contributors * @1998LJ made their first contribution in https://github.com/samuelcolvin/watchfiles/pull/393 **Full Changelog**: https://github.com/samuelcolvin/watchfiles/compare/v1.2.0...v1.3.0 </details> <details> <summary>yarl (1.22.0 → 1.25.1)</summary> Source comparison unavailable: source refs for this transition are not known. ### `1.23.0` ### `1.24.2` ### `1.24.5` ### `1.25.1` </details>
chore: update Python dependencies (uv.lock) (14 updates)
Some checks failed
CI / Quality (pull_request) Failing after 1m39s
57480ee476
Wuast94 force-pushed updatarr/python-dependencies--uv.lock-bbfe89acc5 from 57480ee476
Some checks failed
CI / Quality (pull_request) Failing after 1m39s
to 6e1306e940
Some checks failed
CI / Quality (pull_request) Failing after 1m1s
2026-09-28 18:44:34 +02:00
Compare
fix: satisfy updated Ruff checks and formatting
All checks were successful
CI / Quality (pull_request) Successful in 26s
6dc0f22ff0
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Wuast94/pypypew!6
No description provided.