From 721f3104c72693b7800b2a6b70020bfae552f2ce Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Tue, 4 Aug 2026 16:17:29 +0200 Subject: [PATCH] [ty] Remove deprecated `src.root` setting in favor of `environment.root` (#27456) --- crates/ty/docs/configuration.md | 37 -------- crates/ty/tests/cli/python_environment.rs | 107 ---------------------- crates/ty_project/src/metadata.rs | 42 +++++---- crates/ty_project/src/metadata/options.rs | 58 +----------- ty.schema.json | 12 --- 5 files changed, 25 insertions(+), 231 deletions(-) diff --git a/crates/ty/docs/configuration.md b/crates/ty/docs/configuration.md index fcd90c42b1..94143a37b7 100644 --- a/crates/ty/docs/configuration.md +++ b/crates/ty/docs/configuration.md @@ -1054,43 +1054,6 @@ Enabled by default. --- -### `root` - -!!! warning "Deprecated" - This option has been deprecated. Use `environment.root` instead. - -The root of the project, used for finding first-party modules. - -If left unspecified, ty will try to detect common project layouts and initialize `src.root` accordingly. -The project root (`.`) is always included. Additionally, the following directories are included -if they exist and are not packages (i.e. they do not contain `__init__.py` or `__init__.pyi` files): - -* `./src` -* `./` (if a `.//` directory exists) -* `./python` - -**Default value**: `null` - -**Type**: `str` - -**Example usage**: - -=== "pyproject.toml" - - ```toml - [tool.ty.src] - root = "./app" - ``` - -=== "ty.toml" - - ```toml - [src] - root = "./app" - ``` - ---- - ## `terminal` ### `error-on-warning` diff --git a/crates/ty/tests/cli/python_environment.rs b/crates/ty/tests/cli/python_environment.rs index 2f20a098af..e7966e5d83 100644 --- a/crates/ty/tests/cli/python_environment.rs +++ b/crates/ty/tests/cli/python_environment.rs @@ -2205,113 +2205,6 @@ fn ty_system_environment_and_local_venv() -> anyhow::Result<()> { Ok(()) } -#[test] -fn src_root_deprecation_warning() -> anyhow::Result<()> { - let case = CliTest::with_files([ - ( - "pyproject.toml", - r#" - [tool.ty.src] - root = "./src" - "#, - ), - ("src/test.py", ""), - ])?; - - assert_cmd_snapshot!(case.command(), @r#" - success: false - exit_code: 1 - ----- stdout ----- - warning[deprecated-setting]: The `src.root` setting is deprecated. Use `environment.root` instead. - --> pyproject.toml:3:8 - | - 3 | root = "./src" - | ^^^^^^^ - - Found 1 diagnostic - - ----- stderr ----- - "#); - - Ok(()) -} - -#[test] -fn src_root_deprecation_warning_with_environment_root() -> anyhow::Result<()> { - let case = CliTest::with_files([ - ( - "pyproject.toml", - r#" - [tool.ty.src] - root = "./src" - - [tool.ty.environment] - root = ["./app"] - "#, - ), - ("app/test.py", ""), - ])?; - - assert_cmd_snapshot!(case.command(), @r#" - success: false - exit_code: 1 - ----- stdout ----- - warning[deprecated-setting]: The `src.root` setting is deprecated. Use `environment.root` instead. - --> pyproject.toml:3:8 - | - 3 | root = "./src" - | ^^^^^^^ - info: The `src.root` setting was ignored in favor of the `environment.root` setting - - Found 1 diagnostic - - ----- stderr ----- - "#); - - Ok(()) -} - -#[test] -fn environment_root_takes_precedence_over_src_root() -> anyhow::Result<()> { - let case = CliTest::with_files([ - ( - "pyproject.toml", - r#" - [tool.ty.src] - root = "./src" - - [tool.ty.environment] - root = ["./app"] - "#, - ), - ("src/test.py", "import my_module"), - ( - "app/my_module.py", - "# This module exists in app/ but not src/", - ), - ])?; - - // The test should pass because environment.root points to ./app where my_module.py exists - // If src.root took precedence, it would fail because my_module.py doesn't exist in ./src - assert_cmd_snapshot!(case.command(), @r#" - success: false - exit_code: 1 - ----- stdout ----- - warning[deprecated-setting]: The `src.root` setting is deprecated. Use `environment.root` instead. - --> pyproject.toml:3:8 - | - 3 | root = "./src" - | ^^^^^^^ - info: The `src.root` setting was ignored in favor of the `environment.root` setting - - Found 1 diagnostic - - ----- stderr ----- - "#); - - Ok(()) -} - #[test] fn default_root_src_layout() -> anyhow::Result<()> { let case = CliTest::with_files([ diff --git a/crates/ty_project/src/metadata.rs b/crates/ty_project/src/metadata.rs index c7e1a914ef..e97c390a4d 100644 --- a/crates/ty_project/src/metadata.rs +++ b/crates/ty_project/src/metadata.rs @@ -769,8 +769,8 @@ unclosed table, expected `]` [project] name = "project-root" - [tool.ty.src] - root = "src" + [tool.ty.environment] + root = ["src"] "#, ), ( @@ -779,8 +779,8 @@ unclosed table, expected `]` [project] name = "nested-project" - [tool.ty.src] - root = "src" + [tool.ty.environment] + root = ["src"] "#, ), ]) @@ -794,8 +794,10 @@ unclosed table, expected `]` name: ProjectName("nested-project"), root: "/app/packages/a", options: Options( - src: Some(SrcOptions( - root: Some("src"), + environment: Some(EnvironmentOptions( + root: Some([ + "src", + ]), )), ), ) @@ -819,8 +821,8 @@ unclosed table, expected `]` [project] name = "project-root" - [tool.ty.src] - root = "src" + [tool.ty.environment] + root = ["src"] "#, ), ( @@ -829,8 +831,8 @@ unclosed table, expected `]` [project] name = "nested-project" - [tool.ty.src] - root = "src" + [tool.ty.environment] + root = ["src"] "#, ), ]) @@ -844,8 +846,10 @@ unclosed table, expected `]` name: ProjectName("project-root"), root: "/app", options: Options( - src: Some(SrcOptions( - root: Some("src"), + environment: Some(EnvironmentOptions( + root: Some([ + "src", + ]), )), ), ) @@ -1221,15 +1225,15 @@ unclosed table, expected `]` name = "super-app" requires-python = ">=3.12" - [tool.ty.src] - root = "this_option_is_ignored" + [tool.ty.environment] + root = ["this_option_is_ignored"] "#, ), ( root.join("ty.toml"), r#" - [src] - root = "src" + [environment] + root = ["src"] "#, ), ]) @@ -1244,11 +1248,11 @@ unclosed table, expected `]` root: "/app", options: Options( environment: Some(EnvironmentOptions( + root: Some([ + "src", + ]), r#python-version: Some(r#3.12), )), - src: Some(SrcOptions( - root: Some("src"), - )), ), ) "#); diff --git a/crates/ty_project/src/metadata/options.rs b/crates/ty_project/src/metadata/options.rs index a07a8ce03a..446bef4a56 100644 --- a/crates/ty_project/src/metadata/options.rs +++ b/crates/ty_project/src/metadata/options.rs @@ -307,14 +307,8 @@ impl Options { strategy: &Strategy, ) -> Result> { let environment = self.environment.or_default(); - let src = self.src.or_default(); - #[allow(deprecated)] - let src_roots = if let Some(roots) = environment - .root - .as_deref() - .or_else(|| Some(std::slice::from_ref(src.root.as_ref()?))) - { + let environment_roots = if let Some(roots) = environment.root.as_deref() { roots .iter() .map(|root| root.absolute(project_root, system)) @@ -410,7 +404,7 @@ impl Options { let settings = SearchPathSettings { extra_paths, - src_roots, + src_roots: environment_roots, custom_typeshed: environment .typeshed .as_ref() @@ -443,34 +437,6 @@ impl Options { let src_options = self.src.or_default(); - #[allow(deprecated)] - if let Some(src_root) = src_options.root.as_ref() { - let mut diagnostic = OptionDiagnostic::new( - DiagnosticId::DeprecatedSetting, - "The `src.root` setting is deprecated. Use `environment.root` instead.".to_string(), - Severity::Warning, - ); - - if let Some(file) = src_root - .source() - .file() - .and_then(|path| system_path_to_file(db, path).ok()) - { - diagnostic = diagnostic.with_annotation(Some(Annotation::primary( - Span::from(file).with_optional_range(src_root.range()), - ))); - } - - if self.environment.or_default().root.is_some() { - diagnostic = diagnostic.sub(SubDiagnostic::new( - SubDiagnosticSeverity::Info, - "The `src.root` setting was ignored in favor of the `environment.root` setting", - )); - } - - diagnostics.push(diagnostic); - } - let src = src_options .to_settings(db, project_root, &mut diagnostics) .map_err(|err| ToSettingsError { @@ -910,26 +876,6 @@ pub struct EnvironmentOptions { #[serde(rename_all = "kebab-case", deny_unknown_fields)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct SrcOptions { - /// The root of the project, used for finding first-party modules. - /// - /// If left unspecified, ty will try to detect common project layouts and initialize `src.root` accordingly. - /// The project root (`.`) is always included. Additionally, the following directories are included - /// if they exist and are not packages (i.e. they do not contain `__init__.py` or `__init__.pyi` files): - /// - /// * `./src` - /// * `./` (if a `.//` directory exists) - /// * `./python` - #[serde(skip_serializing_if = "Option::is_none")] - #[option( - default = r#"null"#, - value_type = "str", - example = r#" - root = "./app" - "# - )] - #[deprecated(note = "Use `environment.root` instead.")] - pub root: Option, - /// Whether to automatically exclude files that are ignored by `.ignore`, /// `.gitignore`, `.git/info/exclude`, and global `gitignore` files. /// Enabled by default. diff --git a/ty.schema.json b/ty.schema.json index 58818ff729..aafd177dd8 100644 --- a/ty.schema.json +++ b/ty.schema.json @@ -1610,18 +1610,6 @@ "boolean", "null" ] - }, - "root": { - "description": "The root of the project, used for finding first-party modules.\n\nIf left unspecified, ty will try to detect common project layouts and initialize `src.root` accordingly.\nThe project root (`.`) is always included. Additionally, the following directories are included\nif they exist and are not packages (i.e. they do not contain `__init__.py` or `__init__.pyi` files):\n\n* `./src`\n* `./` (if a `.//` directory exists)\n* `./python`", - "anyOf": [ - { - "$ref": "#/definitions/RelativePathBuf" - }, - { - "type": "null" - } - ], - "deprecated": true } }, "additionalProperties": false