Repository: adrienverge/yamllint (language: python)

Issue:
flake8 → ruff?
How about changing [flake8](https://flake8.pycqa.org/) to [ruff](https://astral.sh/ruff)? While I wasn't interested initially, ruff does gain momentum, and beyond speed, it replaces all Python linters by a single tool, and is less opinionated than say [black](https://black.readthedocs.io/).

These files would be slightly modified:
* [CONTRIBUTING.rst](https://github.com/adrienverge/yamllint/blob/152ba20f339588a872777eafb888f0073e83cafb/CONTRIBUTING.rst?plain=1#L26)
* [.github/workflows/ci.yaml](https://github.com/adrienverge/yamllint/blob/152ba20f339588a872777eafb888f0073e83cafb/.github/workflows/ci.yaml#L23-L26)
* [pyproject.toml](https://github.com/adrienverge/yamllint/blob/152ba20f339588a872777eafb888f0073e83cafb/pyproject.toml#L29-L30)

The only change in code suggested using the default settings of ruff:
* #627

In addition to being user as a linter, ruff _may_ be used as a formatter, as a less opinionated alternative to black (single quotes are OK).

Finally, it would tick a box in the issues reported by the [Repo-Review](https://learn.scientific-python.org/development/guides/repo-review/?repo=adrienverge%2Fyamllint&branch=master) of [Scientific Python](https://scientific-python.org/):
* [RF001](https://learn.scientific-python.org/development/guides/style#RF001): Has Ruff config
  Must have `[tool.ruff]` section in `pyproject.toml` or `ruff.toml`/`.ruff.toml`.


Discussion / hints:

Fix patch:
diff --git a/.flake8 b/.flake8
deleted file mode 100644
index 2b7958b8..00000000
--- a/.flake8
+++ /dev/null
@@ -1,4 +0,0 @@
-[flake8]
-import-order-style = pep8
-application-import-names = yamllint
-ignore = W503,W504
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 780831e9..506d610d 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -21,9 +21,9 @@ jobs:
       - name: Set up Python
         uses: actions/setup-python@v5
       - run:
-          pip install flake8 flake8-import-order sphinx rstcheck[sphinx] doc8
+          pip install ruff sphinx rstcheck[sphinx] doc8
       - run: pip install .
-      - run: flake8 .
+      - run: ruff .
       - run: doc8 $(git ls-files '*.rst')
       - run: rstcheck --ignore-directives automodule $(git ls-files '*.rst')
       - run: yamllint --strict $(git ls-files '*.yaml' '*.yml')
diff --git a/.ruff.toml b/.ruff.toml
new file mode 100644
index 00000000..943ec041
--- /dev/null
+++ b/.ruff.toml
@@ -0,0 +1,5 @@
+[lint]
+extend-select = ["I"]
+
+[lint.isort]
+known-third-party = ["tests"]
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 312c6d88..a1fde07b 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -23,7 +23,7 @@ Pull Request Process
 
    .. code:: bash
 
-    flake8 .
+    ruff .
 
    If you added/modified documentation:
 
diff --git a/docs/conf.py b/docs/conf.py
index 2c40177c..98cc2c40 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -1,8 +1,8 @@
 # yamllint documentation build configuration file, created by
 # sphinx-quickstart on Thu Jan 21 21:18:52 2016.
 
-import sys
 import os
+import sys
 from unittest.mock import MagicMock
 
 sys.path.insert(0, os.path.abspath('..'))
diff --git a/pyproject.toml b/pyproject.toml
index 63746f63..5fd24df5 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -26,9 +26,8 @@ dynamic = ["version"]
 [project.optional-dependencies]
 dev = [
     "doc8",
-    "flake8",
-    "flake8-import-order",
     "rstcheck[sphinx]",
+    "ruff",
     "sphinx",
 ]
 
diff --git a/yamllint/cli.py b/yamllint/cli.py
index dadce781..1050d95d 100644
--- a/yamllint/cli.py
+++ b/yamllint/cli.py
@@ -19,8 +19,7 @@
 import platform
 import sys
 
-from yamllint import APP_DESCRIPTION, APP_NAME, APP_VERSION
-from yamllint import linter
+from yamllint import APP_DESCRIPTION, APP_NAME, APP_VERSION, linter
 from yamllint.config import YamlLintConfig, YamlLintConfigError
 from yamllint.linter import PROBLEM_LEVELS
 
diff --git a/yamllint/linter.py b/yamllint/linter.py
index 0de1f716..a2faa061 100644
--- a/yamllint/linter.py
+++ b/yamllint/linter.py
@@ -13,14 +13,13 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-import re
 import io
+import re
 
 import yaml
 
 from yamllint import parser
 
-
 PROBLEM_LEVELS = {
     0: None,
     1: 'warning',
diff --git a/yamllint/rules/__init__.py b/yamllint/rules/__init__.py
index 606b37a4..815d4bcf 100644
--- a/yamllint/rules/__init__.py
+++ b/yamllint/rules/__init__.py
@@ -25,6 +25,7 @@
     document_start,
     empty_lines,
     empty_values,
+    float_values,
     hyphens,
     indentation,
     key_duplicates,
@@ -33,7 +34,6 @@
     new_line_at_end_of_file,
     new_lines,
     octal_values,
-    float_values,
     quoted_strings,
     trailing_spaces,
     truthy,
diff --git a/yamllint/rules/anchors.py b/yamllint/rules/anchors.py
index 343f38b7..d968461f 100644
--- a/yamllint/rules/anchors.py
+++ b/yamllint/rules/anchors.py
@@ -108,7 +108,6 @@
 
 from yamllint.linter import LintProblem
 
-
 ID = 'anchors'
 TYPE = 'token'
 CONF = {'forbid-undeclared-aliases': bool,
diff --git a/yamllint/rules/braces.py b/yamllint/rules/braces.py
index e77cda44..19f870a1 100644
--- a/yamllint/rules/braces.py
+++ b/yamllint/rules/braces.py
@@ -137,7 +137,6 @@
 from yamllint.linter import LintProblem
 from yamllint.rules.common import spaces_after, spaces_before
 
-
 ID = 'braces'
 TYPE = 'token'
 CONF = {'forbid': (bool, 'non-empty'),
diff --git a/yamllint/rules/brackets.py b/yamllint/rules/brackets.py
index 47d2ad4a..f1c08d5a 100644
--- a/yamllint/rules/brackets.py
+++ b/yamllint/rules/brackets.py
@@ -138,7 +138,6 @@
 from yamllint.linter import LintProblem
 from yamllint.rules.common import spaces_after, spaces_before
 
-
 ID = 'brackets'
 TYPE = 'token'
 CONF = {'forbid': (bool, 'non-empty'),
diff --git a/yamllint/rules/colons.py b/yamllint/rules/colons.py
index 7390e51b..2a181c66 100644
--- a/yamllint/rules/colons.py
+++ b/yamllint/rules/colons.py
@@ -82,7 +82,6 @@
 
 from yamllint.rules.common import is_explicit_key, spaces_after, spaces_before
 
-
 ID = 'colons'
 TYPE = 'token'
 CONF = {'max-spaces-before': int,
diff --git a/yamllint/rules/commas.py b/yamllint/rules/commas.py
index e87c8f94..baa8b7dd 100644
--- a/yamllint/rules/commas.py
+++ b/yamllint/rules/commas.py
@@ -106,7 +106,6 @@
 from yamllint.linter import LintProblem
 from yamllint.rules.common import spaces_after, spaces_before
 
-
 ID = 'commas'
 TYPE = 'token'
 CONF = {'max-spaces-before': int,
diff --git a/yamllint/rules/comments.py b/yamllint/rules/comments.py
index 1259dea6..7e4f04c1 100644
--- a/yamllint/rules/comments.py
+++ b/yamllint/rules/comments.py
@@ -75,7 +75,6 @@
 
 from yamllint.linter import LintProblem
 
-
 ID = 'comments'
 TYPE = 'comment'
 CONF = {'require-starting-space': bool,
diff --git a/yamllint/rules/comments_indentation.py b/yamllint/rules/comments_indentation.py
index 569abee7..8bcda4d2 100644
--- a/yamllint/rules/comments_indentation.py
+++ b/yamllint/rules/comments_indentation.py
@@ -79,7 +79,6 @@
 from yamllint.linter import LintProblem
 from yamllint.rules.common import get_line_indent
 
-
 ID = 'comments-indentation'
 TYPE = 'comment'
 
diff --git a/yamllint/rules/document_end.py b/yamllint/rules/document_end.py
index 2337484c..e1ce2a14 100644
--- a/yamllint/rules/document_end.py
+++ b/yamllint/rules/document_end.py
@@ -85,7 +85,6 @@
 
 from yamllint.linter import LintProblem
 
-
 ID = 'document-end'
 TYPE = 'token'
 CONF = {'present': bool}
diff --git a/yamllint/rules/document_start.py b/yamllint/rules/document_start.py
index f1d66673..225d7c3d 100644
--- a/yamllint/rules/document_start.py
+++ b/yamllint/rules/document_start.py
@@ -75,7 +75,6 @@
 
 from yamllint.linter import LintProblem
 
-
 ID = 'document-start'
 TYPE = 'token'
 CONF = {'present': bool}
diff --git a/yamllint/rules/empty_lines.py b/yamllint/rules/empty_lines.py
index eca78125..7ccbedf0 100644
--- a/yamllint/rules/empty_lines.py
+++ b/yamllint/rules/empty_lines.py
@@ -61,7 +61,6 @@
 
 from yamllint.linter import LintProblem
 
-
 ID = 'empty-lines'
 TYPE = 'line'
 CONF = {'max': int,
diff --git a/yamllint/rules/empty_values.py b/yamllint/rules/empty_values.py
index 6c8328b7..c1ff4f20 100644
--- a/yamllint/rules/empty_values.py
+++ b/yamllint/rules/empty_values.py
@@ -105,7 +105,6 @@
 
 from yamllint.linter import LintProblem
 
-
 ID = 'empty-values'
 TYPE = 'token'
 CONF = {'forbid-in-block-mappings': bool,
diff --git a/yamllint/rules/float_values.py b/yamllint/rules/float_values.py
index a5852c56..77a243bf 100644
--- a/yamllint/rules/float_values.py
+++ b/yamllint/rules/float_values.py
@@ -90,7 +90,6 @@
 
 from yamllint.linter import LintProblem
 
-
 ID = 'float-values'
 TYPE = 'token'
 CONF = {
diff --git a/yamllint/rules/hyphens.py b/yamllint/rules/hyphens.py
index 50e4d6d9..54a96bf1 100644
--- a/yamllint/rules/hyphens.py
+++ b/yamllint/rules/hyphens.py
@@ -79,7 +79,6 @@
 
 from yamllint.rules.common import spaces_after
 
-
 ID = 'hyphens'
 TYPE = 'token'
 CONF = {'max-spaces-after': int}
diff --git a/yamllint/rules/indentation.py b/yamllint/rules/indentation.py
index d839d5aa..bde6fa38 100644
--- a/yamllint/rules/indentation.py
+++ b/yamllint/rules/indentation.py
@@ -204,7 +204,6 @@
 from yamllint.linter import LintProblem
 from yamllint.rules.common import get_real_end_line, is_explicit_key
 
-
 ID = 'indentation'
 TYPE = 'token'
 CONF = {'spaces': (int, 'consistent'),
diff --git a/yamllint/rules/key_duplicates.py b/yamllint/rules/key_duplicates.py
index bc6550f8..638ac1e0 100644
--- a/yamllint/rules/key_duplicates.py
+++ b/yamllint/rules/key_duplicates.py
@@ -93,7 +93,6 @@
 
 from yamllint.linter import LintProblem
 
-
 ID = 'key-duplicates'
 TYPE = 'token'
 CONF = {'forbid-duplicated-merge-keys': bool}
diff --git a/yamllint/rules/key_ordering.py b/yamllint/rules/key_ordering.py
index 7fa9597a..ec0716d9 100644
--- a/yamllint/rules/key_ordering.py
+++ b/yamllint/rules/key_ordering.py
@@ -86,7 +86,6 @@
 
 from yamllint.linter import LintProblem
 
-
 ID = 'key-ordering'
 TYPE = 'token'
 
diff --git a/yamllint/rules/line_length.py b/yamllint/rules/line_length.py
index e7cc8bc2..8214d74e 100644
--- a/yamllint/rules/line_length.py
+++ b/yamllint/rules/line_length.py
@@ -101,7 +101,6 @@
 
 from yamllint.linter import LintProblem
 
-
 ID = 'line-length'
 TYPE = 'line'
 CONF = {'max': int,
diff --git a/yamllint/rules/new_line_at_end_of_file.py b/yamllint/rules/new_line_at_end_of_file.py
index 302cfe6a..f49edb95 100644
--- a/yamllint/rules/new_line_at_end_of_file.py
+++ b/yamllint/rules/new_line_at_end_of_file.py
@@ -25,7 +25,6 @@
 
 from yamllint.linter import LintProblem
 
-
 ID = 'new-line-at-end-of-file'
 TYPE = 'line'
 
diff --git a/yamllint/rules/new_lines.py b/yamllint/rules/new_lines.py
index 4e3023e4..2ee5512a 100644
--- a/yamllint/rules/new_lines.py
+++ b/yamllint/rules/new_lines.py
@@ -37,7 +37,6 @@
 
 from yamllint.linter import LintProblem
 
-
 ID = 'new-lines'
 TYPE = 'line'
 CONF = {'type': ('unix', 'dos', 'platform')}
diff --git a/yamllint/rules/octal_values.py b/yamllint/rules/octal_values.py
index eb24c81f..e94e4bff 100644
--- a/yamllint/rules/octal_values.py
+++ b/yamllint/rules/octal_values.py
@@ -76,7 +76,6 @@
 
 from yamllint.linter import LintProblem
 
-
 ID = 'octal-values'
 TYPE = 'token'
 CONF = {'forbid-implicit-octal': bool,
diff --git a/yamllint/rules/trailing_spaces.py b/yamllint/rules/trailing_spaces.py
index 22957147..b5455f32 100644
--- a/yamllint/rules/trailing_spaces.py
+++ b/yamllint/rules/trailing_spaces.py
@@ -40,7 +40,6 @@
 
 from yamllint.linter import LintProblem
 
-
 ID = 'trailing-spaces'
 TYPE = 'line'
 
diff --git a/yamllint/rules/truthy.py b/yamllint/rules/truthy.py
index d19f6eaf..4b7179ab 100644
--- a/yamllint/rules/truthy.py
+++ b/yamllint/rules/truthy.py
@@ -125,7 +125,6 @@
 
 from yamllint.linter import LintProblem
 
-
 TRUTHY = ['YES', 'Yes', 'yes',
           'NO', 'No', 'no',
           'TRUE', 'True', 'true',


Test patch:
diff --git a/tests/__init__.py b/tests/__init__.py
index da1cd75d..d8c46fc3 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -15,5 +15,4 @@
 
 import locale
 
-
 locale.setlocale(locale.LC_ALL, 'C')
diff --git a/tests/common.py b/tests/common.py
index 640be53b..1aef9e62 100644
--- a/tests/common.py
+++ b/tests/common.py
@@ -21,8 +21,8 @@
 
 import yaml
 
-from yamllint.config import YamlLintConfig
 from yamllint import linter
+from yamllint.config import YamlLintConfig
 
 
 class RuleTestCase(unittest.TestCase):
diff --git a/tests/rules/test_indentation.py b/tests/rules/test_indentation.py
index ad1aeaff..3e929bf2 100644
--- a/tests/rules/test_indentation.py
+++ b/tests/rules/test_indentation.py
@@ -15,7 +15,7 @@
 
 from tests.common import RuleTestCase
 
-from yamllint.parser import token_or_comment_generator, Comment
+from yamllint.parser import Comment, token_or_comment_generator
 from yamllint.rules.indentation import check
 
 
diff --git a/tests/test_cli.py b/tests/test_cli.py
index f8493fe2..bcdd000b 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -13,7 +13,6 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from io import StringIO
 import fcntl
 import locale
 import os
@@ -22,11 +21,11 @@
 import sys
 import tempfile
 import unittest
+from io import StringIO
 
 from tests.common import build_temp_workspace, temp_workspace
 
-from yamllint import cli
-from yamllint import config
+from yamllint import cli, config
 
 
 class RunContext:
diff --git a/tests/test_config.py b/tests/test_config.py
index 13d7ab3b..73f7c01e 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -13,18 +13,17 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from io import StringIO
 import os
 import shutil
 import sys
 import tempfile
 import unittest
+from io import StringIO
 
 from tests.common import build_temp_workspace
 
+from yamllint import cli, config
 from yamllint.config import YamlLintConfigError
-from yamllint import cli
-from yamllint import config
 
 
 class SimpleConfigTestCase(unittest.TestCase):
diff --git a/tests/test_linter.py b/tests/test_linter.py
index 9855120b..ea509d8a 100644
--- a/tests/test_linter.py
+++ b/tests/test_linter.py
@@ -16,8 +16,8 @@
 import io
 import unittest
 
-from yamllint.config import YamlLintConfig
 from yamllint import linter
+from yamllint.config import YamlLintConfig
 
 
 class LinterTestCase(unittest.TestCase):
diff --git a/tests/test_module.py b/tests/test_module.py
index 299e153d..7f4f62ba 100644
--- a/tests/test_module.py
+++ b/tests/test_module.py
@@ -16,11 +16,10 @@
 import os
 import shutil
 import subprocess
-import tempfile
 import sys
+import tempfile
 import unittest
 
-
 PYTHON = sys.executable or 'python'
 
 
diff --git a/tests/test_parser.py b/tests/test_parser.py
index dbeb36b4..c2b598ac 100644
--- a/tests/test_parser.py
+++ b/tests/test_parser.py
@@ -17,9 +17,14 @@
 
 import yaml
 
-from yamllint.parser import (line_generator, token_or_comment_generator,
-                             token_or_comment_or_line_generator,
-                             Line, Token, Comment)
+from yamllint.parser import (
+    Comment,
+    Line,
+    Token,
+    line_generator,
+    token_or_comment_generator,
+    token_or_comment_or_line_generator,
+)
 
 
 class ParserTestCase(unittest.TestCase):
diff --git a/tests/test_spec_examples.py b/tests/test_spec_examples.py
index ac68e12e..eb1582ef 100644
--- a/tests/test_spec_examples.py
+++ b/tests/test_spec_examples.py
@@ -17,7 +17,6 @@
 
 from tests.common import RuleTestCase
 
-
 # This file checks examples from YAML 1.2 specification [1] against yamllint.
 #
 # [1]: http://www.yaml.org/spec/1.2/spec.html