From 9acad2cac818970846999e28a1efaafd23fe64e8 Mon Sep 17 00:00:00 2001 From: Myles Scolnick Date: Sun, 2 Feb 2025 21:37:36 -0500 Subject: [PATCH] chore: enable preview rules from ruff (#3663) Enable `preview = true` to get some more helpful rules from ruff. --- marimo/_ast/pytest.py | 2 +- marimo/_cli/file_path.py | 10 ++++++---- marimo/_output/formatting.py | 4 ++-- marimo/_plugins/ui/_impl/tables/format.py | 7 ++++--- marimo/_save/ast.py | 2 +- marimo/_save/hash.py | 2 +- marimo/_server/api/endpoints/terminal.py | 4 ++-- marimo/_server/api/middleware.py | 13 ++++++------- marimo/_server/export/utils.py | 2 +- pyproject.toml | 5 ++++- tests/_output/test_md.py | 2 +- tests/_output/test_try_format.py | 4 +--- tests/_save/test_cache.py | 8 ++++---- tests/_server/api/endpoints/test_ai.py | 4 ++-- 14 files changed, 36 insertions(+), 33 deletions(-) diff --git a/marimo/_ast/pytest.py b/marimo/_ast/pytest.py index 8fcd67cfd40..ad7d4dcfb1e 100644 --- a/marimo/_ast/pytest.py +++ b/marimo/_ast/pytest.py @@ -52,7 +52,7 @@ def wrap_fn_for_pytest( ast.arg(arg, lineno=args[arg].lineno, col_offset=args[arg].col_offset) for arg in fixtures ] - (call_stub,) = call.keywords + (_call_stub,) = call.keywords call.keywords = [ ast.keyword( arg=arg, diff --git a/marimo/_cli/file_path.py b/marimo/_cli/file_path.py index b6de2fbd841..c22c8dc19ce 100644 --- a/marimo/_cli/file_path.py +++ b/marimo/_cli/file_path.py @@ -3,7 +3,6 @@ import abc import json -import logging import os import pathlib import urllib.parse @@ -12,10 +11,13 @@ from typing import Optional, Tuple from urllib.error import HTTPError +from marimo import _loggers from marimo._cli.print import green from marimo._utils.marimo_path import MarimoPath from marimo._utils.url import is_url +LOGGER = _loggers.marimo_logger() + def is_github_src(url: str, ext: str) -> bool: if not is_url(url): @@ -99,7 +101,7 @@ def read(self, name: str) -> Tuple[str, str]: @staticmethod def _is_static_marimo_notebook_url(url: str) -> tuple[bool, str]: def download(url: str) -> tuple[bool, str]: - logging.info("Downloading %s", url) + LOGGER.info("Downloading %s", url) request = urllib.request.Request( url, # User agent to avoid 403 Forbidden some bot protection @@ -278,11 +280,11 @@ def handle( def _create_tmp_file_from_content( content: str, name: str, temp_dir: TemporaryDirectory[str] ) -> str: - logging.info("Creating temporary file") + LOGGER.info("Creating temporary file") path_to_app = os.path.join(temp_dir.name, name) with open(path_to_app, "w") as f: f.write(content) - logging.info("App saved to %s", path_to_app) + LOGGER.info("App saved to %s", path_to_app) return path_to_app diff --git a/marimo/_output/formatting.py b/marimo/_output/formatting.py index 79daa98c62e..199bba68d24 100644 --- a/marimo/_output/formatting.py +++ b/marimo/_output/formatting.py @@ -325,14 +325,14 @@ def plain(value: Any) -> Plain: return Plain(value) +@dataclass class Plain: """ Wrapper around a value to indicate that it should be displayed without any opinionated formatting. """ - def __init__(self, child: Any): - self.child = child + child: Any @mddoc diff --git a/marimo/_plugins/ui/_impl/tables/format.py b/marimo/_plugins/ui/_impl/tables/format.py index ffce47e6d1e..9f66cf9445e 100644 --- a/marimo/_plugins/ui/_impl/tables/format.py +++ b/marimo/_plugins/ui/_impl/tables/format.py @@ -3,8 +3,11 @@ from typing import Callable, Dict, List, Union +from marimo import _loggers from marimo._plugins.core.web_component import JSONType +LOGGER = _loggers.marimo_logger() + FormatMapping = Dict[str, Union[str, Callable[..., JSONType]]] @@ -38,9 +41,7 @@ def format_value( if callable(formatter): return formatter(value) except Exception as e: - import logging - - logging.warning( + LOGGER.warning( f"Error formatting for value {value} in column {col}: {str(e)}" ) return value diff --git a/marimo/_save/ast.py b/marimo/_save/ast.py index 344c07fe29b..52ee42c88c3 100644 --- a/marimo/_save/ast.py +++ b/marimo/_save/ast.py @@ -80,7 +80,7 @@ def __init__(self, line: int, *arg: Any, **kwargs: Any) -> None: super().__init__(*arg, **kwargs) self.target_line = line - def generic_visit(self, node: ast.AST) -> tuple[ast.Module, ast.Module]: # type: ignore[override] + def generic_visit(self, node: ast.AST) -> tuple[ast.Module, ast.Module]: # type: ignore[override] pre_block = [] # There are a few strange edges cases like: diff --git a/marimo/_save/hash.py b/marimo/_save/hash.py index 550f666b734..93beb4cd064 100644 --- a/marimo/_save/hash.py +++ b/marimo/_save/hash.py @@ -968,7 +968,7 @@ def content_cache_attempt_from_base( refs, scope, ctx ) - refs, content, tmp_stateful_refs = hasher.collect_for_content_hash( + refs, _content, tmp_stateful_refs = hasher.collect_for_content_hash( refs, scope, ctx, scoped_refs, apply_hash=True ) # If the execution block covers this variable, then that's OK diff --git a/marimo/_server/api/endpoints/terminal.py b/marimo/_server/api/endpoints/terminal.py index 91ed3a173da..b20b74df90e 100644 --- a/marimo/_server/api/endpoints/terminal.py +++ b/marimo/_server/api/endpoints/terminal.py @@ -91,7 +91,7 @@ async def websocket_endpoint(websocket: WebSocket) -> None: child_pid, fd = pty.fork() if child_pid == 0: default_shell = os.environ.get("SHELL", "/bin/bash") - subprocess.run([default_shell], shell=True) ## noqa: ASYNC221 + subprocess.run([default_shell], shell=True) # noqa: ASYNC221 return reader_task = asyncio.create_task(_read_from_pty(fd, websocket)) @@ -118,5 +118,5 @@ async def websocket_endpoint(websocket: WebSocket) -> None: if writer_task and not writer_task.done(): writer_task.cancel() os.kill(child_pid, signal.SIGKILL) - os.waitpid(child_pid, 0) ## noqa: ASYNC222 + os.waitpid(child_pid, 0) # noqa: ASYNC222 LOGGER.debug("Terminal websocket closed") diff --git a/marimo/_server/api/middleware.py b/marimo/_server/api/middleware.py index d8dcc029c6e..5043fa9e732 100644 --- a/marimo/_server/api/middleware.py +++ b/marimo/_server/api/middleware.py @@ -2,6 +2,7 @@ from __future__ import annotations import asyncio +from dataclasses import dataclass from http.client import HTTPResponse, HTTPSConnection from typing import ( TYPE_CHECKING, @@ -162,14 +163,12 @@ async def dispatch( return response +@dataclass class _URLRequest: - def __init__( - self, url: str, method: str, headers: dict[str, str], data: Any - ): - self.full_url = url - self.method = method - self.headers = headers - self.data = data + full_url: str + method: str + headers: dict[str, str] + data: Any class _AsyncHTTPResponse: diff --git a/marimo/_server/export/utils.py b/marimo/_server/export/utils.py index 7c54e534589..892f6586b5e 100644 --- a/marimo/_server/export/utils.py +++ b/marimo/_server/export/utils.py @@ -13,7 +13,7 @@ def format_filename_title(filename: str) -> str: basename = os.path.basename(filename) - name, ext = os.path.splitext(basename) + name, _ext = os.path.splitext(basename) title = re.sub("[-_]", " ", name) return title.title() diff --git a/pyproject.toml b/pyproject.toml index 9aeff506f82..dd09142183d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -304,9 +304,11 @@ exclude = [ ] [tool.ruff.lint] +preview = true ignore = [ "G004", # Logging statement uses f-string "TC001", # Move application import into a type-checking block + "TC006", # Add quotes to type expression in typing.cast() "D301", # Use r""" if any backslashes in a docstring "PERF203", # try-except within a loop incurs performance overhead; not always possible "PERF401", # Use {message_str} to create a transformed list; at the cost of readability @@ -331,6 +333,7 @@ extend-select = [ "ARG", # flake8-bugbear "B", + # Performance "PERF", "ANN002", # missing-type-args "ANN003", # missing-type-kwargs @@ -386,7 +389,7 @@ unfixable = ["F401"] convention = "google" [tool.ruff.lint.per-file-ignores] -"**/{tests}/*" = ["ANN201", "ANN202", "T201", "D"] +"**/{tests}/*" = ["ANN201", "ANN202", "T201", "D", "F841"] "dagger/*" = ["TID252"] [tool.ruff.lint.isort] diff --git a/tests/_output/test_md.py b/tests/_output/test_md.py index 552cf08f55a..72c5d2293a6 100644 --- a/tests/_output/test_md.py +++ b/tests/_output/test_md.py @@ -69,7 +69,7 @@ def test_md_iconify() -> None: # Test multiple icons multiple_icons_input = "Icons: ::mdi:home:: ::fa:car:: ::lucide:settings::" - expected_output = 'Icons: ' ## noqa: E501 + expected_output = 'Icons: ' # noqa: E501 assert ( _md(multiple_icons_input, apply_markdown_class=False).text == expected_output diff --git a/tests/_output/test_try_format.py b/tests/_output/test_try_format.py index a52055c52ea..e239d9487b7 100644 --- a/tests/_output/test_try_format.py +++ b/tests/_output/test_try_format.py @@ -160,9 +160,7 @@ def test_plain_object(): result = try_format(obj) # Should fall back to string representation since we opted out of opinionated formatter assert is_html(result) - assert result.data.startswith( - "
<marimo._output.formatting.Plain object"
-    )
+    assert result.data.startswith("
Plain(")
 
 
 def test_opinionated_formatter():
diff --git a/tests/_save/test_cache.py b/tests/_save/test_cache.py
index 61615da1d36..521ab912e8b 100644
--- a/tests/_save/test_cache.py
+++ b/tests/_save/test_cache.py
@@ -75,7 +75,7 @@ def one() -> tuple[int]:
             with persistent_cache(name="one",
                                   _loader=MockLoader(
                                     data={"X": 7, "Y": 8})
-                                  ) as cache: # noqa: E501
+                                  ) as cache:  # noqa: E501
                 Y = 9
                 X = 10
             # fmt: on
@@ -114,8 +114,8 @@ def one() -> tuple[int]:
             # fmt: off
             b = [2]
             if True:
-              with persistent_cache("if", _loader=_loader):
-                  b = [
+              with persistent_cache("if", _loader=_loader):  # noqa: E111
+                  b = [  # noqa: E111
                       7
                   ]
             # fmt: on
@@ -222,7 +222,7 @@ def call(v):
 
             _loader = MockLoader()
             # fmt: off
-            with persistent_cache("else", _loader=_loader): call(False) # noqa: E701
+            with persistent_cache("else", _loader=_loader): call(False)  # noqa: E701
             # fmt: on
 
         with pytest.raises(BlockException):
diff --git a/tests/_server/api/endpoints/test_ai.py b/tests/_server/api/endpoints/test_ai.py
index b82ed7f4ef5..230f0433191 100644
--- a/tests/_server/api/endpoints/test_ai.py
+++ b/tests/_server/api/endpoints/test_ai.py
@@ -477,9 +477,9 @@ def no_google_ai_config(config: UserConfigManager):
 
 class TestStreamResponse(unittest.TestCase):
     def simulate_stream(self, contents: List[str]) -> Any:
+        @dataclass
         class MockContent:
-            def __init__(self, content: str) -> None:
-                self.content = content
+            content: str
 
         class MockDelta:
             def __init__(self, content: str) -> None: