From ff4f4aaeabd8b2bdd944184bb1007c8c4abbd3ad Mon Sep 17 00:00:00 2001 From: trag1c Date: Fri, 3 Nov 2023 21:40:22 +0100 Subject: [PATCH 1/8] Added tabs plugin --- mkdocs.template.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mkdocs.template.yml b/mkdocs.template.yml index 23d417404a00c..ea4ec3a018a13 100644 --- a/mkdocs.template.yml +++ b/mkdocs.template.yml @@ -55,6 +55,8 @@ markdown_extensions: custom_checkbox: true - pymdownx.highlight: anchor_linenums: true + - pymdownx.tabbed: + alternate_style: true plugins: - search extra_css: From 1bd0414c366ced81d85b0e37af771220bd8b21bb Mon Sep 17 00:00:00 2001 From: trag1c Date: Fri, 3 Nov 2023 21:40:48 +0100 Subject: [PATCH 2/8] Updated docs to use tabs --- docs/configuration.md | 373 ++++++++++++++++++++++++++---------------- docs/faq.md | 143 +++++++++++----- docs/formatter.md | 29 +++- docs/linter.md | 157 +++++++++++++----- docs/preview.md | 131 +++++++++++---- docs/tutorial.md | 148 ++++++++++++----- 6 files changed, 676 insertions(+), 305 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 68de7de2592d1..631e77803de23 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -7,147 +7,220 @@ semantics are the same. For a complete enumeration of the available configuration options, see [_Settings_](settings.md). -## Using `pyproject.toml` - If left unspecified, Ruff's default configuration is equivalent to: -```toml -[tool.ruff] -# Exclude a variety of commonly ignored directories. -exclude = [ - ".bzr", - ".direnv", - ".eggs", - ".git", - ".git-rewrite", - ".hg", - ".mypy_cache", - ".nox", - ".pants.d", - ".pytype", - ".ruff_cache", - ".svn", - ".tox", - ".venv", - "__pypackages__", - "_build", - "buck-out", - "build", - "dist", - "node_modules", - "venv", -] - -# Same as Black. -line-length = 88 -indent-width = 4 - -# Assume Python 3.8 -target-version = "py38" +=== "pyproject.toml" + + ```toml + [tool.ruff] + # Exclude a variety of commonly ignored directories. + exclude = [ + ".bzr", + ".direnv", + ".eggs", + ".git", + ".git-rewrite", + ".hg", + ".mypy_cache", + ".nox", + ".pants.d", + ".pytype", + ".ruff_cache", + ".svn", + ".tox", + ".venv", + "__pypackages__", + "_build", + "buck-out", + "build", + "dist", + "node_modules", + "venv", + ] + + # Same as Black. + line-length = 88 + indent-width = 4 + + # Assume Python 3.8 + target-version = "py38" + + [tool.ruff.lint] + # Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default. + # Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or + # McCabe complexity (`C901`) by default. + select = ["E4", "E7", "E9", "F"] + ignore = [] + + # Allow fix for all enabled rules (when `--fix`) is provided. + fixable = ["ALL"] + unfixable = [] + + # Allow unused variables when underscore-prefixed. + dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" + + [tool.ruff.format] + # Like Black, use double quotes for strings. + quote-style = "double" + + # Like Black, indent with spaces, rather than tabs. + indent-style = "space" + + # Like Black, respect magic trailing commas. + skip-magic-trailing-comma = false + + # Like Black, automatically detect the appropriate line ending. + line-ending = "auto" + ``` + +=== "ruff.toml" + + ```toml + # Exclude a variety of commonly ignored directories. + exclude = [ + ".bzr", + ".direnv", + ".eggs", + ".git", + ".git-rewrite", + ".hg", + ".mypy_cache", + ".nox", + ".pants.d", + ".pytype", + ".ruff_cache", + ".svn", + ".tox", + ".venv", + "__pypackages__", + "_build", + "buck-out", + "build", + "dist", + "node_modules", + "venv", + ] + + # Same as Black. + line-length = 88 + indent-width = 4 + + # Assume Python 3.8 + target-version = "py38" + + [lint] + # Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default. + # Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or + # McCabe complexity (`C901`) by default. + select = ["E4", "E7", "E9", "F"] + ignore = [] + + # Allow fix for all enabled rules (when `--fix`) is provided. + fixable = ["ALL"] + unfixable = [] + + # Allow unused variables when underscore-prefixed. + dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" + + [format] + # Like Black, use double quotes for strings. + quote-style = "double" + + # Like Black, indent with spaces, rather than tabs. + indent-style = "space" + + # Like Black, respect magic trailing commas. + skip-magic-trailing-comma = false + + # Like Black, automatically detect the appropriate line ending. + line-ending = "auto" + ``` -[tool.ruff.lint] -# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default. -# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or -# McCabe complexity (`C901`) by default. -select = ["E4", "E7", "E9", "F"] -ignore = [] +As an example, the following would configure Ruff to: -# Allow fix for all enabled rules (when `--fix`) is provided. -fixable = ["ALL"] -unfixable = [] +=== "pyproject.toml" -# Allow unused variables when underscore-prefixed. -dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" + ```toml + [tool.ruff.lint] + # 1. Enable flake8-bugbear (`B`) rules, in addition to the defaults. + select = ["E4", "E7", "E9", "F", "B"] -[tool.ruff.format] -# Like Black, use double quotes for strings. -quote-style = "double" + # 2. Avoid enforcing line-length violations (`E501`) + ignore = ["E501"] -# Like Black, indent with spaces, rather than tabs. -indent-style = "space" + # 3. Avoid trying to fix flake8-bugbear (`B`) violations. + unfixable = ["B"] -# Like Black, respect magic trailing commas. -skip-magic-trailing-comma = false + # 4. Ignore `E402` (import violations) in all `__init__.py` files, and in select subdirectories. + [tool.ruff.lint.per-file-ignores] + "__init__.py" = ["E402"] + "**/{tests,docs,tools}/*" = ["E402"] -# Like Black, automatically detect the appropriate line ending. -line-ending = "auto" -``` + [tool.ruff.format] + # 5. Use single quotes for non-triple-quoted strings. + quote-style = "single" + ``` -As an example, the following would configure Ruff to: +=== "ruff.toml" -```toml -[tool.ruff.lint] -# 1. Enable flake8-bugbear (`B`) rules, in addition to the defaults. -select = ["E4", "E7", "E9", "F", "B"] + ```toml + [lint] + # 1. Enable flake8-bugbear (`B`) rules, in addition to the defaults. + select = ["E4", "E7", "E9", "F", "B"] -# 2. Avoid enforcing line-length violations (`E501`) -ignore = ["E501"] + # 2. Avoid enforcing line-length violations (`E501`) + ignore = ["E501"] -# 3. Avoid trying to fix flake8-bugbear (`B`) violations. -unfixable = ["B"] + # 3. Avoid trying to fix flake8-bugbear (`B`) violations. + unfixable = ["B"] -# 4. Ignore `E402` (import violations) in all `__init__.py` files, and in select subdirectories. -[tool.ruff.lint.per-file-ignores] -"__init__.py" = ["E402"] -"**/{tests,docs,tools}/*" = ["E402"] + # 4. Ignore `E402` (import violations) in all `__init__.py` files, and in select subdirectories. + [lint.per-file-ignores] + "__init__.py" = ["E402"] + "**/{tests,docs,tools}/*" = ["E402"] -[tool.ruff.format] -# 5. Use single quotes for non-triple-quoted strings. -quote-style = "single" -``` + [format] + # 5. Use single quotes for non-triple-quoted strings. + quote-style = "single" + ``` Linter plugin configurations are expressed as subsections, e.g.: -```toml -[tool.ruff.lint] -# Add "Q" to the list of enabled codes. -select = ["E4", "E7", "E9", "F", "Q"] +=== "pyproject.toml" -[tool.ruff.lint.flake8-quotes] -docstring-quotes = "double" -``` + ```toml + [tool.ruff.lint] + # Add "Q" to the list of enabled codes. + select = ["E4", "E7", "E9", "F", "Q"] -For a complete enumeration of the available configuration options, see [_Settings_](settings.md). + [tool.ruff.lint.flake8-quotes] + docstring-quotes = "double" + ``` -## Using `ruff.toml` +=== "ruff.toml" -As an alternative to `pyproject.toml`, Ruff will also respect a `ruff.toml` (or `.ruff.toml`) file, -which implements an equivalent schema (though in the `ruff.toml` and `.ruff.toml` versions, the -`[tool.ruff]` header is omitted). + ```toml + [lint] + # Add "Q" to the list of enabled codes. + select = ["E4", "E7", "E9", "F", "Q"] -For example, the `pyproject.toml` described above would be represented via the following -`ruff.toml` (or `.ruff.toml`): + [lint.flake8-quotes] + docstring-quotes = "double" + ``` -```toml -[lint] -# Enable flake8-bugbear (`B`) rules. -select = ["E4", "E7", "E9", "F", "B"] - -# Never enforce `E501` (line length violations). -ignore = ["E501"] - -# Avoid trying to fix flake8-bugbear (`B`) violations. -unfixable = ["B"] - -# Ignore `E402` (import violations) in all `__init__.py` files, and in select subdirectories. -[lint.per-file-ignores] -"__init__.py" = ["E402"] -"**/{tests,docs,tools}/*" = ["E402"] - -[format] -# Use single quotes for non-triple-quoted strings. -quote-style = "single" -``` +Ruff respects `pyproject.toml`, `ruff.toml`, and `.ruff.toml` files. All three implement +an equivalent schema (though in the `ruff.toml` and `.ruff.toml` versions, the +`[tool.ruff]` header is omitted). For a complete enumeration of the available configuration options, see [_Settings_](settings.md). -## `pyproject.toml` discovery +## Config file discovery Similar to [ESLint](https://eslint.org/docs/latest/user-guide/configuring/configuration-files#cascading-and-hierarchy), -Ruff supports hierarchical configuration, such that the "closest" `pyproject.toml` file in the -directory hierarchy is used for every individual file, with all paths in the `pyproject.toml` file +Ruff supports hierarchical configuration, such that the "closest" config file in the +directory hierarchy is used for every individual file, with all paths in the config file (e.g., `exclude` globs, `src` paths) being resolved relative to the directory containing that -`pyproject.toml` file. +config file. There are a few exceptions to these rules: @@ -156,47 +229,69 @@ There are a few exceptions to these rules: 1. If a configuration file is passed directly via `--config`, those settings are used for _all_ analyzed files, and any relative paths in that configuration file (like `exclude` globs or `src` paths) are resolved relative to the _current_ working directory. -1. If no `pyproject.toml` file is found in the filesystem hierarchy, Ruff will fall back to using +1. If no config file is found in the filesystem hierarchy, Ruff will fall back to using a default configuration. If a user-specific configuration file exists at `${config_dir}/ruff/pyproject.toml`, that file will be used instead of the default configuration, with `${config_dir}` being determined via the [`dirs`](https://docs.rs/dirs/4.0.0/dirs/fn.config_dir.html) crate, and all relative paths being again resolved relative to the _current working directory_. -1. Any `pyproject.toml`-supported settings that are provided on the command-line (e.g., via +1. Any config-file-supported settings that are provided on the command-line (e.g., via `--select`) will override the settings in _every_ resolved configuration file. Unlike [ESLint](https://eslint.org/docs/latest/user-guide/configuring/configuration-files#cascading-and-hierarchy), Ruff does not merge settings across configuration files; instead, the "closest" configuration file is used, and any parent configuration files are ignored. In lieu of this implicit cascade, Ruff supports an [`extend`](settings.md#extend) field, which allows you to inherit the settings from another -`pyproject.toml` file, like so: +config file, like so: -```toml -[tool.ruff] -# Extend the `pyproject.toml` file in the parent directory... -extend = "../pyproject.toml" +=== "pyproject.toml" -# ...but use a different line length. -line-length = 100 -``` + ```toml + [tool.ruff] + # Extend the `pyproject.toml` file in the parent directory... + extend = "../pyproject.toml" + + # ...but use a different line length. + line-length = 100 + ``` + +=== "ruff.toml" -All of the above rules apply equivalently to `ruff.toml` and `.ruff.toml` files. If Ruff detects -multiple configuration files in the same directory, the `.ruff.toml` file will take precedence over -the `ruff.toml` file, and the `ruff.toml` file will take precedence over the `pyproject.toml` file. + ```toml + # Extend the `ruff.toml` file in the parent directory... + extend = "../ruff.toml" + + # ...but use a different line length. + line-length = 100 + ``` + +All of the above rules apply equivalently to `pyproject.toml`, `ruff.toml`, and `.ruff.toml` files. +If Ruff detects multiple configuration files in the same directory, the `.ruff.toml` file will take +precedence over the `ruff.toml` file, and the `ruff.toml` file will take precedence over +the `pyproject.toml` file. ## Python file discovery When passed a path on the command-line, Ruff will automatically discover all Python files in that path, taking into account the [`exclude`](settings.md#exclude) and [`extend-exclude`](settings.md#extend-exclude) -settings in each directory's `pyproject.toml` file. +settings in each directory's configuration file. Files can also be selectively excluded from linting or formatting by scoping the `exclude` setting to the tool-specific configuration tables. For example, the following would prevent `ruff` from formatting `.pyi` files, but would continue to include them in linting: -```toml -[tool.ruff.format] -exclude = ["*.pyi"] -``` +=== "pyproject.toml" + + ```toml + [tool.ruff.format] + exclude = ["*.pyi"] + ``` + +=== "ruff.toml" + + ```toml + [format] + exclude = ["*.pyi"] + ``` By default, Ruff will also skip any files that are omitted via `.ignore`, `.gitignore`, `.git/info/exclude`, and global `gitignore` files (see: [`respect-gitignore`](settings.md#respect-gitignore)). @@ -211,10 +306,18 @@ Ruff has built-in support for [Jupyter Notebooks](https://jupyter.org/). To opt in to linting and formatting Jupyter Notebook (`.ipynb`) files, add the `*.ipynb` pattern to your [`extend-include`](settings.md#extend-include) setting, like so: -```toml -[tool.ruff] -extend-include = ["*.ipynb"] -``` +=== "pyproject.toml" + + ```toml + [tool.ruff] + extend-include = ["*.ipynb"] + ``` + +=== "ruff.toml' + + ```toml + extend-include = ["*.ipynb"] + ``` This will prompt Ruff to discover Jupyter Notebook (`.ipynb`) files in any specified directories, then lint and format them accordingly. @@ -245,10 +348,6 @@ Alternatively, pass the notebook file(s) to `ruff` on the command-line directly. `ruff check /path/to/notebook.ipynb` will always lint `notebook.ipynb`. Similarly, `ruff format /path/to/notebook.ipynb` will always format `notebook.ipynb`. -All of the above rules apply equivalently to `ruff.toml` and `.ruff.toml` files. If Ruff detects -multiple configuration files in the same directory, the `.ruff.toml` file will take precedence over -the `ruff.toml` file, and the `ruff.toml` file will take precedence over the `pyproject.toml` file. - ## Command-line interface Some configuration options can be provided via the command-line, such as those related to rule diff --git a/docs/faq.md b/docs/faq.md index eef55607d3df3..4e9ec14d2af1b 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -265,24 +265,47 @@ them. You can find the supported settings in the [API reference](settings.md#iso For example, you can set [`known-first-party`](settings.md#known-first-party--isort-known-first-party-) like so: -```toml -[tool.ruff.lint] -select = [ - # Pyflakes - "F", - # Pycodestyle - "E", - "W", - # isort - "I001" -] - -# Note: Ruff supports a top-level `src` option in lieu of isort's `src_paths` setting. -src = ["src", "tests"] - -[tool.ruff.lint.isort] -known-first-party = ["my_module1", "my_module2"] -``` +=== "pyproject.toml" + + ```toml + [tool.ruff.lint] + select = [ + # Pyflakes + "F", + # Pycodestyle + "E", + "W", + # isort + "I001" + ] + + # Note: Ruff supports a top-level `src` option in lieu of isort's `src_paths` setting. + src = ["src", "tests"] + + [tool.ruff.lint.isort] + known-first-party = ["my_module1", "my_module2"] + ``` + +=== "ruff.toml" + + ```toml + [lint] + select = [ + # Pyflakes + "F", + # Pycodestyle + "E", + "W", + # isort + "I001" + ] + + # Note: Ruff supports a top-level `src` option in lieu of isort's `src_paths` setting. + src = ["src", "tests"] + + [lint.isort] + known-first-party = ["my_module1", "my_module2"] + ``` ## How does Ruff determine which of my imports are first-party, third-party, etc.? @@ -315,11 +338,20 @@ the `--config` option, in which case, the current working directory is used as t In this case, Ruff would only check the top-level directory. Instead, we can configure Ruff to consider `src` as a first-party source like so: -```toml -[tool.ruff] -# All paths are relative to the project root, which is the directory containing the pyproject.toml. -src = ["src"] -``` +=== "pyproject.toml" + + ```toml + [tool.ruff] + # All paths are relative to the project root, which is the directory containing the pyproject.toml. + src = ["src"] + ``` + +=== "ruff.toml" + + ```toml + # All paths are relative to the project root, which is the directory containing the pyproject.toml. + src = ["src"] + ``` If your `pyproject.toml`, `ruff.toml`, or `.ruff.toml` extends another configuration file, Ruff will still use the directory containing your `pyproject.toml`, `ruff.toml`, or `.ruff.toml` file as @@ -349,10 +381,18 @@ Ruff has built-in support for linting [Jupyter Notebooks](https://jupyter.org/). To opt in to linting Jupyter Notebook (`.ipynb`) files, add the `*.ipynb` pattern to your [`extend-include`](settings.md#extend-include) setting, like so: -```toml -[tool.ruff] -extend-include = ["*.ipynb"] -``` +=== "pyproject.toml" + + ```toml + [tool.ruff] + extend-include = ["*.ipynb"] + ``` + +=== "ruff.toml" + + ```toml + extend-include = ["*.ipynb"] + ``` This will prompt Ruff to discover Jupyter Notebook (`.ipynb`) files in any specified directories, then lint and format them accordingly. @@ -378,12 +418,21 @@ Found 3 errors. ## Does Ruff support NumPy- or Google-style docstrings? Yes! To enforce a docstring convention, add a [`convention`](settings.md#convention--pydocstyle-convention-) -setting following to your `pyproject.toml`: +setting following to your configuration file: -```toml -[tool.ruff.lint.pydocstyle] -convention = "google" # Accepts: "google", "numpy", or "pep257". -``` +=== "pyproject.toml" + + ```toml + [tool.ruff.lint.pydocstyle] + convention = "google" # Accepts: "google", "numpy", or "pep257". + ``` + +=== "ruff.toml" + + ```toml + [lint.pydocstyle] + convention = "google" # Accepts: "google", "numpy", or "pep257". + ``` For example, if you're coming from flake8-docstrings, and your originating configuration uses `--docstring-convention=numpy`, you'd instead set `convention = "numpy"` in your `pyproject.toml`, @@ -392,15 +441,29 @@ as above. Alongside [`convention`](settings.md#convention--pydocstyle-convention-), you'll want to explicitly enable the `D` rule code prefix, since the `D` rules are not enabled by default: -```toml -[tool.ruff.lint] -select = [ - "D", -] +=== "pyproject.toml" -[tool.ruff.lint.pydocstyle] -convention = "google" -``` + ```toml + [tool.ruff.lint] + select = [ + "D", + ] + + [tool.ruff.lint.pydocstyle] + convention = "google" + ``` + +=== "ruff.toml" + + ```toml + [lint] + select = [ + "D", + ] + + [lint.pydocstyle] + convention = "google" + ``` Setting a [`convention`](settings.md#convention--pydocstyle-convention-) force-disables any rules that are incompatible with that convention, no matter how they're provided, which avoids accidental diff --git a/docs/formatter.md b/docs/formatter.md index 79279139199af..caa7459e55b3d 100644 --- a/docs/formatter.md +++ b/docs/formatter.md @@ -99,16 +99,29 @@ The Ruff Formatter exposes a small set of configuration options, some of which a by Black (like line width), some of which are unique to Ruff (like quote and indentation style). For example, to configure the formatter to use single quotes, a line width of 100, and -tab indentation, add the following to your `pyproject.toml`: +tab indentation, add the following to your configuration file: -```toml -[tool.ruff] -line-length = 100 +=== "pyproject.toml" + + ```toml + [tool.ruff] + line-length = 100 + + [tool.ruff.format] + quote-style = "single" + indent-style = "tab" + ``` + +=== "ruff.toml" + + ```toml + line-length = 100 + + [format] + quote-style = "single" + indent-style = "tab" + ``` -[tool.ruff.format] -quote-style = "single" -indent-style = "tab" -``` For the full list of supported settings, see [_Settings_](settings.md#format). For more on configuring Ruff via `pyproject.toml`, see [_Configuring Ruff_](configuration.md). diff --git a/docs/linter.md b/docs/linter.md index 85d6a8775cfb5..71c5d04ef20aa 100644 --- a/docs/linter.md +++ b/docs/linter.md @@ -29,13 +29,23 @@ letter prefix, followed by three digits (e.g., `F401`). The prefix indicates tha Rule selectors like [`select`](settings.md#select) and [`ignore`](settings.md#ignore) accept either a full rule code (e.g., `F401`) or any valid prefix (e.g., `F`). For example, given the following -`pyproject.toml` file: +configuration file: -```toml -[tool.ruff.lint] -select = ["E", "F"] -ignore = ["F401"] -``` +=== "pyproject.toml" + + ```toml + [tool.ruff.lint] + select = ["E", "F"] + ignore = ["F401"] + ``` + +=== "ruff.toml" + + ```toml + [lint] + select = ["E", "F"] + ignore = ["F401"] + ``` Ruff would enable all rules with the `E` (pycodestyle) or `F` (Pyflakes) prefix, with the exception of `F401`. For more on configuring Ruff via `pyproject.toml`, see [_Configuring Ruff_](configuration.md). @@ -55,23 +65,45 @@ If you're wondering how to configure Ruff, here are some **recommended guideline For example, a configuration that enables some of the most popular rules (without being too pedantic) might look like the following: -```toml -[tool.ruff.lint] -select = [ - # pycodestyle - "E", - # Pyflakes - "F", - # pyupgrade - "UP", - # flake8-bugbear - "B", - # flake8-simplify - "SIM", - # isort - "I", -] -``` +=== "pyproject.toml" + + ```toml + [tool.ruff.lint] + select = [ + # pycodestyle + "E", + # Pyflakes + "F", + # pyupgrade + "UP", + # flake8-bugbear + "B", + # flake8-simplify + "SIM", + # isort + "I", + ] + ``` + +=== "ruff.toml" + + ```toml + [lint] + select = [ + # pycodestyle + "E", + # Pyflakes + "F", + # pyupgrade + "UP", + # flake8-bugbear + "B", + # flake8-simplify + "SIM", + # isort + "I", + ] + ``` To resolve the enabled rule set, Ruff may need to reconcile [`select`](settings.md#select) and [`ignore`](settings.md#ignore) from a variety of sources, including the current `pyproject.toml`, @@ -83,13 +115,23 @@ the rule set, and then applies [`extend-select`](settings.md#extend-select) and `pyproject.toml` options, and the current `pyproject.toml` file is given higher priority than any inherited `pyproject.toml` files. -For example, given the following `pyproject.toml` file: +For example, given the following configuration file: -```toml -[tool.ruff.lint] -select = ["E", "F"] -ignore = ["F401"] -``` +=== "pyproject.toml" + + ```toml + [tool.ruff.lint] + select = ["E", "F"] + ignore = ["F401"] + ``` + +=== "ruff.toml" + + ```toml + [lint] + select = ["E", "F"] + ignore = ["F401"] + ``` Running `ruff check --select F401` would result in Ruff enforcing `F401`, and no other rules. @@ -161,11 +203,21 @@ The safety of fixes can be adjusted per rule using the [`extend-safe-fixes`](set For example, the following configuration would promote unsafe fixes for `F601` to safe fixes and demote safe fixes for `UP034` to unsafe fixes: -```toml -[tool.ruff.lint] -extend-safe-fixes = ["F601"] -extend-unsafe-fixes = ["UP034"] -``` +=== "pyproject.toml" + + ```toml + [tool.ruff.lint] + extend-safe-fixes = ["F601"] + extend-unsafe-fixes = ["UP034"] + ``` + +=== "ruff.toml" + + ```toml + [lint] + extend-safe-fixes = ["F601"] + extend-unsafe-fixes = ["UP034"] + ``` You may use prefixes to select rules as well, e.g., `F` can be used to promote fixes for all rules in Pyflakes to safe. @@ -181,18 +233,37 @@ and [`extend-unfixable`](settings.md#extend-unfixable) variants. For example, the following configuration would enable fixes for all rules except [`unused-imports`](rules/unused-import.md) (`F401`): -```toml -[tool.ruff.lint] -fixable = ["ALL"] -unfixable = ["F401"] -``` +=== "pyproject.toml" + + ```toml + [tool.ruff.lint] + fixable = ["ALL"] + unfixable = ["F401"] + ``` + +=== "ruff.toml" + + ```toml + [lint] + fixable = ["ALL"] + unfixable = ["F401"] + ``` Conversely, the following configuration would only enable fixes for `F401`: -```toml -[tool.ruff.lint] -fixable = ["F401"] -``` +=== "pyproject.toml" + + ```toml + [tool.ruff.lint] + fixable = ["F401"] + ``` + +=== "ruff.toml" + + ```toml + [lint] + fixable = ["F401"] + ``` ## Error suppression diff --git a/docs/preview.md b/docs/preview.md index 3e1faab110bd1..1cdcab0729502 100644 --- a/docs/preview.md +++ b/docs/preview.md @@ -9,54 +9,109 @@ considered experimental or unstable,. ## Enabling preview mode Preview mode can be enabled with the `--preview` flag on the CLI or by setting `preview = true` in your Ruff -configuration file (e.g. `pyproject.toml`). +configuration file. Preview mode can be configured separately for linting and formatting (requires Ruff v0.1.1+). To enable preview lint rules without preview style formatting: -```toml -[lint] -preview = true -``` +=== "pyproject.toml" + + ```toml + [tool.ruff.lint] + preview = true + ``` + +=== "ruff.toml" + + ```toml + [lint] + preview = true + ``` To enable preview style formatting without enabling any preview lint rules: -```toml -[format] -preview = true -``` +=== "pyproject.toml" + + ```toml + [tool.ruff.preview] + preview = true + ``` + +=== "ruff.toml" + + ```toml + [preview] + preview = true + ``` ## Using rules that are in preview If a rule is marked as preview, it can only be selected if preview mode is enabled. For example, consider a hypothetical rule, `HYP001`. If `HYP001` were in preview, it would _not_ be enabled by adding following to your -`pyproject.toml`: +config file: -```toml -[tool.ruff.lint] -extend-select = ["HYP001"] -``` +=== "pyproject.toml" + + ```toml + [tool.ruff.lint] + extend-select = ["HYP001"] + ``` + +=== "ruff.toml" + + ```toml + [lint] + extend-select = ["HYP001"] + ``` It also would _not_ be enabled by selecting the `HYP` category, like so: -```toml -[tool.ruff.lint] -extend-select = ["HYP"] -``` +=== "pyproject.toml" + + ```toml + [tool.ruff.lint] + extend-select = ["HYP"] + ``` + +=== "ruff.toml" + + ```toml + [lint] + extend-select = ["HYP"] + ``` Similarly, it would _not_ be enabled via the `ALL` selector: -```toml -[tool.ruff.lint] -select = ["ALL"] -``` +=== "pyproject.toml" + + ```toml + [tool.ruff.lint] + select = ["ALL"] + ``` + +=== "ruff.toml" + + ```toml + [lint] + select = ["ALL"] + ``` However, it would be enabled in any of the above cases if you enabled preview in your configuration file: -```toml -[tool.ruff.lint] -extend-select = ["HYP"] -preview = true -``` +=== "pyproject.toml" + + ```toml + [tool.ruff.lint] + extend-select = ["HYP"] + preview = true + ``` + +=== "ruff.toml" + + ```toml + [lint] + extend-select = ["HYP"] + preview = true + ``` Or, if you provided the `--preview` CLI flag. @@ -66,13 +121,23 @@ To see which rules are currently in preview, visit the [rules reference](rules.m When preview mode is enabled, selecting rule categories or prefixes will include all preview rules that match. If you'd prefer to opt-in to each preview rule individually, you can toggle the `explicit-preview-rules` -setting in your `pyproject.toml`: +setting in your configuration file: + +=== "pyproject.toml" + + ```toml + [tool.ruff.lint] + preview = true + explicit-preview-rules = true + ``` + +=== "ruff.toml" -```toml -[tool.ruff.lint] -preview = true -explicit-preview-rules = true -``` + ```toml + [lint] + preview = true + explicit-preview-rules = true + ``` In our previous example, `--select` with `ALL` `HYP`, `HYP0`, or `HYP00` would not enable `HYP001`. Each preview rule will need to be selected with its exact code, e.g. `--select ALL,HYP001`. diff --git a/docs/tutorial.md b/docs/tutorial.md index 60f7bca033f56..90913bd727711 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -103,19 +103,34 @@ Ruff's behavior. To determine the appropriate settings for each Python file, Ruff looks for the first `pyproject.toml`, `ruff.toml`, or `.ruff.toml` file in the file's directory or any parent directory. -To configure Ruff, let's create a `pyproject.toml` file in our project's root directory: - -```toml -[tool.ruff] -# Set the maximum line length to 79. -line-length = 79 - -[tool.ruff.lint] -# Add the `line-too-long` rule to the enforced rule set. By default, Ruff omits rules that -# overlap with the use of a formatter, like Black, but we can override this behavior by -# explicitly adding the rule. -extend-select = ["E501"] -``` +To configure Ruff, let's create a configuration file in our project's root directory: + +=== "pyproject.toml" + + ```toml + [tool.ruff] + # Set the maximum line length to 79. + line-length = 79 + + [tool.ruff.lint] + # Add the `line-too-long` rule to the enforced rule set. By default, Ruff omits rules that + # overlap with the use of a formatter, like Black, but we can override this behavior by + # explicitly adding the rule. + extend-select = ["E501"] + ``` + +=== "ruff.toml" + + ```toml + # Set the maximum line length to 79. + line-length = 79 + + [lint] + # Add the `line-too-long` rule to the enforced rule set. By default, Ruff omits rules that + # overlap with the use of a formatter, like Black, but we can override this behavior by + # explicitly adding the rule. + extend-select = ["E501"] + ``` Running Ruff again, we see that it now enforces a maximum line width, with a limit of 79: @@ -128,19 +143,34 @@ Found 1 error. For a full enumeration of the supported settings, see [_Settings_](settings.md). For our project specifically, we'll want to make note of the minimum supported Python version: -```toml -[project] -# Support Python 3.10+. -requires-python = ">=3.10" +=== "pyproject.toml" -[tool.ruff] -# Set the maximum line length to 79. -line-length = 79 + ```toml + [project] + # Support Python 3.10+. + requires-python = ">=3.10" -[tool.ruff.lint] -# Add the `line-too-long` rule to the enforced rule set. -extend-select = ["E501"] -``` + [tool.ruff] + # Set the maximum line length to 79. + line-length = 79 + + [tool.ruff.lint] + # Add the `line-too-long` rule to the enforced rule set. + extend-select = ["E501"] + ``` + +=== "ruff.toml" + + ```toml + # Support Python 3.10+. + target-version = "py310" + # Set the maximum line length to 79. + line-length = 79 + + [lint] + # Add the `line-too-long` rule to the enforced rule set. + extend-select = ["E501"] + ``` ### Rule Selection @@ -158,17 +188,30 @@ imports) with zero configuration. If you're migrating to Ruff from another linter, you can enable rules that are equivalent to those enforced in your previous configuration. For example, if we want to enforce the pyupgrade -rules, we can set our `pyproject.toml` to the following: +rules, we can set our configuration file to the following: -```toml -[project] -requires-python = ">=3.10" +=== "pyproject.toml" -[tool.ruff.lint] -extend-select = [ - "UP", # pyupgrade -] -``` + ```toml + [project] + requires-python = ">=3.10" + + [tool.ruff.lint] + extend-select = [ + "UP", # pyupgrade + ] + ``` + +=== "ruff.toml" + + ```toml + target-version = "py310" + + [lint] + extend-select = [ + "UP", # pyupgrade + ] + ``` If we run Ruff again, we'll see that it now enforces the pyupgrade rules. In particular, Ruff flags the use of the deprecated `typing.Iterable` instead of `collections.abc.Iterable`: @@ -183,19 +226,36 @@ Found 1 error. Over time, we may choose to enforce additional rules. For example, we may want to enforce that all functions have docstrings: -```toml -[project] -requires-python = ">=3.10" +=== "pyproject.toml" -[tool.ruff.lint] -extend-select = [ - "UP", # pyupgrade - "D", # pydocstyle -] + ```toml + [project] + requires-python = ">=3.10" -[tool.ruff.lint.pydocstyle] -convention = "google" -``` + [tool.ruff.lint] + extend-select = [ + "UP", # pyupgrade + "D", # pydocstyle + ] + + [tool.ruff.lint.pydocstyle] + convention = "google" + ``` + +=== "ruff.toml" + + ```toml + target-version = "py310" + + [lint] + extend-select = [ + "UP", # pyupgrade + "D", # pydocstyle + ] + + [lint.pydocstyle] + convention = "google" + ``` If we run Ruff again, we'll see that it now enforces the pydocstyle rules: From 414d624c320a1627c55ceb2effe319b2c1c82ff9 Mon Sep 17 00:00:00 2001 From: trag1c Date: Fri, 3 Nov 2023 21:58:24 +0100 Subject: [PATCH 3/8] Added tabs when generating the settings section --- crates/ruff_dev/src/generate_options.rs | 51 +++++++++++++++++++------ 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/crates/ruff_dev/src/generate_options.rs b/crates/ruff_dev/src/generate_options.rs index a3d6b2d4d267a..8a5ac842e2a34 100644 --- a/crates/ruff_dev/src/generate_options.rs +++ b/crates/ruff_dev/src/generate_options.rs @@ -3,6 +3,7 @@ //! Used for . use std::fmt::Write; +use ruff_python_trivia::textwrap; use ruff_workspace::options::Options; use ruff_workspace::options_base::{OptionField, OptionSet, OptionsMetadata, Visit}; @@ -125,22 +126,48 @@ fn emit_field(output: &mut String, name: &str, field: &OptionField, parent_set: output.push('\n'); output.push_str(&format!("**Type**: `{}`\n", field.value_type)); output.push('\n'); - output.push_str(&format!( - "**Example usage**:\n\n```toml\n[tool.ruff{}]\n{}\n```\n", - if let Some(set_name) = parent_set.name() { - if set_name == "format" { - String::from(".format") - } else { - format!(".lint.{set_name}") - } - } else { - String::new() - }, - field.example + output.push_str("**Example usage**:\n\n"); + output.push_str(&format_tab( + "pyproject.toml", + format_header(parent_set, true), + field.example, + )); + output.push_str(&format_tab( + "ruff.toml", + format_header(parent_set, false), + field.example, )); output.push('\n'); } +fn format_tab(tab_name: &str, header: String, content: &str) -> String { + format!( + "=== \"{}\"\n\n ```toml\n {}\n{}\n ```\n", + tab_name, + header, + textwrap::indent(content, " ") + ) +} + +fn format_header(parent_set: &Set, pyproject: bool) -> String { + let fmt = if let Some(set_name) = parent_set.name() { + if set_name == "format" { + String::from(".format") + } else { + format!(".lint.{set_name}") + } + } else { + String::new() + }; + if pyproject { + format!("[tool.ruff{fmt}]") + } else if !fmt.is_empty() { + format!("[{}]", fmt.strip_prefix('.').unwrap()) + } else { + String::new() + } +} + #[derive(Default)] struct CollectOptionsVisitor { groups: Vec<(String, OptionSet)>, From a8a8273449896794a9988b573b9b101724cc6338 Mon Sep 17 00:00:00 2001 From: trag1c Date: Fri, 3 Nov 2023 22:13:53 +0100 Subject: [PATCH 4/8] Calmed clippy down --- crates/ruff_dev/src/generate_options.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/ruff_dev/src/generate_options.rs b/crates/ruff_dev/src/generate_options.rs index 8a5ac842e2a34..7afe48e8be1e0 100644 --- a/crates/ruff_dev/src/generate_options.rs +++ b/crates/ruff_dev/src/generate_options.rs @@ -129,18 +129,18 @@ fn emit_field(output: &mut String, name: &str, field: &OptionField, parent_set: output.push_str("**Example usage**:\n\n"); output.push_str(&format_tab( "pyproject.toml", - format_header(parent_set, true), + &format_header(parent_set, true), field.example, )); output.push_str(&format_tab( "ruff.toml", - format_header(parent_set, false), + &format_header(parent_set, false), field.example, )); output.push('\n'); } -fn format_tab(tab_name: &str, header: String, content: &str) -> String { +fn format_tab(tab_name: &str, header: &str, content: &str) -> String { format!( "=== \"{}\"\n\n ```toml\n {}\n{}\n ```\n", tab_name, From 764e1d6465bdc41733af60c2a0dffb8c653a7f1f Mon Sep 17 00:00:00 2001 From: trag1c Date: Fri, 3 Nov 2023 23:55:56 +0100 Subject: [PATCH 5/8] Excluded docs from mdformat/mdlint check --- .pre-commit-config.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f7cbb3a7d96a2..9e156fd942931 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,13 +26,19 @@ repos: - mdformat-admon exclude: | (?x)^( - docs/formatter/black.md + docs/formatter/black\.md + | docs/\w+\.md )$ - repo: https://github.com/igorshubovych/markdownlint-cli rev: v0.33.0 hooks: - id: markdownlint-fix + exclude: | + (?x)^( + docs/formatter/black\.md + | docs/\w+\.md + )$ - repo: https://github.com/crate-ci/typos rev: v1.14.12 From d2d792e7c37cf8f058f58b08e17e34879a430a95 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Sun, 5 Nov 2023 11:55:28 -0500 Subject: [PATCH 6/8] Share across page --- mkdocs.template.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/mkdocs.template.yml b/mkdocs.template.yml index ea4ec3a018a13..f3410e93d7abb 100644 --- a/mkdocs.template.yml +++ b/mkdocs.template.yml @@ -13,6 +13,7 @@ theme: - navigation.path - navigation.top - content.code.copy + - content.tabs.link palette: # Note: Using the system theme works with the insiders version # https://squidfunk.github.io/mkdocs-material/setup/changing-the-colors/#automatic-light-dark-mode From 02592c1d68771065596d8f163b510959f10d3608 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Sun, 5 Nov 2023 12:00:16 -0500 Subject: [PATCH 7/8] Use enum --- crates/ruff_dev/src/generate_options.rs | 27 ++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/crates/ruff_dev/src/generate_options.rs b/crates/ruff_dev/src/generate_options.rs index 7afe48e8be1e0..48b5e4876e19e 100644 --- a/crates/ruff_dev/src/generate_options.rs +++ b/crates/ruff_dev/src/generate_options.rs @@ -129,12 +129,12 @@ fn emit_field(output: &mut String, name: &str, field: &OptionField, parent_set: output.push_str("**Example usage**:\n\n"); output.push_str(&format_tab( "pyproject.toml", - &format_header(parent_set, true), + &format_header(parent_set, ConfigurationFile::PyprojectToml), field.example, )); output.push_str(&format_tab( "ruff.toml", - &format_header(parent_set, false), + &format_header(parent_set, ConfigurationFile::RuffToml), field.example, )); output.push('\n'); @@ -149,7 +149,7 @@ fn format_tab(tab_name: &str, header: &str, content: &str) -> String { ) } -fn format_header(parent_set: &Set, pyproject: bool) -> String { +fn format_header(parent_set: &Set, configuration: ConfigurationFile) -> String { let fmt = if let Some(set_name) = parent_set.name() { if set_name == "format" { String::from(".format") @@ -159,15 +159,24 @@ fn format_header(parent_set: &Set, pyproject: bool) -> String { } else { String::new() }; - if pyproject { - format!("[tool.ruff{fmt}]") - } else if !fmt.is_empty() { - format!("[{}]", fmt.strip_prefix('.').unwrap()) - } else { - String::new() + match configuration { + ConfigurationFile::PyprojectToml => format!("[tool.ruff{fmt}]", fmt = fmt), + ConfigurationFile::RuffToml => { + if !fmt.is_empty() { + format!("[{}]", fmt.strip_prefix('.').unwrap()) + } else { + String::new() + } + } } } +#[derive(Debug)] +enum ConfigurationFile { + PyprojectToml, + RuffToml, +} + #[derive(Default)] struct CollectOptionsVisitor { groups: Vec<(String, OptionSet)>, From 1273c796412f1891872916ec6bfe65a559bba0cf Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Sun, 5 Nov 2023 12:05:21 -0500 Subject: [PATCH 8/8] Fix Clippy --- crates/ruff_dev/src/generate_options.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/ruff_dev/src/generate_options.rs b/crates/ruff_dev/src/generate_options.rs index 48b5e4876e19e..2a7302a07ad08 100644 --- a/crates/ruff_dev/src/generate_options.rs +++ b/crates/ruff_dev/src/generate_options.rs @@ -160,18 +160,18 @@ fn format_header(parent_set: &Set, configuration: ConfigurationFile) -> String { String::new() }; match configuration { - ConfigurationFile::PyprojectToml => format!("[tool.ruff{fmt}]", fmt = fmt), + ConfigurationFile::PyprojectToml => format!("[tool.ruff{fmt}]"), ConfigurationFile::RuffToml => { - if !fmt.is_empty() { - format!("[{}]", fmt.strip_prefix('.').unwrap()) - } else { + if fmt.is_empty() { String::new() + } else { + format!("[{}]", fmt.strip_prefix('.').unwrap()) } } } } -#[derive(Debug)] +#[derive(Debug, Copy, Clone)] enum ConfigurationFile { PyprojectToml, RuffToml,