From 9646bc7d7f6bf3f9c90ce29400f1873772636cb8 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Sun, 28 May 2023 22:50:35 -0400 Subject: [PATCH] Add docs to clarify project root heuristics (#4697) --- crates/ruff/src/settings/options.rs | 10 +++++-- docs/faq.md | 46 +++++++++++++++++++++++++++++ ruff.schema.json | 2 +- 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/crates/ruff/src/settings/options.rs b/crates/ruff/src/settings/options.rs index 5904adcc39..e9cbf4519c 100644 --- a/crates/ruff/src/settings/options.rs +++ b/crates/ruff/src/settings/options.rs @@ -407,11 +407,15 @@ pub struct Options { /// (e.g., `src = ["src"]`), such that when resolving imports, /// `my_package.foo` is considered a first-party import. /// + /// When omitted, the `src` directory will typically default to the + /// directory containing the nearest `pyproject.toml`, `ruff.toml`, or + /// `.ruff.toml` file (the "project root"), unless a configuration file + /// is explicitly provided (e.g., via the `--config` command-line flag). + /// /// This field supports globs. For example, if you have a series of Python /// packages in a `python_modules` directory, `src = ["python_modules/*"]` - /// would expand to incorporate all of the - /// packages in that directory. User home directory and environment - /// variables will also be expanded. + /// would expand to incorporate all of the packages in that directory. User + /// home directory and environment variables will also be expanded. pub src: Option>, #[option( default = r#"[]"#, diff --git a/docs/faq.md b/docs/faq.md index c40cfa9052..3b4f3d0d90 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -255,6 +255,52 @@ src = ["src", "tests"] known-first-party = ["my_module1", "my_module2"] ``` +## How does Ruff determine which of my imports are first-party, third-party, etc.? + +Ruff accepts a `src` option that in your `pyproject.toml`, `ruff.toml`, or `.ruff.toml` file, which +specifies the directories that Ruff should consider when determining whether an import is +first-party. + +For example, if you have a project with the following structure: + +```tree +. +├── pyproject.toml +├── src +│ ├── __init__.py +│ ├── module1.py +│ └── module2.py +└── tests + ├── __init__.py + ├── test_module1.py + └── test_module2.py +``` + +When Ruff sees an import like `import module1`, it will then iterate over the `src` directories, +looking for a corresponding Python module. You can configure Ruff to consider `src` and `tests` as +first-party sources like so: + +```toml +[tool.ruff] +src = ["src", "tests"] +``` + +If the `src` field is omitted, Ruff will default to using the "project root" as the only +first-party source. The "project root" is typically the directory containing your `pyproject.toml`, +`ruff.toml`, or `.ruff.toml` file, unless a configuration file is provided on the command-line via +the `--config` option, in which case, the current working directory is used as the project root. + +If your `pyproject.toml`, `ruff.toml`, or `.ruff.toml` extends another configuration file, Ruff +will still use the "extended" configuration file's directory as the project root. For example, if +you add a `ruff.toml` to the `tests` directory in the above example, you'll want to explicitly +set the `src` option in the extended configuration file: + +```toml +# tests/ruff.toml +extend = "../pyproject.toml" +src = ["../src", "../test"] +``` + ## Does Ruff support Jupyter Notebooks? Ruff is integrated into [nbQA](https://github.com/nbQA-dev/nbQA), a tool for running linters and diff --git a/ruff.schema.json b/ruff.schema.json index ffc81fb068..cc5aee89b6 100644 --- a/ruff.schema.json +++ b/ruff.schema.json @@ -496,7 +496,7 @@ ] }, "src": { - "description": "The source code paths to consider, e.g., when resolving first- vs. third-party imports.\n\nAs an example: given a Python package structure like:\n\n```text my_package/ pyproject.toml src/ my_package/ __init__.py foo.py bar.py ```\n\nThe `src` directory should be included in the `src` option (e.g., `src = [\"src\"]`), such that when resolving imports, `my_package.foo` is considered a first-party import.\n\nThis field supports globs. For example, if you have a series of Python packages in a `python_modules` directory, `src = [\"python_modules/*\"]` would expand to incorporate all of the packages in that directory. User home directory and environment variables will also be expanded.", + "description": "The source code paths to consider, e.g., when resolving first- vs. third-party imports.\n\nAs an example: given a Python package structure like:\n\n```text my_package/ pyproject.toml src/ my_package/ __init__.py foo.py bar.py ```\n\nThe `src` directory should be included in the `src` option (e.g., `src = [\"src\"]`), such that when resolving imports, `my_package.foo` is considered a first-party import.\n\nWhen omitted, the `src` directory will typically default to the directory containing the nearest `pyproject.toml`, `ruff.toml`, or `.ruff.toml` file (the \"project root\"), unless a configuration file is explicitly provided (e.g., via the `--config` command-line flag).\n\nThis field supports globs. For example, if you have a series of Python packages in a `python_modules` directory, `src = [\"python_modules/*\"]` would expand to incorporate all of the packages in that directory. User home directory and environment variables will also be expanded.", "type": [ "array", "null"