diff --git a/backend/pyproject.toml b/backend/pyproject.toml index ce9fb215..6e768972 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -77,8 +77,8 @@ where = ["src"] dev = [ "pytest==9.1.1", "pytest-asyncio==1.4.0", - "black==26.3.1", - "ruff==0.1.14", + "black==26.5.1", + "ruff==0.16.1", "pip-audit==2.10.1", "scikit-learn==1.9.0", # Used only by the standalone OCR benchmark scripts (scripts/benchmark_ocr_variants.py @@ -87,6 +87,22 @@ dev = [ "python-levenshtein>=0.27.3", ] +[tool.ruff] +target-version = "py312" + +[tool.ruff.lint] +# Pin the rule set explicitly rather than inheriting whatever ruff defaults to. +# Ruff changes its default selection between releases: 0.16 turned on B, BLE, I, +# S, SIM, UP, RUF and more, which surfaced 874 findings on an otherwise +# unchanged tree and was the only thing blocking the 0.1.14 -> 0.16 bump. +# Selecting here means the lint surface changes when we decide to change it, +# not as a side effect of bumping the linter. +# +# This is ruff's own stable default — pyflakes plus the pycodestyle errors that +# catch real mistakes rather than formatting noise — so it is exactly the +# baseline the backend was already green on under 0.1.14. +select = ["E4", "E7", "E9", "F"] + [tool.pytest.ini_options] testpaths = ["tests"] pythonpath = ["src"] diff --git a/backend/scripts/score_ocr_accuracy.py b/backend/scripts/score_ocr_accuracy.py index 0e6d88af..7806e952 100644 --- a/backend/scripts/score_ocr_accuracy.py +++ b/backend/scripts/score_ocr_accuracy.py @@ -151,12 +151,12 @@ def main(): m = all_results.get("mobile", {}).get(category) s = all_results.get("server", {}).get(category) m_str = ( - f"{m['exact_match_rate']*100:.0f}% / CER {m['avg_char_error_rate']}" + f"{m['exact_match_rate'] * 100:.0f}% / CER {m['avg_char_error_rate']}" if m else "n/a" ) s_str = ( - f"{s['exact_match_rate']*100:.0f}% / CER {s['avg_char_error_rate']}" + f"{s['exact_match_rate'] * 100:.0f}% / CER {s['avg_char_error_rate']}" if s else "n/a" ) diff --git a/backend/src/find_api/core/config.py b/backend/src/find_api/core/config.py index 6538817a..d583fd54 100644 --- a/backend/src/find_api/core/config.py +++ b/backend/src/find_api/core/config.py @@ -52,9 +52,9 @@ class Settings(BaseSettings): # Runtime/build profile. Docker images set this explicitly so the API can # distinguish installed capabilities from hardware that merely exists on # the host. ``development`` keeps source checkouts backwards compatible. - FIND_BUILD_PROFILE: Literal[ - "development", "no-ai", "mock", "cpu", "nvidia" - ] = "development" + FIND_BUILD_PROFILE: Literal["development", "no-ai", "mock", "cpu", "nvidia"] = ( + "development" + ) # ML Models ML_MODE: Literal["disabled", "full", "mock", "remote"] = "full" diff --git a/backend/tests/test_hybrid_embedding.py b/backend/tests/test_hybrid_embedding.py index d974c180..05dd5fd9 100644 --- a/backend/tests/test_hybrid_embedding.py +++ b/backend/tests/test_hybrid_embedding.py @@ -383,9 +383,9 @@ def test_empty_string_never_embedded_in_any_scenario(self): f"caption={caption!r}, objects={objects}" ) else: - assert ( - "" not in args - ), f"Empty string found in embed_text list call: {args}" + assert "" not in args, ( + f"Empty string found in embed_text list call: {args}" + ) def test_ocr_present_uses_weighted_hybrid(self): """When OCR text is present, weighted fusion should include OCR signal.""" diff --git a/backend/tests/test_perf_timeline.py b/backend/tests/test_perf_timeline.py index c2bf1df8..ac1d5a42 100644 --- a/backend/tests/test_perf_timeline.py +++ b/backend/tests/test_perf_timeline.py @@ -92,9 +92,9 @@ def test_buckets_aggregate_under_budget(self, client, seeded, capsys): f"{MONTHS} months: {elapsed * 1000:.1f} ms " f"(budget {BUCKETS_BUDGET_S * 1000:.0f} ms)" ) - assert ( - elapsed < BUCKETS_BUDGET_S - ), f"/timeline/buckets took {elapsed:.3f}s (budget {BUCKETS_BUDGET_S}s)" + assert elapsed < BUCKETS_BUDGET_S, ( + f"/timeline/buckets took {elapsed:.3f}s (budget {BUCKETS_BUDGET_S}s)" + ) def test_single_bucket_window_under_budget(self, client, seeded, capsys): # Pick a month that actually has assets. @@ -114,9 +114,9 @@ def test_single_bucket_window_under_budget(self, client, seeded, capsys): f"\n[perf] /timeline/bucket ({month_key}, {body['count']} assets): " f"{elapsed * 1000:.1f} ms (budget {BUCKET_BUDGET_S * 1000:.0f} ms)" ) - assert ( - elapsed < BUCKET_BUDGET_S - ), f"/timeline/bucket took {elapsed:.3f}s (budget {BUCKET_BUDGET_S}s)" + assert elapsed < BUCKET_BUDGET_S, ( + f"/timeline/bucket took {elapsed:.3f}s (budget {BUCKET_BUDGET_S}s)" + ) def test_liked_filter_aggregate_under_budget(self, client, seeded): # The favorites filter must not change the query's scaling characteristics. diff --git a/backend/tests/test_remote_ml_dispatch.py b/backend/tests/test_remote_ml_dispatch.py index 31ee2ba6..2487aca8 100644 --- a/backend/tests/test_remote_ml_dispatch.py +++ b/backend/tests/test_remote_ml_dispatch.py @@ -27,8 +27,9 @@ def test_remote_mode_calls_remote_analyze(self, monkeypatch): fake = MagicMock( return_value={"caption": "a bike", "objects": [], "ocr_text": ""} ) - with patch("find_api.ml.remote_client.remote_analyze", fake), patch( - "find_api.ml.remote_client._feature_enabled", lambda f: True + with ( + patch("find_api.ml.remote_client.remote_analyze", fake), + patch("find_api.ml.remote_client._feature_enabled", lambda f: True), ): result = processors.extract_image_metadata(_rgb_image()) @@ -42,8 +43,9 @@ def test_remote_mode_skips_transmission_when_no_features_enabled(self, monkeypat monkeypatch.setattr(processors, "current_ml_mode", lambda: "remote") fake = MagicMock() - with patch("find_api.ml.remote_client.remote_analyze", fake), patch( - "find_api.ml.remote_client._feature_enabled", lambda f: False + with ( + patch("find_api.ml.remote_client.remote_analyze", fake), + patch("find_api.ml.remote_client._feature_enabled", lambda f: False), ): result = processors.extract_image_metadata(_rgb_image()) @@ -54,8 +56,9 @@ def test_remote_mode_calls_remote_embed(self, monkeypatch): monkeypatch.setattr(processors, "current_ml_mode", lambda: "remote") fake = MagicMock(return_value=[0.1] * 768) - with patch("find_api.ml.remote_client.remote_embed", fake), patch( - "find_api.ml.remote_client._feature_enabled", lambda f: True + with ( + patch("find_api.ml.remote_client.remote_embed", fake), + patch("find_api.ml.remote_client._feature_enabled", lambda f: True), ): vector = processors.generate_hybrid_embedding(_rgb_image(), {}) @@ -79,8 +82,9 @@ def test_remote_cluster_is_dispatched(self): embeddings = np.eye(4, dtype=np.float32) fake = MagicMock(return_value={"labels": [0, 0, 1, 1], "info": {"n": 4}}) - with patch("find_api.ml.remote_client.remote_cluster", fake), patch( - "find_api.ml.remote_client._feature_enabled", lambda f: True + with ( + patch("find_api.ml.remote_client.remote_cluster", fake), + patch("find_api.ml.remote_client._feature_enabled", lambda f: True), ): labels, info = jobs._remote_cluster_embeddings(embeddings) @@ -98,9 +102,11 @@ def test_disabled_cluster_feature_falls_back_to_local(self): fake_local = MagicMock() fake_local.cluster.return_value = (np.array([-1, -1, -1, -1]), {}) - with patch("find_api.ml.remote_client.remote_cluster", fake_remote), patch( - "find_api.ml.remote_client._feature_enabled", lambda f: False - ), patch("find_api.ml.clusterer.get_image_clusterer", lambda: fake_local): + with ( + patch("find_api.ml.remote_client.remote_cluster", fake_remote), + patch("find_api.ml.remote_client._feature_enabled", lambda f: False), + patch("find_api.ml.clusterer.get_image_clusterer", lambda: fake_local), + ): jobs._remote_cluster_embeddings(embeddings) assert fake_remote.call_count == 0 @@ -136,9 +142,12 @@ def test_enabled_features_are_sent_to_the_server(self, monkeypatch): monkeypatch.setattr(processors, "current_ml_mode", lambda: "remote") fake = MagicMock(return_value={"caption": "x"}) - with patch("find_api.ml.remote_client.remote_analyze", fake), patch( - "find_api.ml.remote_client._feature_enabled", - lambda f: f in {"caption", "detect"}, + with ( + patch("find_api.ml.remote_client.remote_analyze", fake), + patch( + "find_api.ml.remote_client._feature_enabled", + lambda f: f in {"caption", "detect"}, + ), ): result = processors.extract_image_metadata(_rgb_image()) @@ -175,9 +184,10 @@ def test_disabled_embed_raises_rather_than_returning_a_mock_vector( """ monkeypatch.setattr(processors, "current_ml_mode", lambda: "remote") - with patch( - "find_api.ml.remote_client._feature_enabled", lambda f: False - ), pytest.raises(processors.RemoteFeatureDisabled): + with ( + patch("find_api.ml.remote_client._feature_enabled", lambda f: False), + pytest.raises(processors.RemoteFeatureDisabled), + ): processors.generate_hybrid_embedding(_rgb_image(), {}) diff --git a/backend/uv.lock b/backend/uv.lock index 4b5d4a8e..3e503150 100644 --- a/backend/uv.lock +++ b/backend/uv.lock @@ -263,7 +263,7 @@ wheels = [ [[package]] name = "black" -version = "26.3.1" +version = "26.5.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, @@ -273,14 +273,14 @@ dependencies = [ { name = "platformdirs" }, { name = "pytokens" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e1/c5/61175d618685d42b005847464b8fb4743a67b1b8fdb75e50e5a96c31a27a/black-26.3.1.tar.gz", hash = "sha256:2c50f5063a9641c7eed7795014ba37b0f5fa227f3d408b968936e24bc0566b07", size = 666155, upload-time = "2026-03-12T03:36:03.593Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c0/37/5628dd55bf2b34257fc7603f0fe97c40e3aaf24265f416a9c85c95ca1436/black-26.5.1.tar.gz", hash = "sha256:dd321f668053961824bcc1be1cc1df748b2d7e4fa28086b08331e577b0100a73", size = 679439, upload-time = "2026-05-18T16:53:36.107Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/dc/f8/da5eae4fc75e78e6dceb60624e1b9662ab00d6b452996046dfa9b8a6025b/black-26.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e6f89631eb88a7302d416594a32faeee9fb8fb848290da9d0a5f2903519fc1", size = 1895920, upload-time = "2026-03-12T03:40:13.921Z" }, - { url = "https://files.pythonhosted.org/packages/2c/9f/04e6f26534da2e1629b2b48255c264cabf5eedc5141d04516d9d68a24111/black-26.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:41cd2012d35b47d589cb8a16faf8a32ef7a336f56356babd9fcf70939ad1897f", size = 1718499, upload-time = "2026-03-12T03:40:15.239Z" }, - { url = "https://files.pythonhosted.org/packages/04/91/a5935b2a63e31b331060c4a9fdb5a6c725840858c599032a6f3aac94055f/black-26.3.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f76ff19ec5297dd8e66eb64deda23631e642c9393ab592826fd4bdc97a4bce7", size = 1794994, upload-time = "2026-03-12T03:40:17.124Z" }, - { url = "https://files.pythonhosted.org/packages/e7/0a/86e462cdd311a3c2a8ece708d22aba17d0b2a0d5348ca34b40cdcbea512e/black-26.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:ddb113db38838eb9f043623ba274cfaf7d51d5b0c22ecb30afe58b1bb8322983", size = 1420867, upload-time = "2026-03-12T03:40:18.83Z" }, - { url = "https://files.pythonhosted.org/packages/5b/e5/22515a19cb7eaee3440325a6b0d95d2c0e88dd180cb011b12ae488e031d1/black-26.3.1-cp312-cp312-win_arm64.whl", hash = "sha256:dfdd51fc3e64ea4f35873d1b3fb25326773d55d2329ff8449139ebaad7357efb", size = 1230124, upload-time = "2026-03-12T03:40:20.425Z" }, - { url = "https://files.pythonhosted.org/packages/8e/0d/52d98722666d6fc6c3dd4c76df339501d6efd40e0ff95e6186a7b7f0befd/black-26.3.1-py3-none-any.whl", hash = "sha256:2bd5aa94fc267d38bb21a70d7410a89f1a1d318841855f698746f8e7f51acd1b", size = 207542, upload-time = "2026-03-12T03:36:01.668Z" }, + { url = "https://files.pythonhosted.org/packages/24/99/7744b906703228264ef73bdd534df88ec1ef3de45c4e78f6d31b9e32d0c9/black-26.5.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4ad6fa01f941920f54f2bbb35f3df7673428a0ef98a0b0840c2eaef3b110efa8", size = 2012518, upload-time = "2026-05-18T17:05:20.108Z" }, + { url = "https://files.pythonhosted.org/packages/b7/c0/c5a3b1636dfd09c42534f2b3cf33506814f6d3e066fb0879ffa16c1ae860/black-26.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3915f256e75a2d7cf88d8953d37f780455dc586cc72dee059c528fe77f581217", size = 1816016, upload-time = "2026-05-18T17:05:21.84Z" }, + { url = "https://files.pythonhosted.org/packages/1f/0e/36044316b65ca471d3bb6d3703fd06fb50c6b727c3562f6a5a3153634f88/black-26.5.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d98d4137277c75dfb898ec8d846c4fd68ba1e9cf77f95e2865c203dc18f4c3d", size = 1884150, upload-time = "2026-05-18T17:05:23.546Z" }, + { url = "https://files.pythonhosted.org/packages/b3/33/dafc5808c2af43672912111d7c3354af1615f7e2be3bed7a878461abbe4d/black-26.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:a1dca32d9f1784af512a13410ec204c6f7f0aa9797a111c42e1c03449821c264", size = 1486825, upload-time = "2026-05-18T17:05:25.004Z" }, + { url = "https://files.pythonhosted.org/packages/82/14/b965ee6ad2a311f28bdbf692def3ee9848d2ae289dab28b27657fcee3e78/black-26.5.1-cp312-cp312-win_arm64.whl", hash = "sha256:1037d5ac7b7b310b2632ad867ec8d0e4c4819dcdb0b820f63135da746a24e418", size = 1288646, upload-time = "2026-05-18T17:05:26.477Z" }, + { url = "https://files.pythonhosted.org/packages/94/51/f975cae76d44274cc2868dc9040ac5d58d464784610234455b4e7b19c6ef/black-26.5.1-py3-none-any.whl", hash = "sha256:4ed7f7da04046d2e488437170797d3b4a4ad83906683bcb7dfc68b673bbce5e2", size = 213693, upload-time = "2026-05-18T16:53:33.964Z" }, ] [[package]] @@ -752,13 +752,13 @@ provides-extras = ["mock", "cpu", "nvidia"] [package.metadata.requires-dev] dev = [ - { name = "black", specifier = "==26.3.1" }, + { name = "black", specifier = "==26.5.1" }, { name = "pip-audit", specifier = "==2.10.1" }, { name = "psutil", specifier = ">=7.2.2" }, { name = "pytest", specifier = "==9.1.1" }, { name = "pytest-asyncio", specifier = "==1.4.0" }, { name = "python-levenshtein", specifier = ">=0.27.3" }, - { name = "ruff", specifier = "==0.1.14" }, + { name = "ruff", specifier = "==0.16.1" }, { name = "scikit-learn", specifier = "==1.9.0" }, ] @@ -2413,26 +2413,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.1.14" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5c/76/f1fbd0a6625d1f3044854b540642171acd02bd91c592001aac9f9606474c/ruff-0.1.14.tar.gz", hash = "sha256:ad3f8088b2dfd884820289a06ab718cde7d38b94972212cc4ba90d5fbc9955f3", size = 1954042, upload-time = "2024-01-19T20:19:35.342Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e9/7b/0f9cc50fd6936f7b125f8682d6ece05826573fd5cbc9f4e40ddd9e2175cb/ruff-0.1.14-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:96f76536df9b26622755c12ed8680f159817be2f725c17ed9305b472a757cdbb", size = 14356933, upload-time = "2024-01-19T20:18:30.083Z" }, - { url = "https://files.pythonhosted.org/packages/60/f8/d579ca257d26a5e6cc309298698340720e52115774253a73946182f106fa/ruff-0.1.14-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ab3f71f64498c7241123bb5a768544cf42821d2a537f894b22457a543d3ca7a9", size = 7331387, upload-time = "2024-01-19T20:18:36.649Z" }, - { url = "https://files.pythonhosted.org/packages/cf/6b/152672e4a5b990aa0796377348d40729cad51644bf94d72f46e606461f41/ruff-0.1.14-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7060156ecc572b8f984fd20fd8b0fcb692dd5d837b7606e968334ab7ff0090ab", size = 7107642, upload-time = "2024-01-19T20:18:40.247Z" }, - { url = "https://files.pythonhosted.org/packages/d2/c1/6673c34a491176cb93f9c1c49fbff0281981e3ca6814ba8bbb2e0def5a68/ruff-0.1.14-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a53d8e35313d7b67eb3db15a66c08434809107659226a90dcd7acb2afa55faea", size = 6537299, upload-time = "2024-01-19T20:18:43.848Z" }, - { url = "https://files.pythonhosted.org/packages/02/87/f474a50ddde6bb7cd6aeaf97c3368d68aefd112f9475cf3f1c51e27175ab/ruff-0.1.14-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bea9be712b8f5b4ebed40e1949379cfb2a7d907f42921cf9ab3aae07e6fba9eb", size = 7513665, upload-time = "2024-01-19T20:18:48.165Z" }, - { url = "https://files.pythonhosted.org/packages/4a/6c/272fb422375572e9a005baacfa8949c1a2c4445c972974c96dc7f8e5b186/ruff-0.1.14-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:2270504d629a0b064247983cbc495bed277f372fb9eaba41e5cf51f7ba705a6a", size = 8168069, upload-time = "2024-01-19T20:18:53.707Z" }, - { url = "https://files.pythonhosted.org/packages/7b/dc/c16b4db432d8f5250e0cc50d0ffcf1ab0ba7484933e24c84165af9e23706/ruff-0.1.14-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80258bb3b8909b1700610dfabef7876423eed1bc930fe177c71c414921898efa", size = 7946193, upload-time = "2024-01-19T20:18:57.744Z" }, - { url = "https://files.pythonhosted.org/packages/19/63/9b4a6e3ffbc54f5a240755bfb407e3b9a30efe2b4f1f76aa9d4c0db93a91/ruff-0.1.14-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:653230dd00aaf449eb5ff25d10a6e03bc3006813e2cb99799e568f55482e5cae", size = 8487204, upload-time = "2024-01-19T20:19:01.99Z" }, - { url = "https://files.pythonhosted.org/packages/8d/57/936030481a19d95a4a3171b259c8c81e224e6c7eabf1c6fbdb1479704548/ruff-0.1.14-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87b3acc6c4e6928459ba9eb7459dd4f0c4bf266a053c863d72a44c33246bfdbf", size = 7530991, upload-time = "2024-01-19T20:19:05.606Z" }, - { url = "https://files.pythonhosted.org/packages/c0/9a/f007e17874498e92ed28a85878d801b03c7ce3affb8a7dbfb1013b98eee9/ruff-0.1.14-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6b3dadc9522d0eccc060699a9816e8127b27addbb4697fc0c08611e4e6aeb8b5", size = 7039729, upload-time = "2024-01-19T20:19:09.691Z" }, - { url = "https://files.pythonhosted.org/packages/bf/f7/8a1436adeb00f7942dbd7645c26921654cdb938024fb249eb959c5446907/ruff-0.1.14-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1c8eca1a47b4150dc0fbec7fe68fc91c695aed798532a18dbb1424e61e9b721f", size = 6514682, upload-time = "2024-01-19T20:19:13.575Z" }, - { url = "https://files.pythonhosted.org/packages/e9/3f/c701e4fe507fc72900c6d72f797ab5f0b8cd3e5c32b8d1645a5e1c5f9b8e/ruff-0.1.14-py3-none-musllinux_1_2_i686.whl", hash = "sha256:62ce2ae46303ee896fc6811f63d6dabf8d9c389da0f3e3f2bce8bc7f15ef5488", size = 7191644, upload-time = "2024-01-19T20:19:17.533Z" }, - { url = "https://files.pythonhosted.org/packages/2c/b0/2d296522922a4d2f55ecf9ad496dee134bcffe29a72a8c0fefe738a82ea9/ruff-0.1.14-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b2027dde79d217b211d725fc833e8965dc90a16d0d3213f1298f97465956661b", size = 7593461, upload-time = "2024-01-19T20:19:20.354Z" }, - { url = "https://files.pythonhosted.org/packages/86/d9/7412e381f1d17e1438c2f513d4ff36dc6b5df3a1a62cb146d00017e9a54e/ruff-0.1.14-py3-none-win32.whl", hash = "sha256:722bafc299145575a63bbd6b5069cb643eaa62546a5b6398f82b3e4403329cab", size = 6683315, upload-time = "2024-01-19T20:19:23.843Z" }, - { url = "https://files.pythonhosted.org/packages/5b/72/bee209a32ef942bd884a80582de467d9cae98f8db0756c014dda16659541/ruff-0.1.14-py3-none-win_amd64.whl", hash = "sha256:e3d241aa61f92b0805a7082bd89a9990826448e4d0398f0e2bc8f05c75c63d99", size = 7316791, upload-time = "2024-01-19T20:19:26.804Z" }, - { url = "https://files.pythonhosted.org/packages/22/e5/ca6754d8a32a5a9e061d78d7c1491ec0c01f64b36125a6a27e2c5bf4f109/ruff-0.1.14-py3-none-win_arm64.whl", hash = "sha256:269302b31ade4cde6cf6f9dd58ea593773a37ed3f7b97e793c8594b262466b67", size = 6986910, upload-time = "2024-01-19T20:19:31.943Z" }, +version = "0.16.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/70/25/7113f6d5498888c5fb7db34081cba7d5971c4cb1bfb26819966eee68f003/ruff-0.16.1.tar.gz", hash = "sha256:fedad7c801dabd3fb9741d76aca39246e6ddd9ca446a015875207bf19f1e6bc7", size = 4877500, upload-time = "2026-07-30T19:37:01.379Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1b/bd/694da69368e0973de65df2ddc73ab18d43c469d5963d9b150911de6bc513/ruff-0.16.1-py3-none-linux_armv6l.whl", hash = "sha256:58edb313b88f0c5460a26adf5f39a37a3be789494a15e3e411e35fa78b89f9a0", size = 10839126, upload-time = "2026-07-30T19:36:13.697Z" }, + { url = "https://files.pythonhosted.org/packages/3f/f0/b626e5d5bd0dd9576263658ef12885e2288afd1029a48e26ffed65ec1ac1/ruff-0.16.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:fde5a99e2f97479af66edd6622c6d5a2a7592c77cf4153d9e4428f5eeb55b60c", size = 11070253, upload-time = "2026-07-30T19:36:17.14Z" }, + { url = "https://files.pythonhosted.org/packages/83/63/f40acfb6b35b88623e71684942b552c3edd96035f5d98f313815f7b277de/ruff-0.16.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e0d4c20532fca4f7fa609369161d968dd28f65d83dabbd61d8e9c7edbf7001f6", size = 10561425, upload-time = "2026-07-30T19:36:20.04Z" }, + { url = "https://files.pythonhosted.org/packages/aa/dd/14ec0e9c2b4d315547dd38765004b4863e354e1b52cb308272215d9f6f6d/ruff-0.16.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30affbcedf59ad5703d9c91f82266e02b47739f797e1a7b6e158e5526a6dae38", size = 10948879, upload-time = "2026-07-30T19:36:22.476Z" }, + { url = "https://files.pythonhosted.org/packages/33/e9/9d870cbae575030fdef595f04b4b97573c525b5497cce4f4498cf2f85446/ruff-0.16.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:24e9c631573cbca9d20f1283f8f479b2afa4a8503504822bd71a293889f16743", size = 10643691, upload-time = "2026-07-30T19:36:24.914Z" }, + { url = "https://files.pythonhosted.org/packages/c4/09/12743d544e2173f53ecd27217c65f90d2bc0f8424a66a60339e56bbc0457/ruff-0.16.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b41bdd48fb420987a9b5212e4957c26ad4abce401fa9ea9d4d85843727945f4f", size = 11435354, upload-time = "2026-07-30T19:36:28.447Z" }, + { url = "https://files.pythonhosted.org/packages/7f/89/a1652b2daee52083c9554a6333b678a8b01d0400f976827bb87857f9449a/ruff-0.16.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b0d1e1393b7648079e13669de1c1f4fde06d4583e84d8fd5c1551e0a77a2aa75", size = 12259033, upload-time = "2026-07-30T19:36:31.326Z" }, + { url = "https://files.pythonhosted.org/packages/16/96/ecdcb8c54ee7b123b487f807eb014e6e019155a0b81dfb669acd52f28ce3/ruff-0.16.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:07bf434b1c95f4e093be4532068ef4fcf00924eb2ade8796075980902d6fd54a", size = 11667981, upload-time = "2026-07-30T19:36:34.394Z" }, + { url = "https://files.pythonhosted.org/packages/cd/90/c52e12e0d862e9572f2a33aa227409143520abe53111e9a6babbac7b4af8/ruff-0.16.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39897739f112253ee4fdd2e8aa9a4f9ded99fb2be367d5f31dfa4ded6025584c", size = 11468183, upload-time = "2026-07-30T19:36:37.339Z" }, + { url = "https://files.pythonhosted.org/packages/2c/6b/4ffb7ad1d83eb16cf8cbb3c8815d3f11c88460fd162d4b372a2059be1c2a/ruff-0.16.1-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:82ae3c0c0d74daf17b968a10b7b3bb3ef297ab7de0c1f749646b25e690ccb150", size = 11470071, upload-time = "2026-07-30T19:36:39.91Z" }, + { url = "https://files.pythonhosted.org/packages/9c/72/32ae7db4c0b5e32ab611787caa19d1546800676d79f7483b7100a3561bf4/ruff-0.16.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4d5f2ed10f8242d83fc08d521301089364e3375375705356f20c0e31606ef3ef", size = 10919503, upload-time = "2026-07-30T19:36:42.65Z" }, + { url = "https://files.pythonhosted.org/packages/f7/ca/3d901ba6ad6fc38da39c3448fc6c59ac945679293a17c3ceb6d6c1cba13e/ruff-0.16.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a4665b309891f83f3e3c25447935f1213e9abbd4b5640af7a1f2def9f8d413c1", size = 10649861, upload-time = "2026-07-30T19:36:45.18Z" }, + { url = "https://files.pythonhosted.org/packages/92/79/894ef1ced26552d5f8c9cf6d85b0687840e1128c55aeab7b9c2d54a0d880/ruff-0.16.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:26e9ca5c9bc3971f20d3cf18a957f52ffd6a5f6564ff15c4912a144dcac22494", size = 11148137, upload-time = "2026-07-30T19:36:47.936Z" }, + { url = "https://files.pythonhosted.org/packages/2d/69/3609a09fa1cb46cc28b762363e440a354204e5dff01bd0c8d7437874d6b9/ruff-0.16.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:67e1e1e3fa4f0c82f0e36d4cd61e661f6e7a6196cb1aa92fe0828fa7b8f257cd", size = 11559211, upload-time = "2026-07-30T19:36:50.448Z" }, + { url = "https://files.pythonhosted.org/packages/fc/8a/fb22af2fd78a736e241fabf67e30ce1799a64244026377a49e133af90762/ruff-0.16.1-py3-none-win32.whl", hash = "sha256:d31765e131295b8445caf301e3e8a85b34d1b9b211b4109b7ba457888b051806", size = 10838258, upload-time = "2026-07-30T19:36:53.298Z" }, + { url = "https://files.pythonhosted.org/packages/d4/35/e57fd9fb5d423961df087a00b12d42c0a830288dc2f3b45ecca299158b4f/ruff-0.16.1-py3-none-win_amd64.whl", hash = "sha256:09b05e8b90c2cb06ad63464350e7a45e8e44a2dfe52072ebfba6666ca8d3f596", size = 11961111, upload-time = "2026-07-30T19:36:56.107Z" }, + { url = "https://files.pythonhosted.org/packages/cb/46/240ea004bf6dc4feb40e9832f2205a476a47dd5b8a3f8211a5fc5f95e20e/ruff-0.16.1-py3-none-win_arm64.whl", hash = "sha256:dbaadaac38c70239f056d306b7476f246b0bf000fa6b3876402acbf5b227eaf8", size = 11309414, upload-time = "2026-07-30T19:36:58.79Z" }, ] [[package]]