diff --git a/jupyterlab_code_formatter/formatters.py b/jupyterlab_code_formatter/formatters.py index 46c10b9..ac7d668 100644 --- a/jupyterlab_code_formatter/formatters.py +++ b/jupyterlab_code_formatter/formatters.py @@ -456,9 +456,11 @@ def format_code(self, code: str, notebook: bool, args: List[str] = [], **options class RuffFixFormatter(CommandLineFormatter): + ruff_args = ["check", "-eq", "--fix-only", "-"] + @property def label(self) -> str: - return f"Apply ruff Formatter" + return "Apply ruff fix" def __init__(self): try: @@ -467,7 +469,15 @@ def __init__(self): ruff_command = find_ruff_bin() except (ImportError, FileNotFoundError): ruff_command = "ruff" - self.command = [ruff_command, "check", "--fix-only", "-"] + self.command = [ruff_command, *self.ruff_args] + + +class RuffFormatFormatter(RuffFixFormatter): + @property + def label(self) -> str: + return "Apply ruff formatter" + + ruff_args = ["format", "-q", "-"] SERVER_FORMATTERS = { @@ -477,6 +487,7 @@ def __init__(self): "yapf": YapfFormatter(), "isort": IsortFormatter(), "ruff": RuffFixFormatter(), + "ruffformat": RuffFormatFormatter(), "formatR": FormatRFormatter(), "styler": StylerFormatter(), "scalafmt": CommandLineFormatter(command=["scalafmt", "--stdin"]), diff --git a/jupyterlab_code_formatter/tests/test_handlers.py b/jupyterlab_code_formatter/tests/test_handlers.py index 7493af1..4d118ca 100644 --- a/jupyterlab_code_formatter/tests/test_handlers.py +++ b/jupyterlab_code_formatter/tests/test_handlers.py @@ -588,11 +588,15 @@ async def test_can_rustfmt(request_format): # type: ignore[no-untyped-def] assert json_result["code"][0]["code"] == expected -@pytest.mark.xfail(reason="Rust toolchain isn't respected in test for some reason atm.") -async def test_can_apply_ruff(request_format): # type: ignore[no-untyped-def] - """Check that it can apply black with simple config.""" +IMPORT_SORTING_EXAMPLE = ( + "import numpy as np\nimport sys,os\nfrom enum import IntEnum\nfrom enum import auto" +) + + +async def test_can_apply_ruff_formatter(request_format): # type: ignore[no-untyped-def] + """Check that it can apply ruff with simple config.""" response: HTTPResponse = await request_format( - formatter="ruff", + formatter="ruffformat", code=[SIMPLE_VALID_PYTHON_CODE], options={}, ) @@ -602,3 +606,47 @@ async def test_can_apply_ruff(request_format): # type: ignore[no-untyped-def] expected_schema=EXPECTED_FROMAT_SCHEMA, ) assert json_result["code"][0]["code"] == "x = 22\ne = 1" + + +async def test_can_apply_ruff_import_fix(request_format): # type: ignore[no-untyped-def] + """Check that it can organize imports with ruff.""" + + given = "import foo\nimport numpy as np\nimport sys,os\nfrom enum import IntEnum\nfrom enum import auto" + expected = "import os\nimport sys\nfrom enum import IntEnum, auto\n\nimport numpy as np\n\nimport foo" + response: HTTPResponse = await request_format( + formatter="ruff", + code=[given], + options={ + "args": [ + "--select=I001", + "--config", + "lint.isort.known-first-party=['foo']", + ] + }, + ) + json_result = _check_http_code_and_schema( + response=response, + expected_code=200, + expected_schema=EXPECTED_FROMAT_SCHEMA, + ) + assert json_result["code"][0]["code"] == expected + + +async def test_can_apply_ruff_fix_unsafe(request_format): # type: ignore[no-untyped-def] + """Check that it can apply unsafe fixes.""" + + given = """if arg != None: + pass""" + expected = """if arg is not None: + pass""" + response: HTTPResponse = await request_format( + formatter="ruff", + code=[given], + options={"args": ["--select=E711", "--unsafe-fixes"]}, + ) + json_result = _check_http_code_and_schema( + response=response, + expected_code=200, + expected_schema=EXPECTED_FROMAT_SCHEMA, + ) + assert json_result["code"][0]["code"] == expected diff --git a/pyproject.toml b/pyproject.toml index 26cac4a..8ae98b2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,6 +53,7 @@ test = [ "yapf", "rpy2", "importlib_metadata; python_version<'3.8'", + "ruff", ] [tool.hatch.version] diff --git a/schema/settings.json b/schema/settings.json index f5d3c03..36fdf2f 100644 --- a/schema/settings.json +++ b/schema/settings.json @@ -208,6 +208,13 @@ "additionalProperties": false, "type": "object" }, + "ruffformat": { + "properties": { + "args": { "type": "array", "items": { "type": "string" } } + }, + "additionalProperties": false, + "type": "object" + }, "formatR": { "properties": { "comment": { @@ -407,11 +414,19 @@ } }, "ruff": { - "title": "Ruff Config", - "description": "Command line options to be passed to ruff.", + "title": "Ruff Check Config", + "description": "Command line options to be passed to ruff check. Default is to organise imports.", "$ref": "#/definitions/ruff", "default": { - "args": ["--select=I"] + "args": ["--select=I001"] + } + }, + "ruffformat": { + "title": "Ruff Format Config", + "description": "Command line options to be passed to ruff format.", + "$ref": "#/definitions/ruffformat", + "default": { + "args": [] } }, "suppressFormatterErrors": {