From 066ba5bb325850910e8f4cb76a91e3293c3b7619 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Sep 2025 06:24:56 +0000 Subject: [PATCH] Update Ruff to v0.13.1 (#4962) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- .../4962.mZAGRv4sXnpirJCkrKniVJ.toml | 5 +++ pyproject.toml | 2 +- src/telegram/ext/_application.py | 2 +- src/telegram/ext/_basepersistence.py | 2 +- src/telegram/ext/_handlers/basehandler.py | 2 +- tests/_files/test_inputmedia.py | 2 +- tests/_passport/test_passport.py | 2 +- tests/_utils/test_files.py | 2 +- tests/ext/test_applicationbuilder.py | 2 +- tests/ext/test_basepersistence.py | 4 +- tests/ext/test_callbackcontext.py | 4 +- tests/ext/test_callbackdatacache.py | 2 +- tests/ext/test_jobqueue.py | 2 +- tests/ext/test_messagereactionhandler.py | 2 +- tests/ext/test_ratelimiter.py | 2 +- tests/ext/test_updater.py | 2 +- tests/request/test_request.py | 2 +- tests/test_bot.py | 4 +- tests/test_error.py | 34 +++++++-------- tests/test_message.py | 8 ++-- uv.lock | 43 ++++++++++--------- 22 files changed, 69 insertions(+), 63 deletions(-) create mode 100644 changes/unreleased/4962.mZAGRv4sXnpirJCkrKniVJ.toml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d75378f8c..039c8346d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,7 +8,7 @@ ci: repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: 'v0.12.7' + rev: 'v0.13.1' hooks: # Run the linter: - id: ruff-check diff --git a/changes/unreleased/4962.mZAGRv4sXnpirJCkrKniVJ.toml b/changes/unreleased/4962.mZAGRv4sXnpirJCkrKniVJ.toml new file mode 100644 index 000000000..ef28b76ca --- /dev/null +++ b/changes/unreleased/4962.mZAGRv4sXnpirJCkrKniVJ.toml @@ -0,0 +1,5 @@ +internal = "Update Ruff to v0.13.1" +[[pull_requests]] +uid = "4962" +author_uids = ["renovate[bot]"] +closes_threads = [] diff --git a/pyproject.toml b/pyproject.toml index 1c15b402b..06f28fb13 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -133,7 +133,7 @@ docs = [ ] linting = [ "pre-commit", - "ruff==0.12.7", + "ruff==0.13.1", "mypy==1.18.2", "pylint==3.3.8" ] diff --git a/src/telegram/ext/_application.py b/src/telegram/ext/_application.py index 62222f8da..4bf79ed9f 100644 --- a/src/telegram/ext/_application.py +++ b/src/telegram/ext/_application.py @@ -116,8 +116,8 @@ class ApplicationHandlerStop(Exception): class Application( - Generic[BT, CCT, UD, CD, BD, JQ], contextlib.AbstractAsyncContextManager["Application"], + Generic[BT, CCT, UD, CD, BD, JQ], ): """This class dispatches all kinds of updates to its registered handlers, and is the entry point to a PTB application. diff --git a/src/telegram/ext/_basepersistence.py b/src/telegram/ext/_basepersistence.py index 2bdd6b808..9f7fae369 100644 --- a/src/telegram/ext/_basepersistence.py +++ b/src/telegram/ext/_basepersistence.py @@ -54,7 +54,7 @@ class PersistenceInput(NamedTuple): callback_data: bool = True -class BasePersistence(Generic[UD, CD, BD], ABC): +class BasePersistence(ABC, Generic[UD, CD, BD]): """Interface class for adding persistence to your bot. Subclass this object for different implementations of a persistent bot. diff --git a/src/telegram/ext/_handlers/basehandler.py b/src/telegram/ext/_handlers/basehandler.py index fc60b0884..8dd9387cc 100644 --- a/src/telegram/ext/_handlers/basehandler.py +++ b/src/telegram/ext/_handlers/basehandler.py @@ -33,7 +33,7 @@ RT = TypeVar("RT") UT = TypeVar("UT") -class BaseHandler(Generic[UT, CCT, RT], ABC): +class BaseHandler(ABC, Generic[UT, CCT, RT]): """The base class for all update handlers. Create custom handlers by inheriting from it. Warning: diff --git a/tests/_files/test_inputmedia.py b/tests/_files/test_inputmedia.py index 57bf8609f..b637eaf54 100644 --- a/tests/_files/test_inputmedia.py +++ b/tests/_files/test_inputmedia.py @@ -760,7 +760,7 @@ class TestSendMediaGroupWithoutRequest: ): with pytest.raises( ValueError, - match="You can only supply either group caption or media with captions.", + match="You can only supply either group caption or media with captions\\.", ): await offline_bot.send_media_group(chat_id, group, caption="foo") diff --git a/tests/_passport/test_passport.py b/tests/_passport/test_passport.py index 4104a2c6b..0ae9700ec 100644 --- a/tests/_passport/test_passport.py +++ b/tests/_passport/test_passport.py @@ -420,7 +420,7 @@ class TestPassportWithoutRequest(PassportTestBase): # Different error messages for different cryptography versions with pytest.raises( - ValueError, match="(Could not deserialize key data)|(Unable to load PEM file)" + ValueError, match=r"(Could not deserialize key data)|(Unable to load PEM file)" ): Bot(offline_bot.token, private_key=b"Invalid key!") diff --git a/tests/_utils/test_files.py b/tests/_utils/test_files.py index d789bdcd6..ad48e8ce0 100644 --- a/tests/_utils/test_files.py +++ b/tests/_utils/test_files.py @@ -75,7 +75,7 @@ class TestFiles: telegram._utils.files.parse_file_input(string, local_mode=False), InputFile ) elif expected_non_local is ValueError: - with pytest.raises(ValueError, match="but local mode is not enabled."): + with pytest.raises(ValueError, match="but local mode is not enabled\\."): telegram._utils.files.parse_file_input(string, local_mode=False) else: assert ( diff --git a/tests/ext/test_applicationbuilder.py b/tests/ext/test_applicationbuilder.py index b7ef6297f..b5fbecca8 100644 --- a/tests/ext/test_applicationbuilder.py +++ b/tests/ext/test_applicationbuilder.py @@ -110,7 +110,7 @@ class TestApplicationBuilder: ApplicationBuilder() def test_build_without_token(self, builder): - with pytest.raises(RuntimeError, match="No bot token was set."): + with pytest.raises(RuntimeError, match="No bot token was set\\."): builder.build() def test_build_custom_bot(self, builder, bot): diff --git a/tests/ext/test_basepersistence.py b/tests/ext/test_basepersistence.py index 42be9c62e..86d394b3a 100644 --- a/tests/ext/test_basepersistence.py +++ b/tests/ext/test_basepersistence.py @@ -404,7 +404,7 @@ class TestBasePersistence: @default_papp def test_set_bot_error(self, papp): - with pytest.raises(TypeError, match="when using telegram.ext.ExtBot"): + with pytest.raises(TypeError, match="when using telegram\\.ext\\.ExtBot"): papp.persistence.set_bot(Bot(papp.bot.token)) # just making sure that setting an ExtBoxt without callback_data_cache doesn't raise an @@ -419,7 +419,7 @@ class TestBasePersistence: self.store_data = PersistenceInput(False, False, False, False) with pytest.raises( - TypeError, match="persistence must be based on telegram.ext.BasePersistence" + TypeError, match="persistence must be based on telegram\\.ext\\.BasePersistence" ): ApplicationBuilder().bot(bot).persistence(MyPersistence()).build() diff --git a/tests/ext/test_callbackcontext.py b/tests/ext/test_callbackcontext.py index d74f2473d..6fb13a680 100644 --- a/tests/ext/test_callbackcontext.py +++ b/tests/ext/test_callbackcontext.py @@ -200,12 +200,12 @@ class TestCallbackContext: callback_context = CallbackContext.from_update(update, app) - with pytest.raises(RuntimeError, match="This telegram.ext.ExtBot instance does not"): + with pytest.raises(RuntimeError, match="This telegram\\.ext\\.ExtBot instance does not"): callback_context.drop_callback_data(None) try: app.bot = raw_bot - with pytest.raises(RuntimeError, match="telegram.Bot does not allow for"): + with pytest.raises(RuntimeError, match="telegram\\.Bot does not allow for"): callback_context.drop_callback_data(None) finally: app.bot = bot diff --git a/tests/ext/test_callbackdatacache.py b/tests/ext/test_callbackdatacache.py index f0a5f7b6c..7c335bb82 100644 --- a/tests/ext/test_callbackdatacache.py +++ b/tests/ext/test_callbackdatacache.py @@ -320,7 +320,7 @@ class TestCallbackDataCache: data=out.inline_keyboard[0][1].callback_data, ) - with pytest.raises(KeyError, match="CallbackQuery was not found in cache."): + with pytest.raises(KeyError, match="CallbackQuery was not found in cache\\."): callback_data_cache.drop_data(callback_query) callback_data_cache.process_callback_query(callback_query) diff --git a/tests/ext/test_jobqueue.py b/tests/ext/test_jobqueue.py index 57bac18b3..40b537980 100644 --- a/tests/ext/test_jobqueue.py +++ b/tests/ext/test_jobqueue.py @@ -629,7 +629,7 @@ class TestJobQueue: async def test_attribute_error(self): job = Job(self.job_run_once) with pytest.raises( - AttributeError, match="nor 'apscheduler.job.Job' has attribute 'error'" + AttributeError, match="nor 'apscheduler\\.job\\.Job' has attribute 'error'" ): job.error diff --git a/tests/ext/test_messagereactionhandler.py b/tests/ext/test_messagereactionhandler.py index dd843be91..684213143 100644 --- a/tests/ext/test_messagereactionhandler.py +++ b/tests/ext/test_messagereactionhandler.py @@ -210,7 +210,7 @@ class TestMessageReactionHandler: ) async def test_username_with_anonymous_reaction(self, app, allowed_types, kwargs): with pytest.raises( - ValueError, match="You can not filter for users and include anonymous reactions." + ValueError, match="You can not filter for users and include anonymous reactions\\." ): MessageReactionHandler(self.callback, message_reaction_types=allowed_types, **kwargs) diff --git a/tests/ext/test_ratelimiter.py b/tests/ext/test_ratelimiter.py index 4f4e51519..e1892b364 100644 --- a/tests/ext/test_ratelimiter.py +++ b/tests/ext/test_ratelimiter.py @@ -54,7 +54,7 @@ class TestBaseRateLimiter: request_received = None async def test_no_rate_limiter(self, bot): - with pytest.raises(ValueError, match="if a `ExtBot.rate_limiter` is set"): + with pytest.raises(ValueError, match="if a `ExtBot\\.rate_limiter` is set"): await bot.send_message(chat_id=42, text="test", rate_limit_args="something") async def test_argument_passing(self, bot_info, monkeypatch, bot): diff --git a/tests/ext/test_updater.py b/tests/ext/test_updater.py index ebca2585d..9ea1b31be 100644 --- a/tests/ext/test_updater.py +++ b/tests/ext/test_updater.py @@ -849,7 +849,7 @@ class TestUpdater: ) async def test_no_unix(self, updater): async with updater: - with pytest.raises(RuntimeError, match="binding unix sockets."): + with pytest.raises(RuntimeError, match="binding unix sockets\\."): await updater.start_webhook(unix="DoesntMatter", webhook_url="TOKEN") async def test_start_webhook_already_running(self, updater, monkeypatch): diff --git a/tests/request/test_request.py b/tests/request/test_request.py index 84cffdb04..4cc92a884 100644 --- a/tests/request/test_request.py +++ b/tests/request/test_request.py @@ -273,7 +273,7 @@ class TestRequestWithoutRequest: with pytest.raises( BadRequest, - match="{'unknown': '42'}", + match="\\{'unknown': '42'\\}", ): await httpx_request.post(None, None, None) diff --git a/tests/test_bot.py b/tests/test_bot.py index e2c905c1a..fc6884567 100644 --- a/tests/test_bot.py +++ b/tests/test_bot.py @@ -2672,7 +2672,7 @@ class TestBotWithRequest: # No need to duplicate here. async def test_invalid_token_server_response(self): - with pytest.raises(InvalidToken, match="The token `12` was rejected by the server."): + with pytest.raises(InvalidToken, match="The token `12` was rejected by the server\\."): async with ExtBot(token="12"): pass @@ -3835,7 +3835,7 @@ class TestBotWithRequest: # # The error message Hide_requester_missing started showing up instead of # User_already_participant. Don't know why … - with pytest.raises(BadRequest, match="User_already_participant|Hide_requester_missing"): + with pytest.raises(BadRequest, match=r"User_already_participant|Hide_requester_missing"): await bot.decline_chat_join_request(chat_id=channel_id, user_id=chat_id) async def test_set_chat_photo(self, bot, channel_id): diff --git a/tests/test_error.py b/tests/test_error.py index 863ec0c4c..2a0c7ad7f 100644 --- a/tests/test_error.py +++ b/tests/test_error.py @@ -42,23 +42,23 @@ from tests.auxil.slots import mro_slots class TestErrors: def test_telegram_error(self): - with pytest.raises(TelegramError, match="^test message$"): + with pytest.raises(TelegramError, match=r"^test message$"): raise TelegramError("test message") - with pytest.raises(TelegramError, match="^Test message$"): + with pytest.raises(TelegramError, match=r"^Test message$"): raise TelegramError("Error: test message") - with pytest.raises(TelegramError, match="^Test message$"): + with pytest.raises(TelegramError, match=r"^Test message$"): raise TelegramError("[Error]: test message") - with pytest.raises(TelegramError, match="^Test message$"): + with pytest.raises(TelegramError, match=r"^Test message$"): raise TelegramError("Bad Request: test message") def test_unauthorized(self): with pytest.raises(Forbidden, match="test message"): raise Forbidden("test message") - with pytest.raises(Forbidden, match="^Test message$"): + with pytest.raises(Forbidden, match=r"^Test message$"): raise Forbidden("Error: test message") - with pytest.raises(Forbidden, match="^Test message$"): + with pytest.raises(Forbidden, match=r"^Test message$"): raise Forbidden("[Error]: test message") - with pytest.raises(Forbidden, match="^Test message$"): + with pytest.raises(Forbidden, match=r"^Test message$"): raise Forbidden("Bad Request: test message") def test_invalid_token(self): @@ -68,25 +68,25 @@ class TestErrors: def test_network_error(self): with pytest.raises(NetworkError, match="test message"): raise NetworkError("test message") - with pytest.raises(NetworkError, match="^Test message$"): + with pytest.raises(NetworkError, match=r"^Test message$"): raise NetworkError("Error: test message") - with pytest.raises(NetworkError, match="^Test message$"): + with pytest.raises(NetworkError, match=r"^Test message$"): raise NetworkError("[Error]: test message") - with pytest.raises(NetworkError, match="^Test message$"): + with pytest.raises(NetworkError, match=r"^Test message$"): raise NetworkError("Bad Request: test message") def test_bad_request(self): with pytest.raises(BadRequest, match="test message"): raise BadRequest("test message") - with pytest.raises(BadRequest, match="^Test message$"): + with pytest.raises(BadRequest, match=r"^Test message$"): raise BadRequest("Error: test message") - with pytest.raises(BadRequest, match="^Test message$"): + with pytest.raises(BadRequest, match=r"^Test message$"): raise BadRequest("[Error]: test message") - with pytest.raises(BadRequest, match="^Test message$"): + with pytest.raises(BadRequest, match=r"^Test message$"): raise BadRequest("Bad Request: test message") def test_timed_out(self): - with pytest.raises(TimedOut, match="^Timed out$"): + with pytest.raises(TimedOut, match=r"^Timed out$"): raise TimedOut def test_chat_migrated(self): @@ -97,11 +97,11 @@ class TestErrors: @pytest.mark.parametrize("retry_after", [12, dtm.timedelta(seconds=12)]) def test_retry_after(self, PTB_TIMEDELTA, retry_after): if PTB_TIMEDELTA: - with pytest.raises(RetryAfter, match="Flood control exceeded. Retry in 0:00:12"): + with pytest.raises(RetryAfter, match="Flood control exceeded\\. Retry in 0:00:12"): raise (exception := RetryAfter(retry_after)) assert type(exception.retry_after) is dtm.timedelta else: - with pytest.raises(RetryAfter, match="Flood control exceeded. Retry in 12 seconds"): + with pytest.raises(RetryAfter, match="Flood control exceeded\\. Retry in 12 seconds"): raise (exception := RetryAfter(retry_after)) assert type(exception.retry_after) is int @@ -118,7 +118,7 @@ class TestErrors: assert type(retry_after) is int def test_conflict(self): - with pytest.raises(Conflict, match="Something something."): + with pytest.raises(Conflict, match="Something something\\."): raise Conflict("Something something.") @pytest.mark.parametrize( diff --git a/tests/test_message.py b/tests/test_message.py index 81fa66f79..3bafe22d5 100644 --- a/tests/test_message.py +++ b/tests/test_message.py @@ -603,13 +603,13 @@ class TestMessageWithoutRequest(MessageTestBase): """Used in testing reply_* below. Makes sure that do_quote is handled correctly""" with pytest.raises( ValueError, - match="`reply_to_message_id` and `reply_parameters` are mutually exclusive.", + match="`reply_to_message_id` and `reply_parameters` are mutually exclusive\\.", ): await method(*args, reply_to_message_id=42, reply_parameters=42) with pytest.raises( ValueError, - match="`allow_sending_without_reply` and `reply_parameters` are mutually exclusive.", + match="`allow_sending_without_reply` and `reply_parameters` are mutually exclusive\\.", ): await method(*args, allow_sending_without_reply=True, reply_parameters=42) @@ -1463,7 +1463,7 @@ class TestMessageWithoutRequest(MessageTestBase): message.text = "AA" with pytest.raises( ValueError, - match="You requested the 5-th occurrence of 'A', but this text appears only 2 times.", + match="You requested the 5-th occurrence of 'A', but this text appears only 2 times", ): message.compute_quote_position_and_entities("A", 5) @@ -1472,7 +1472,7 @@ class TestMessageWithoutRequest(MessageTestBase): message.caption = None with pytest.raises( RuntimeError, - match="This message has neither text nor caption.", + match="This message has neither text nor caption\\.", ): message.compute_quote_position_and_entities("A", 5) diff --git a/uv.lock b/uv.lock index bb0d5a00e..6e767accd 100644 --- a/uv.lock +++ b/uv.lock @@ -1547,7 +1547,7 @@ all = [ { name = "pytest-cov" }, { name = "pytest-xdist", specifier = "==3.8.0" }, { name = "pytz" }, - { name = "ruff", specifier = "==0.12.7" }, + { name = "ruff", specifier = "==0.13.1" }, { name = "sphinx", marker = "python_full_version >= '3.11'", specifier = "==8.2.3" }, { name = "sphinx-build-compatibility", git = "https://github.com/readthedocs/sphinx-build-compatibility.git?rev=58aabc5f207c6c2421f23d3578adc0b14af57047" }, { name = "sphinx-copybutton", specifier = "==0.5.2" }, @@ -1571,7 +1571,7 @@ linting = [ { name = "mypy", specifier = "==1.18.2" }, { name = "pre-commit" }, { name = "pylint", specifier = "==3.3.8" }, - { name = "ruff", specifier = "==0.12.7" }, + { name = "ruff", specifier = "==0.13.1" }, ] tests = [ { name = "beautifulsoup4" }, @@ -1686,27 +1686,28 @@ wheels = [ [[package]] name = "ruff" -version = "0.12.7" +version = "0.13.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a1/81/0bd3594fa0f690466e41bd033bdcdf86cba8288345ac77ad4afbe5ec743a/ruff-0.12.7.tar.gz", hash = "sha256:1fc3193f238bc2d7968772c82831a4ff69252f673be371fb49663f0068b7ec71", size = 5197814, upload-time = "2025-07-29T22:32:35.877Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ab/33/c8e89216845615d14d2d42ba2bee404e7206a8db782f33400754f3799f05/ruff-0.13.1.tar.gz", hash = "sha256:88074c3849087f153d4bb22e92243ad4c1b366d7055f98726bc19aa08dc12d51", size = 5397987, upload-time = "2025-09-18T19:52:44.33Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e1/d2/6cb35e9c85e7a91e8d22ab32ae07ac39cc34a71f1009a6f9e4a2a019e602/ruff-0.12.7-py3-none-linux_armv6l.whl", hash = "sha256:76e4f31529899b8c434c3c1dede98c4483b89590e15fb49f2d46183801565303", size = 11852189, upload-time = "2025-07-29T22:31:41.281Z" }, - { url = "https://files.pythonhosted.org/packages/63/5b/a4136b9921aa84638f1a6be7fb086f8cad0fde538ba76bda3682f2599a2f/ruff-0.12.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:789b7a03e72507c54fb3ba6209e4bb36517b90f1a3569ea17084e3fd295500fb", size = 12519389, upload-time = "2025-07-29T22:31:54.265Z" }, - { url = "https://files.pythonhosted.org/packages/a8/c9/3e24a8472484269b6b1821794141f879c54645a111ded4b6f58f9ab0705f/ruff-0.12.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2e1c2a3b8626339bb6369116e7030a4cf194ea48f49b64bb505732a7fce4f4e3", size = 11743384, upload-time = "2025-07-29T22:31:59.575Z" }, - { url = "https://files.pythonhosted.org/packages/26/7c/458dd25deeb3452c43eaee853c0b17a1e84169f8021a26d500ead77964fd/ruff-0.12.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32dec41817623d388e645612ec70d5757a6d9c035f3744a52c7b195a57e03860", size = 11943759, upload-time = "2025-07-29T22:32:01.95Z" }, - { url = "https://files.pythonhosted.org/packages/7f/8b/658798472ef260ca050e400ab96ef7e85c366c39cf3dfbef4d0a46a528b6/ruff-0.12.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47ef751f722053a5df5fa48d412dbb54d41ab9b17875c6840a58ec63ff0c247c", size = 11654028, upload-time = "2025-07-29T22:32:04.367Z" }, - { url = "https://files.pythonhosted.org/packages/a8/86/9c2336f13b2a3326d06d39178fd3448dcc7025f82514d1b15816fe42bfe8/ruff-0.12.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a828a5fc25a3efd3e1ff7b241fd392686c9386f20e5ac90aa9234a5faa12c423", size = 13225209, upload-time = "2025-07-29T22:32:06.952Z" }, - { url = "https://files.pythonhosted.org/packages/76/69/df73f65f53d6c463b19b6b312fd2391dc36425d926ec237a7ed028a90fc1/ruff-0.12.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5726f59b171111fa6a69d82aef48f00b56598b03a22f0f4170664ff4d8298efb", size = 14182353, upload-time = "2025-07-29T22:32:10.053Z" }, - { url = "https://files.pythonhosted.org/packages/58/1e/de6cda406d99fea84b66811c189b5ea139814b98125b052424b55d28a41c/ruff-0.12.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:74e6f5c04c4dd4aba223f4fe6e7104f79e0eebf7d307e4f9b18c18362124bccd", size = 13631555, upload-time = "2025-07-29T22:32:12.644Z" }, - { url = "https://files.pythonhosted.org/packages/6f/ae/625d46d5164a6cc9261945a5e89df24457dc8262539ace3ac36c40f0b51e/ruff-0.12.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d0bfe4e77fba61bf2ccadf8cf005d6133e3ce08793bbe870dd1c734f2699a3e", size = 12667556, upload-time = "2025-07-29T22:32:15.312Z" }, - { url = "https://files.pythonhosted.org/packages/55/bf/9cb1ea5e3066779e42ade8d0cd3d3b0582a5720a814ae1586f85014656b6/ruff-0.12.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06bfb01e1623bf7f59ea749a841da56f8f653d641bfd046edee32ede7ff6c606", size = 12939784, upload-time = "2025-07-29T22:32:17.69Z" }, - { url = "https://files.pythonhosted.org/packages/55/7f/7ead2663be5627c04be83754c4f3096603bf5e99ed856c7cd29618c691bd/ruff-0.12.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e41df94a957d50083fd09b916d6e89e497246698c3f3d5c681c8b3e7b9bb4ac8", size = 11771356, upload-time = "2025-07-29T22:32:20.134Z" }, - { url = "https://files.pythonhosted.org/packages/17/40/a95352ea16edf78cd3a938085dccc55df692a4d8ba1b3af7accbe2c806b0/ruff-0.12.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:4000623300563c709458d0ce170c3d0d788c23a058912f28bbadc6f905d67afa", size = 11612124, upload-time = "2025-07-29T22:32:22.645Z" }, - { url = "https://files.pythonhosted.org/packages/4d/74/633b04871c669e23b8917877e812376827c06df866e1677f15abfadc95cb/ruff-0.12.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:69ffe0e5f9b2cf2b8e289a3f8945b402a1b19eff24ec389f45f23c42a3dd6fb5", size = 12479945, upload-time = "2025-07-29T22:32:24.765Z" }, - { url = "https://files.pythonhosted.org/packages/be/34/c3ef2d7799c9778b835a76189c6f53c179d3bdebc8c65288c29032e03613/ruff-0.12.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a07a5c8ffa2611a52732bdc67bf88e243abd84fe2d7f6daef3826b59abbfeda4", size = 12998677, upload-time = "2025-07-29T22:32:27.022Z" }, - { url = "https://files.pythonhosted.org/packages/77/ab/aca2e756ad7b09b3d662a41773f3edcbd262872a4fc81f920dc1ffa44541/ruff-0.12.7-py3-none-win32.whl", hash = "sha256:c928f1b2ec59fb77dfdf70e0419408898b63998789cc98197e15f560b9e77f77", size = 11756687, upload-time = "2025-07-29T22:32:29.381Z" }, - { url = "https://files.pythonhosted.org/packages/b4/71/26d45a5042bc71db22ddd8252ca9d01e9ca454f230e2996bb04f16d72799/ruff-0.12.7-py3-none-win_amd64.whl", hash = "sha256:9c18f3d707ee9edf89da76131956aba1270c6348bfee8f6c647de841eac7194f", size = 12912365, upload-time = "2025-07-29T22:32:31.517Z" }, - { url = "https://files.pythonhosted.org/packages/4c/9b/0b8aa09817b63e78d94b4977f18b1fcaead3165a5ee49251c5d5c245bb2d/ruff-0.12.7-py3-none-win_arm64.whl", hash = "sha256:dfce05101dbd11833a0776716d5d1578641b7fddb537fe7fa956ab85d1769b69", size = 11982083, upload-time = "2025-07-29T22:32:33.881Z" }, + { url = "https://files.pythonhosted.org/packages/f3/41/ca37e340938f45cfb8557a97a5c347e718ef34702546b174e5300dbb1f28/ruff-0.13.1-py3-none-linux_armv6l.whl", hash = "sha256:b2abff595cc3cbfa55e509d89439b5a09a6ee3c252d92020bd2de240836cf45b", size = 12304308, upload-time = "2025-09-18T19:51:56.253Z" }, + { url = "https://files.pythonhosted.org/packages/ff/84/ba378ef4129415066c3e1c80d84e539a0d52feb250685091f874804f28af/ruff-0.13.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:4ee9f4249bf7f8bb3984c41bfaf6a658162cdb1b22e3103eabc7dd1dc5579334", size = 12937258, upload-time = "2025-09-18T19:52:00.184Z" }, + { url = "https://files.pythonhosted.org/packages/8d/b6/ec5e4559ae0ad955515c176910d6d7c93edcbc0ed1a3195a41179c58431d/ruff-0.13.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5c5da4af5f6418c07d75e6f3224e08147441f5d1eac2e6ce10dcce5e616a3bae", size = 12214554, upload-time = "2025-09-18T19:52:02.753Z" }, + { url = "https://files.pythonhosted.org/packages/70/d6/cb3e3b4f03b9b0c4d4d8f06126d34b3394f6b4d764912fe80a1300696ef6/ruff-0.13.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80524f84a01355a59a93cef98d804e2137639823bcee2931f5028e71134a954e", size = 12448181, upload-time = "2025-09-18T19:52:05.279Z" }, + { url = "https://files.pythonhosted.org/packages/d2/ea/bf60cb46d7ade706a246cd3fb99e4cfe854efa3dfbe530d049c684da24ff/ruff-0.13.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff7f5ce8d7988767dd46a148192a14d0f48d1baea733f055d9064875c7d50389", size = 12104599, upload-time = "2025-09-18T19:52:07.497Z" }, + { url = "https://files.pythonhosted.org/packages/2d/3e/05f72f4c3d3a69e65d55a13e1dd1ade76c106d8546e7e54501d31f1dc54a/ruff-0.13.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c55d84715061f8b05469cdc9a446aa6c7294cd4bd55e86a89e572dba14374f8c", size = 13791178, upload-time = "2025-09-18T19:52:10.189Z" }, + { url = "https://files.pythonhosted.org/packages/81/e7/01b1fc403dd45d6cfe600725270ecc6a8f8a48a55bc6521ad820ed3ceaf8/ruff-0.13.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:ac57fed932d90fa1624c946dc67a0a3388d65a7edc7d2d8e4ca7bddaa789b3b0", size = 14814474, upload-time = "2025-09-18T19:52:12.866Z" }, + { url = "https://files.pythonhosted.org/packages/fa/92/d9e183d4ed6185a8df2ce9faa3f22e80e95b5f88d9cc3d86a6d94331da3f/ruff-0.13.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c366a71d5b4f41f86a008694f7a0d75fe409ec298685ff72dc882f882d532e36", size = 14217531, upload-time = "2025-09-18T19:52:15.245Z" }, + { url = "https://files.pythonhosted.org/packages/3b/4a/6ddb1b11d60888be224d721e01bdd2d81faaf1720592858ab8bac3600466/ruff-0.13.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4ea9d1b5ad3e7a83ee8ebb1229c33e5fe771e833d6d3dcfca7b77d95b060d38", size = 13265267, upload-time = "2025-09-18T19:52:17.649Z" }, + { url = "https://files.pythonhosted.org/packages/81/98/3f1d18a8d9ea33ef2ad508f0417fcb182c99b23258ec5e53d15db8289809/ruff-0.13.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0f70202996055b555d3d74b626406476cc692f37b13bac8828acff058c9966a", size = 13243120, upload-time = "2025-09-18T19:52:20.332Z" }, + { url = "https://files.pythonhosted.org/packages/8d/86/b6ce62ce9c12765fa6c65078d1938d2490b2b1d9273d0de384952b43c490/ruff-0.13.1-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:f8cff7a105dad631085d9505b491db33848007d6b487c3c1979dd8d9b2963783", size = 13443084, upload-time = "2025-09-18T19:52:23.032Z" }, + { url = "https://files.pythonhosted.org/packages/a1/6e/af7943466a41338d04503fb5a81b2fd07251bd272f546622e5b1599a7976/ruff-0.13.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:9761e84255443316a258dd7dfbd9bfb59c756e52237ed42494917b2577697c6a", size = 12295105, upload-time = "2025-09-18T19:52:25.263Z" }, + { url = "https://files.pythonhosted.org/packages/3f/97/0249b9a24f0f3ebd12f007e81c87cec6d311de566885e9309fcbac5b24cc/ruff-0.13.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:3d376a88c3102ef228b102211ef4a6d13df330cb0f5ca56fdac04ccec2a99700", size = 12072284, upload-time = "2025-09-18T19:52:27.478Z" }, + { url = "https://files.pythonhosted.org/packages/f6/85/0b64693b2c99d62ae65236ef74508ba39c3febd01466ef7f354885e5050c/ruff-0.13.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:cbefd60082b517a82c6ec8836989775ac05f8991715d228b3c1d86ccc7df7dae", size = 12970314, upload-time = "2025-09-18T19:52:30.212Z" }, + { url = "https://files.pythonhosted.org/packages/96/fc/342e9f28179915d28b3747b7654f932ca472afbf7090fc0c4011e802f494/ruff-0.13.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:dd16b9a5a499fe73f3c2ef09a7885cb1d97058614d601809d37c422ed1525317", size = 13422360, upload-time = "2025-09-18T19:52:32.676Z" }, + { url = "https://files.pythonhosted.org/packages/37/54/6177a0dc10bce6f43e392a2192e6018755473283d0cf43cc7e6afc182aea/ruff-0.13.1-py3-none-win32.whl", hash = "sha256:55e9efa692d7cb18580279f1fbb525146adc401f40735edf0aaeabd93099f9a0", size = 12178448, upload-time = "2025-09-18T19:52:35.545Z" }, + { url = "https://files.pythonhosted.org/packages/64/51/c6a3a33d9938007b8bdc8ca852ecc8d810a407fb513ab08e34af12dc7c24/ruff-0.13.1-py3-none-win_amd64.whl", hash = "sha256:3a3fb595287ee556de947183489f636b9f76a72f0fa9c028bdcabf5bab2cc5e5", size = 13286458, upload-time = "2025-09-18T19:52:38.198Z" }, + { url = "https://files.pythonhosted.org/packages/fd/04/afc078a12cf68592345b1e2d6ecdff837d286bac023d7a22c54c7a698c5b/ruff-0.13.1-py3-none-win_arm64.whl", hash = "sha256:c0bae9ffd92d54e03c2bf266f466da0a65e145f298ee5b5846ed435f6a00518a", size = 12437893, upload-time = "2025-09-18T19:52:41.283Z" }, ] [[package]]