From a17b202b01f586ff8be3cb89414ef14b59db0cf1 Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Wed, 10 Apr 2024 15:35:19 -0700 Subject: [PATCH 1/8] Implement ruff executable search for the new experimental server --- bundled/tool/ruff_server.py | 89 +++++++++++++++++++++++++++++++++++++ src/common/constants.ts | 6 ++- src/common/server.ts | 34 +++++++++----- 3 files changed, 118 insertions(+), 11 deletions(-) create mode 100644 bundled/tool/ruff_server.py diff --git a/bundled/tool/ruff_server.py b/bundled/tool/ruff_server.py new file mode 100644 index 0000000..55c9cfb --- /dev/null +++ b/bundled/tool/ruff_server.py @@ -0,0 +1,89 @@ +import os +import shutil +import site +import subprocess +import sys +import sysconfig +from pathlib import Path + +RUFF_EXE = "ruff.exe" if sys.platform == "win32" else "ruff" + +BUNDLE_DIR = Path(__file__).parent.parent + + +def update_sys_path(path_to_add: str) -> None: + """Add given path to `sys.path`.""" + if os.path.isdir(path_to_add): + # The `site` module adds the directory at the end, if not yet present; we want + # it to be at the beginning, so that it takes precedence over any other + # installed versions. + sys.path.insert(0, path_to_add) + + # Allow development versions of libraries to be imported. + site.addsitedir(path_to_add) + + +if __name__ == "__main__": + # Ensure that we can import bundled libraries like `packaging` + update_sys_path(os.fspath(BUNDLE_DIR / "libs")) + + +from packaging.specifiers import SpecifierSet +from packaging.version import Version + +# This is the first release that included `ruff server`. +# The minimum version may change in the future. +RUFF_VERSION_REQUIREMENT = SpecifierSet(">=0.3.3") +# These versions have major bugs or broken integration, and should be avoided. +FORBIDDEN_RUFF_VERSIONS = [Version("0.3.4")] + + +def executable_version(executable: str) -> Version: + """Return the version of the executable at the given path.""" + output = subprocess.check_output([executable, "--version"]).decode().strip() + version = output.replace("ruff ", "") + return Version(version) + + +def check_compatibility( + executable: str, + requirement: SpecifierSet, + forbidden_requirements: SpecifierSet, +) -> None: + """Check the executable for compatibility against various version specifiers.""" + version = executable_version(executable) + if not requirement.contains(version, prereleases=True): + message = f"Ruff {requirement} required, but found {version} at {executable}" + raise RuntimeError(message) + for forbidden in forbidden_requirements: + if version == forbidden: + message = ( + f"Tried to use Ruff version {version} at {executable}, which is not allowed.\n" + "This version of the server has incompatibilities and/or integration-breaking bugs.\n" + "Please upgrade to the latest version and try again." + ) + raise RuntimeError(message) + + +def find_ruff_bin(fallback: Path) -> Path: + """Return the ruff binary path.""" + path = Path(sysconfig.get_path("scripts")) / RUFF_EXE + if path.is_file(): + return path + + path = shutil.which("ruff") + if path: + return path + + return fallback + + +if __name__ == "__main__": + ruff = os.fsdecode( + find_ruff_bin( + Path(BUNDLE_DIR / "libs" / "bin" / RUFF_EXE), + ), + ) + check_compatibility(ruff, RUFF_VERSION_REQUIREMENT, FORBIDDEN_RUFF_VERSIONS) + completed_process = subprocess.run([ruff, *sys.argv[1:]], check=False) + sys.exit(completed_process.returncode) diff --git a/src/common/constants.ts b/src/common/constants.ts index 6e7205b..0f7351c 100644 --- a/src/common/constants.ts +++ b/src/common/constants.ts @@ -10,6 +10,10 @@ export const DEBUG_SERVER_SCRIPT_PATH = path.join( "tool", `_debug_server.py`, ); -export const RUFF_BIN_PATH = path.join(BUNDLED_PYTHON_SCRIPTS_DIR, "libs", "bin", "ruff"); +export const NEW_SERVER_SCRIPT_PATH = path.join( + BUNDLED_PYTHON_SCRIPTS_DIR, + "tool", + "ruff_server.py", +); export const RUFF_SERVER_CMD = "server"; export const RUFF_SERVER_REQUIRED_ARGS = ["--preview"]; diff --git a/src/common/server.ts b/src/common/server.ts index 5dce35a..79779fe 100644 --- a/src/common/server.ts +++ b/src/common/server.ts @@ -10,10 +10,10 @@ import { import { BUNDLED_PYTHON_SCRIPTS_DIR, DEBUG_SERVER_SCRIPT_PATH, - RUFF_BIN_PATH, RUFF_SERVER_REQUIRED_ARGS, RUFF_SERVER_CMD, SERVER_SCRIPT_PATH, + NEW_SERVER_SCRIPT_PATH, } from "./constants"; import { traceError, traceInfo, traceVerbose } from "./log/logging"; import { getDebuggerPath } from "./python"; @@ -39,17 +39,31 @@ async function createExperimentalServer( outputChannel: LogOutputChannel, initializationOptions: IInitOptions, ): Promise { - const command = RUFF_BIN_PATH; - const cwd = settings.cwd; - const args = [RUFF_SERVER_CMD, ...RUFF_SERVER_REQUIRED_ARGS]; + let serverOptions: ServerOptions; + if (settings.path.length > 0 && settings.path[0]) { + const command = settings.path[0]; + const cwd = settings.cwd; + const args = [RUFF_SERVER_CMD, ...RUFF_SERVER_REQUIRED_ARGS]; + serverOptions = { + command, + args, + options: { cwd, env: process.env }, + }; + + traceInfo(`Server run command: ${[command, ...args].join(" ")}`); + } else { + const command = settings.interpreter[0]; + const cwd = settings.cwd; + const args = [NEW_SERVER_SCRIPT_PATH, RUFF_SERVER_CMD, ...RUFF_SERVER_REQUIRED_ARGS]; - const serverOptions: ServerOptions = { - command, - args, - options: { cwd, env: process.env }, - }; + serverOptions = { + command, + args, + options: { cwd, env: process.env }, + }; - traceInfo(`Server run command: ${[command, ...args].join(" ")}`); + traceInfo(`Server run command: ${[command, ...args].join(" ")}`); + } const clientOptions = { // Register the server for python documents From 339000b772a2b7bd7471bbf35428a4b4e2386b04 Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Wed, 10 Apr 2024 22:13:17 -0700 Subject: [PATCH 2/8] Check the user install scheme if sysconfig.get_path('scripts') is not available --- bundled/tool/ruff_server.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/bundled/tool/ruff_server.py b/bundled/tool/ruff_server.py index 55c9cfb..2e188f8 100644 --- a/bundled/tool/ruff_server.py +++ b/bundled/tool/ruff_server.py @@ -71,6 +71,19 @@ def find_ruff_bin(fallback: Path) -> Path: if path.is_file(): return path + if sys.version_info >= (3, 10): + user_scheme = sysconfig.get_preferred_scheme("user") + elif os.name == "nt": + user_scheme = "nt_user" + elif sys.platform == "darwin" and sys._framework: + user_scheme = "osx_framework_user" + else: + user_scheme = "posix_user" + + path = Path(sysconfig.get_path("scripts", scheme=user_scheme)) / RUFF_EXE + if path.is_file(): + return path + path = shutil.which("ruff") if path: return path From f72f03e1829fe6984fb53010bbfda7fc4634d579 Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Wed, 10 Apr 2024 22:13:53 -0700 Subject: [PATCH 3/8] Rename script path constant --- src/common/constants.ts | 2 +- src/common/server.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/constants.ts b/src/common/constants.ts index 0f7351c..2f7a238 100644 --- a/src/common/constants.ts +++ b/src/common/constants.ts @@ -10,7 +10,7 @@ export const DEBUG_SERVER_SCRIPT_PATH = path.join( "tool", `_debug_server.py`, ); -export const NEW_SERVER_SCRIPT_PATH = path.join( +export const EXPERIMENTAL_SERVER_SCRIPT_PATH = path.join( BUNDLED_PYTHON_SCRIPTS_DIR, "tool", "ruff_server.py", diff --git a/src/common/server.ts b/src/common/server.ts index 79779fe..e66c958 100644 --- a/src/common/server.ts +++ b/src/common/server.ts @@ -13,7 +13,7 @@ import { RUFF_SERVER_REQUIRED_ARGS, RUFF_SERVER_CMD, SERVER_SCRIPT_PATH, - NEW_SERVER_SCRIPT_PATH, + EXPERIMENTAL_SERVER_SCRIPT_PATH, } from "./constants"; import { traceError, traceInfo, traceVerbose } from "./log/logging"; import { getDebuggerPath } from "./python"; @@ -54,7 +54,7 @@ async function createExperimentalServer( } else { const command = settings.interpreter[0]; const cwd = settings.cwd; - const args = [NEW_SERVER_SCRIPT_PATH, RUFF_SERVER_CMD, ...RUFF_SERVER_REQUIRED_ARGS]; + const args = [EXPERIMENTAL_SERVER_SCRIPT_PATH, RUFF_SERVER_CMD, ...RUFF_SERVER_REQUIRED_ARGS]; serverOptions = { command, From edd105aa84ac35da20fdd0a408452a5368eeec4b Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Wed, 10 Apr 2024 22:24:54 -0700 Subject: [PATCH 4/8] Describe the branches in createExperimentalServer --- src/common/server.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/common/server.ts b/src/common/server.ts index e66c958..76364c2 100644 --- a/src/common/server.ts +++ b/src/common/server.ts @@ -40,6 +40,7 @@ async function createExperimentalServer( initializationOptions: IInitOptions, ): Promise { let serverOptions: ServerOptions; + // If the user provided a binary path, we'll try to call that path directly. if (settings.path.length > 0 && settings.path[0]) { const command = settings.path[0]; const cwd = settings.cwd; @@ -52,6 +53,8 @@ async function createExperimentalServer( traceInfo(`Server run command: ${[command, ...args].join(" ")}`); } else { + // Otherwise, we'll call a Python script that tries to locate + // a binary, falling back to the bundled version if no local executable is found. const command = settings.interpreter[0]; const cwd = settings.cwd; const args = [EXPERIMENTAL_SERVER_SCRIPT_PATH, RUFF_SERVER_CMD, ...RUFF_SERVER_REQUIRED_ARGS]; From 126602a4a19c57caf5d2f96ea63aceaffa8892b9 Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Wed, 10 Apr 2024 22:39:55 -0700 Subject: [PATCH 5/8] Bump minimum required version to v0.3.5 --- bundled/tool/ruff_server.py | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/bundled/tool/ruff_server.py b/bundled/tool/ruff_server.py index 2e188f8..a7bbf5c 100644 --- a/bundled/tool/ruff_server.py +++ b/bundled/tool/ruff_server.py @@ -31,11 +31,8 @@ def update_sys_path(path_to_add: str) -> None: from packaging.specifiers import SpecifierSet from packaging.version import Version -# This is the first release that included `ruff server`. -# The minimum version may change in the future. -RUFF_VERSION_REQUIREMENT = SpecifierSet(">=0.3.3") -# These versions have major bugs or broken integration, and should be avoided. -FORBIDDEN_RUFF_VERSIONS = [Version("0.3.4")] +# This is subject to change in the future +RUFF_VERSION_REQUIREMENT = SpecifierSet(">=0.3.5") def executable_version(executable: str) -> Version: @@ -48,21 +45,12 @@ def executable_version(executable: str) -> Version: def check_compatibility( executable: str, requirement: SpecifierSet, - forbidden_requirements: SpecifierSet, ) -> None: """Check the executable for compatibility against various version specifiers.""" version = executable_version(executable) if not requirement.contains(version, prereleases=True): message = f"Ruff {requirement} required, but found {version} at {executable}" raise RuntimeError(message) - for forbidden in forbidden_requirements: - if version == forbidden: - message = ( - f"Tried to use Ruff version {version} at {executable}, which is not allowed.\n" - "This version of the server has incompatibilities and/or integration-breaking bugs.\n" - "Please upgrade to the latest version and try again." - ) - raise RuntimeError(message) def find_ruff_bin(fallback: Path) -> Path: @@ -97,6 +85,6 @@ def find_ruff_bin(fallback: Path) -> Path: Path(BUNDLE_DIR / "libs" / "bin" / RUFF_EXE), ), ) - check_compatibility(ruff, RUFF_VERSION_REQUIREMENT, FORBIDDEN_RUFF_VERSIONS) + check_compatibility(ruff, RUFF_VERSION_REQUIREMENT) completed_process = subprocess.run([ruff, *sys.argv[1:]], check=False) sys.exit(completed_process.returncode) From 7dad2d1af6d175ac0e2b75273aa11ce675ac294d Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Thu, 11 Apr 2024 11:53:15 -0700 Subject: [PATCH 6/8] Simplify clause checking for Ruff path --- src/common/server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/server.ts b/src/common/server.ts index 76364c2..dc55c7c 100644 --- a/src/common/server.ts +++ b/src/common/server.ts @@ -41,7 +41,7 @@ async function createExperimentalServer( ): Promise { let serverOptions: ServerOptions; // If the user provided a binary path, we'll try to call that path directly. - if (settings.path.length > 0 && settings.path[0]) { + if (settings.path[0]) { const command = settings.path[0]; const cwd = settings.cwd; const args = [RUFF_SERVER_CMD, ...RUFF_SERVER_REQUIRED_ARGS]; From 0d3eaa61841c3e362a663a8d52a91aea8183f978 Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Thu, 11 Apr 2024 11:54:38 -0700 Subject: [PATCH 7/8] Explain why `ruff_server.py` uses a split main block --- bundled/tool/ruff_server.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bundled/tool/ruff_server.py b/bundled/tool/ruff_server.py index a7bbf5c..e606d19 100644 --- a/bundled/tool/ruff_server.py +++ b/bundled/tool/ruff_server.py @@ -23,6 +23,8 @@ def update_sys_path(path_to_add: str) -> None: site.addsitedir(path_to_add) +# This is separate from the 'main' entrypoint because we need +# to update the system path _before_ importing `pacakging` if __name__ == "__main__": # Ensure that we can import bundled libraries like `packaging` update_sys_path(os.fspath(BUNDLE_DIR / "libs")) From c08ff5e35db80ce9c5cb2785dcc006d0b0a8ab51 Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Thu, 11 Apr 2024 12:14:12 -0700 Subject: [PATCH 8/8] Bump Ruff version to v0.3.6 --- README.md | 10 +++++----- pyproject.toml | 2 +- requirements-dev.txt | 36 ++++++++++++++++++------------------ requirements.txt | 36 ++++++++++++++++++------------------ 4 files changed, 42 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 382768a..f7ef536 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # Ruff extension for Visual Studio Code [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) -[![image](https://img.shields.io/pypi/v/ruff/0.3.3.svg)](https://pypi.python.org/pypi/ruff) -[![image](https://img.shields.io/pypi/l/ruff/0.3.3.svg)](https://pypi.python.org/pypi/ruff) -[![image](https://img.shields.io/pypi/pyversions/ruff/0.3.3.svg)](https://pypi.python.org/pypi/ruff) +[![image](https://img.shields.io/pypi/v/ruff/0.3.6.svg)](https://pypi.python.org/pypi/ruff) +[![image](https://img.shields.io/pypi/l/ruff/0.3.6.svg)](https://pypi.python.org/pypi/ruff) +[![image](https://img.shields.io/pypi/pyversions/ruff/0.3.6.svg)](https://pypi.python.org/pypi/ruff) [![Actions status](https://github.com/astral-sh/ruff-vscode/workflows/CI/badge.svg)](https://github.com/astral-sh/ruff-vscode/actions) A Visual Studio Code extension for [Ruff](https://github.com/astral-sh/ruff), an extremely fast @@ -12,7 +12,7 @@ Python linter and code formatter, written in Rust. Available on the [Visual Stud Ruff can be used to replace Flake8 (plus dozens of plugins), Black, isort, pyupgrade, and more, all while executing tens or hundreds of times faster than any individual tool. -The extension ships with `ruff==0.3.3`. +The extension ships with `ruff==0.3.6`. (Interested in using [Ruff](https://github.com/astral-sh/ruff) with another editor? Check out [`ruff-lsp`](https://github.com/astral-sh/ruff-lsp).) @@ -294,7 +294,7 @@ At the moment, the experimental server has the following known limitations: - Commands like `Fix all` and `Organize Imports` have not yet been implemented. (Quick Fixes should still work, though) - Hierarchial configuration for individual files is not yet supported. At the moment, the language server uses the `ruff.toml` / `pyproject.toml` at the workspace root to configure the formatter and linter. - Jupyter Notebook files are not supported yet. -- Using local Ruff binaries is not yet supported. At the moment, the extension will always use the bundled Ruff binary. (`v0.3.3`) +- Using local Ruff binaries is not yet supported. At the moment, the extension will always use the bundled Ruff binary. (`v0.3.6`) ## Commands diff --git a/pyproject.toml b/pyproject.toml index eb3b8cf..80b37ee 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ authors = [{ name = "Charlie Marsh", email = "charlie.r.marsh@gmail.com" }] maintainers = [{ name = "Charlie Marsh", email = "charlie.r.marsh@gmail.com" }] requires-python = ">=3.7" license = "MIT" -dependencies = ["packaging>=23.1", "ruff-lsp==0.0.53", "ruff==0.3.3"] +dependencies = ["packaging>=23.1", "ruff-lsp==0.0.53", "ruff==0.3.6"] [project.optional-dependencies] dev = ["mypy==1.2.0", "python-lsp-jsonrpc==1.0.0"] diff --git a/requirements-dev.txt b/requirements-dev.txt index c1c91cd..4fb8226 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -74,24 +74,24 @@ python-lsp-jsonrpc==1.0.0 \ --hash=sha256:079b143be64b0a378bdb21dff5e28a8c1393fe7e8a654ef068322d754e545fc7 \ --hash=sha256:7bec170733db628d3506ea3a5288ff76aa33c70215ed223abdb0d95e957660bd # via ruff-vscode (./pyproject.toml) -ruff==0.3.3 \ - --hash=sha256:0171aab5fecdc54383993389710a3d1227f2da124d76a2784a7098e818f92d61 \ - --hash=sha256:0da458989ce0159555ef224d5b7c24d3d2e4bf4c300b85467b08c3261c6bc6a8 \ - --hash=sha256:1eca7ff7a47043cf6ce5c7f45f603b09121a7cc047447744b029d1b719278eb5 \ - --hash=sha256:2700a804d5336bcffe063fd789ca2c7b02b552d2e323a336700abb8ae9e6a3f8 \ - --hash=sha256:352e95ead6964974b234e16ba8a66dad102ec7bf8ac064a23f95371d8b198aab \ - --hash=sha256:38671be06f57a2f8aba957d9f701ea889aa5736be806f18c0cd03d6ff0cbca8d \ - --hash=sha256:45817af234605525cdf6317005923bf532514e1ea3d9270acf61ca2440691376 \ - --hash=sha256:5a6cbf216b69c7090f0fe4669501a27326c34e119068c1494f35aaf4cc683778 \ - --hash=sha256:79bca3a03a759cc773fca69e0bdeac8abd1c13c31b798d5bb3c9da4a03144a9f \ - --hash=sha256:8d6ab88c81c4040a817aa432484e838aaddf8bfd7ca70e4e615482757acb64f8 \ - --hash=sha256:973a0e388b7bc2e9148c7f9be8b8c6ae7471b9be37e1cc732f8f44a6f6d7720d \ - --hash=sha256:b24c19e8598916d9c6f5a5437671f55ee93c212a2c4c569605dc3842b6820386 \ - --hash=sha256:be90bcae57c24d9f9d023b12d627e958eb55f595428bafcb7fec0791ad25ddfc \ - --hash=sha256:cfa60d23269d6e2031129b053fdb4e5a7b0637fc6c9c0586737b962b2f834493 \ - --hash=sha256:e7d3f6762217c1da954de24b4a1a70515630d29f71e268ec5000afe81377642d \ - --hash=sha256:f2831ec6a580a97f1ea82ea1eda0401c3cdf512cf2045fa3c85e8ef109e87de0 \ - --hash=sha256:fd66469f1a18fdb9d32e22b79f486223052ddf057dc56dea0caaf1a47bdfaf4e +ruff==0.3.6 \ + --hash=sha256:26071fb530038602b984e3bbe1443ef82a38450c4dcb1344a9caf67234ff9756 \ + --hash=sha256:28ccf3fb6d1162a73cd286c63a5e4d885f46a1f99f0b392924bc95ccbd18ea8f \ + --hash=sha256:2b0c4c70578ef1871a9ac5c85ed7a8c33470e976c73ba9211a111d2771b5f787 \ + --hash=sha256:4056480f5cf38ad278667c31b0ef334c29acdfcea617cb89c4ccbc7d96f1637f \ + --hash=sha256:647f1fb5128a3e24ce68878b8050bb55044c45bb3f3ae4710d4da9ca96ede5cb \ + --hash=sha256:732ef99984275534f9466fbc01121523caf72aa8c2bdeb36fd2edf2bc294a992 \ + --hash=sha256:7c8a2a0e0cab077a07465259ffe3b3c090e747ca8097c5dc4c36ca0fdaaac90d \ + --hash=sha256:878ef1a55ce931f3ca23b690b159cd0659f495a4c231a847b00ca55e4c688baf \ + --hash=sha256:93699d61116807edc5ca1cdf9d2d22cf8d93335d59e3ff0ca7aee62c1818a736 \ + --hash=sha256:b11e09439d9df6cc12d9f622065834654417c40216d271f639512d80e80e3e53 \ + --hash=sha256:b2e79f8e1b6bd5411d7ddad3f2abff3f9d371beda29daef86400d416dedb7e02 \ + --hash=sha256:c466a52c522e6a08df0af018f550902f154f5649ad09e7f0d43da766e7399ebc \ + --hash=sha256:cf48ec2c4bfae7837dc325c431a2932dc23a1485e71c59591c1df471ba234e0e \ + --hash=sha256:e3da499ded004d0b956ab04248b2ae17e54a67ffc81353514ac583af5959a255 \ + --hash=sha256:ecb87788284af96725643eae9ab3ac746d8cc09aad140268523b019f7ac3cd98 \ + --hash=sha256:f1aa621beed533f46e9c7d6fe00e7f6e4570155b61d8f020387b72ace2b42e04 \ + --hash=sha256:fc4006cbc6c11fefc25f122d2eb4731d7a3d815dc74d67c54991cc3f99c90177 # via # ruff-lsp # ruff-vscode (./pyproject.toml) diff --git a/requirements.txt b/requirements.txt index 9bb8752..9f32d0a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -38,24 +38,24 @@ pygls==1.2.1 \ --hash=sha256:04f9b9c115b622dcc346fb390289066565343d60245a424eca77cb429b911ed8 \ --hash=sha256:7dcfcf12b6f15beb606afa46de2ed348b65a279c340ef2242a9a35c22eeafe94 # via ruff-lsp -ruff==0.3.3 \ - --hash=sha256:0171aab5fecdc54383993389710a3d1227f2da124d76a2784a7098e818f92d61 \ - --hash=sha256:0da458989ce0159555ef224d5b7c24d3d2e4bf4c300b85467b08c3261c6bc6a8 \ - --hash=sha256:1eca7ff7a47043cf6ce5c7f45f603b09121a7cc047447744b029d1b719278eb5 \ - --hash=sha256:2700a804d5336bcffe063fd789ca2c7b02b552d2e323a336700abb8ae9e6a3f8 \ - --hash=sha256:352e95ead6964974b234e16ba8a66dad102ec7bf8ac064a23f95371d8b198aab \ - --hash=sha256:38671be06f57a2f8aba957d9f701ea889aa5736be806f18c0cd03d6ff0cbca8d \ - --hash=sha256:45817af234605525cdf6317005923bf532514e1ea3d9270acf61ca2440691376 \ - --hash=sha256:5a6cbf216b69c7090f0fe4669501a27326c34e119068c1494f35aaf4cc683778 \ - --hash=sha256:79bca3a03a759cc773fca69e0bdeac8abd1c13c31b798d5bb3c9da4a03144a9f \ - --hash=sha256:8d6ab88c81c4040a817aa432484e838aaddf8bfd7ca70e4e615482757acb64f8 \ - --hash=sha256:973a0e388b7bc2e9148c7f9be8b8c6ae7471b9be37e1cc732f8f44a6f6d7720d \ - --hash=sha256:b24c19e8598916d9c6f5a5437671f55ee93c212a2c4c569605dc3842b6820386 \ - --hash=sha256:be90bcae57c24d9f9d023b12d627e958eb55f595428bafcb7fec0791ad25ddfc \ - --hash=sha256:cfa60d23269d6e2031129b053fdb4e5a7b0637fc6c9c0586737b962b2f834493 \ - --hash=sha256:e7d3f6762217c1da954de24b4a1a70515630d29f71e268ec5000afe81377642d \ - --hash=sha256:f2831ec6a580a97f1ea82ea1eda0401c3cdf512cf2045fa3c85e8ef109e87de0 \ - --hash=sha256:fd66469f1a18fdb9d32e22b79f486223052ddf057dc56dea0caaf1a47bdfaf4e +ruff==0.3.6 \ + --hash=sha256:26071fb530038602b984e3bbe1443ef82a38450c4dcb1344a9caf67234ff9756 \ + --hash=sha256:28ccf3fb6d1162a73cd286c63a5e4d885f46a1f99f0b392924bc95ccbd18ea8f \ + --hash=sha256:2b0c4c70578ef1871a9ac5c85ed7a8c33470e976c73ba9211a111d2771b5f787 \ + --hash=sha256:4056480f5cf38ad278667c31b0ef334c29acdfcea617cb89c4ccbc7d96f1637f \ + --hash=sha256:647f1fb5128a3e24ce68878b8050bb55044c45bb3f3ae4710d4da9ca96ede5cb \ + --hash=sha256:732ef99984275534f9466fbc01121523caf72aa8c2bdeb36fd2edf2bc294a992 \ + --hash=sha256:7c8a2a0e0cab077a07465259ffe3b3c090e747ca8097c5dc4c36ca0fdaaac90d \ + --hash=sha256:878ef1a55ce931f3ca23b690b159cd0659f495a4c231a847b00ca55e4c688baf \ + --hash=sha256:93699d61116807edc5ca1cdf9d2d22cf8d93335d59e3ff0ca7aee62c1818a736 \ + --hash=sha256:b11e09439d9df6cc12d9f622065834654417c40216d271f639512d80e80e3e53 \ + --hash=sha256:b2e79f8e1b6bd5411d7ddad3f2abff3f9d371beda29daef86400d416dedb7e02 \ + --hash=sha256:c466a52c522e6a08df0af018f550902f154f5649ad09e7f0d43da766e7399ebc \ + --hash=sha256:cf48ec2c4bfae7837dc325c431a2932dc23a1485e71c59591c1df471ba234e0e \ + --hash=sha256:e3da499ded004d0b956ab04248b2ae17e54a67ffc81353514ac583af5959a255 \ + --hash=sha256:ecb87788284af96725643eae9ab3ac746d8cc09aad140268523b019f7ac3cd98 \ + --hash=sha256:f1aa621beed533f46e9c7d6fe00e7f6e4570155b61d8f020387b72ace2b42e04 \ + --hash=sha256:fc4006cbc6c11fefc25f122d2eb4731d7a3d815dc74d67c54991cc3f99c90177 # via # ruff-lsp # ruff-vscode (./pyproject.toml)