changelogs/0.4.x.md
Ruff's new parser is >2x faster, which translates to a 20-40% speedup for all linting and formatting invocations. There's a lot to say about this exciting change, so check out the blog post for more details!
See #10036 for implementation details.
With this release, we also want to highlight our new language server. ruff server is a Rust-powered language
server that comes built-in with Ruff. It can be used with any editor that supports the Language Server Protocol (LSP).
It uses a multi-threaded, lock-free architecture inspired by rust-analyzer and it will open the door for a lot
of exciting features. It’s also faster than our previous Python-based language server
-- but you probably guessed that already.
ruff server is only in alpha, but it has a lot of features that you can try out today:
ruff.applyAutofix, ruff.applyFormat, and ruff.applyOrganizeImportssource.fixAll and source.organizeImports source actionsTo setup ruff server with your editor, refer to the README.md.
pycodestyle] Do not trigger E3 rules on defs following a function/method with a dummy body (#10704)pylint] Implement invalid-bytes-returned (E0308) (#10959)pylint] Implement invalid-length-returned (E0303) (#10963)pylint] Implement self-cls-assignment (W0642) (#9267)pylint] Omit stubs from invalid-bool and invalid-str-return-type (#11008)ruff] New rule unused-async (RUF029) to detect unneeded async keywords on functions (#9966)flake8-bandit] Allow urllib.request.urlopen calls with static Request argument (S310) (#10964)flake8-bugbear] Treat raise NotImplemented-only bodies as stub functions (B006) (#10990)flake8-slots] Respect same-file Enum subclasses (SLOT000) (#11006)pylint] Support inverted comparisons (PLR1730) (#10920)--show-settings (#11003)BuiltinTypeChecker (#10976)RuleTable::any_enabled (#10971)This section is devoted to updates for our new language server, written in Rust.
RUFF_OUTPUT_FILE environment variable support (#10992)non-augmented-assignment for reversed, non-commutative operators (PLR6104) (#10909)PLR6104) (#10912)per-file-ignores for RUF100 on blanket # noqa (#10908)if expression for parenthesized with items parsing (#11010)FOR_TARGET context for all kinds of parentheses (#11009)pylint] Implement invalid-hash-returned (PLE0309) (#10961)pylint] Implement invalid-index-returned (PLE0305) (#10962)pylint] Allow NoReturn-like functions for __str__, __len__, etc. (PLE0307) (#11017)ruff] Ignore stub functions in unused-async (RUF029) (#11026)flake8-pyi] Allow for overloaded __exit__ and __aexit__ definitions (PYI036) (#11057)pyupgrade] Catch usages of "%s" % var and provide an unsafe fix (UP031) (#11019)refurb] Implement new rule that suggests min/max over sorted() (FURB192) (#10868)noqa codes (#11096)macos-12 for building release wheels to enable macOS 11 compatibility (#11146)flake8-blind-expect] Allow raise from in BLE001 (#11131)flake8-pyi] Allow simple assignments to None in enum class scopes (PYI026) (#11128)flake8-simplify] Avoid raising SIM911 for non-zip attribute calls (#11126)refurb] Avoid operator.itemgetter suggestion for single-item tuple (#11095)ruff] Respect per-file-ignores for RUF100 with no other diagnostics (#11058)ruff] Fix async comprehension false positive (RUF029) (#11070)flake8-bugbear] Document explicitly disabling strict zip (B905) (#11040)flake8-type-checking] Mention lint.typing-modules in TCH001, TCH002, and TCH003 (#11144)isort] Improve documentation around custom isort sections (#11050)pylint] Fix documentation oversight for invalid-X-returns (#11094)matchit to resolve per-file settings (#11111)refurb] Use function range for reimplemented-operator diagnostics (#11271)refurb] Ignore methods in reimplemented-operator (FURB118) (#11270)refurb] Implement fstring-number-format (FURB116) (#10921)ruff] Implement redirected-noqa (RUF101) (#11052)pyflakes] Distinguish between first-party and third-party imports for fix suggestions (#11168)flake8-bugbear] Ignore non-abstract class attributes when enforcing B024 (#11210)flake8-logging] Include inline instantiations when detecting loggers (#11154)pylint] Also emit PLR0206 for properties with variadic parameters (#11200)ruff] Detect duplicate codes as part of unused-noqa (RUF100) (#10850)ruff server setup guide for Helix (#11183)ruff server no longer hangs after shutdown (#11222)ruff server reads from a configuration TOML file in the user configuration directory if no local configuration exists (#11225)ruff server respects per-file-ignores configuration (#11224)ruff server: Support a custom TOML configuration file (#11140)ruff server: Support setting to prioritize project configuration over editor configuration (#11086)pyflakes] Prioritize redefined-while-unused over unused-import (#11173)ruff] Respect async expressions in comprehension bodies (#11219)pygrep_hooks] Fix blanket-noqa panic when last line has noqa with no newline (PGH004) (#11108)perflint] Ignore list-copy recommendations for async for loops (#11250)pyflakes] Improve invalid-print-syntax documentation (#11171)pycodestyle] Ignore end-of-line comments when determining blank line rules (#11342)pylint] Detect pathlib.Path.open calls in unspecified-encoding (PLW1514) (#11288)flake8-pyi] Implement PYI059 (generic-not-last-base-class) (#11233)flake8-pyi] Implement PYI062 (duplicate-literal-member) (#11269)flake8-boolean-trap] Allow passing booleans as positional-only arguments in code such as set(True) (#11287)flake8-bugbear] Ignore enum classes in cached-instance-method (B019) (#11312)ruff server hanging after Neovim closes (#11291)pylint] Consider with statements for too-many-branches (PLR0912) (#11321)flake8-blind-except, tryceratops] Respect logged and re-raised expressions in nested statements (BLE001, TRY201) (#11301)__all__ = builtins.list(["foo", "bar"]) as valid __all__ definitions (#11335)v0.4.5 marks the official Beta release of ruff server, an integrated language server built into Ruff.
ruff server supports the same feature set as ruff-lsp, powering linting, formatting, and
code fixes in Ruff's editor integrations -- but with superior performance and
no installation required. We'd love your feedback!
You can enable ruff server in the VS Code extension today.
To read more about this exciting milestone, check out our blog post!
flake8-future-annotations] Reword future-rewritable-type-annotation (FA100) message (#11381)isort] Expanded the set of standard-library modules to include _string, etc. (#11374)pycodestyle] Consider soft keywords for E27 rules (#11446)pyflakes] Recommend adding unused import bindings to __all__ (#11314)pyflakes] Update documentation and deprecate ignore_init_module_imports (#11436)pyupgrade] Mark quotes as unnecessary for non-evaluated annotations (#11485)quote-style = preserve (#11490)noqa comment code actions (#11276)--output-format as a CLI option for ruff config (#11438)PLE0237 for property with setter (#11377)TCH005 for if stmt with elif/else block (#11376)__future__ annotations as required for non-evaluated type annotations (#11414)flake8-pie] Preserve parentheses in unnecessary-dict-kwargs (#11372)pylint] Ignore __slots__ with dynamic values (#11488)pylint] Remove try body from branch counting (#11487)refurb] Respect operator precedence in FURB110 (#11464)--preview to the README (#11395)pycodestyle] Clarify motivation for E713 and E714 (#11483)pyflakes] Update docs to describe WAI behavior (F541) (#11362)pylint] Clearly indicate what is counted as a branch (#11423)flake8-async] Sleep with >24 hour interval should usually sleep forever (ASYNC116) (#11498)numpy] Add missing functions to NumPy 2.0 migration rule (#11528)mccabe] Consider irrefutable pattern similar to if .. else for C901 (#11565)match-case statements for C901, PLR0912, and PLR0915 (#11521)UP032) (#11524)flake8-bandit] request-without-timeout should warn for requests.request (#11548)flake8-self] Ignore sunder accesses in flake8-self rules (#11546)pyupgrade] Lint for TypeAliasType usages (UP040) (#11530)ruff server configuration discovery (#11551)ruff server correctly treats .pyi files as stub files (#11535)ruff server searches for configuration in parent directories (#11537)ruff server: An empty code action filter no longer returns notebook source actions (#11526)flake8-logging-format] Fix autofix title in logging-warn (G010) (#11514)refurb] Avoid recommending operator.itemgetter with dependence on lambda arguments (#11574)flake8-simplify] Avoid recommending context manager in __enter__ implementations (#11575)--output-file (#11550)singledispatch arguments as runtime-required (#11523)flake8-pyi] Implement PYI064 (#11325)flake8-pyi] Implement PYI066 (#11541)flake8-pyi] Implement PYI057 (#11486)pyflakes] Enable F822 in __init__.py files by default (#11370)ruff server (#11590)ruff server (#11615)flake8-comprehension] Strip parentheses around generators in C400 (#11607)repeated-isinstance-calls as unsafe on Python 3.10 and later (#11622)flake8-bugbear] Implement return-in-generator (B901) (#11644)flake8-pyi] Implement pep484-style-positional-only-parameter (PYI063) (#11699)pygrep_hooks] Check blanket ignores via file-level pragmas (PGH004) (#11540)pyupgrade] Update UP035 for Python 3.13 and the latest version of typing_extensions (#11693)numpy] Update NPY001 rule for NumPy 2.0 (#11735)--output-format flag (#11682)pyupgrade] Write empty string in lieu of panic when fixing UP032 (#11696)flake8-simplify] Simplify double negatives in SIM103 (#11684)type statements (#11720)pylint] Implement consider-dict-items (C0206) (#11688)refurb] Implement repeated-global (FURB154) (#11187)pycodestyle] Adapt fix for E203 to work identical to ruff format (#10999)ruff server (#11800)ruff.printDebugInformation command (#11831)refurb] Avoid suggesting starmap when arguments are used outside call (FURB140) (#11830)flake8-bugbear] Avoid panic in B909 when checking large loop blocks (#11772)refurb] Fix misbehavior of operator.itemgetter when getter param is a tuple (FURB118) (#11774)flake8-copyright] Update CPY001 to check the first 4096 bytes instead of 1024 (#11927)pycodestyle] Update E999 to show all syntax errors instead of just the first one (#11900)