Repository: astral-sh/ruff
File: crates/ty_project/src/metadata/options.rs (Rust)

Code before:
        .inspect_err(|err| tracing::debug!("Failed to discover ty's environment: {err}"))
        .ok()?;

    let search_paths = environment
        .site_packages_paths(system)
        .inspect_err(|err| {
            tracing::debug!("Failed to discover site-packages in ty's environment: {err}");
        })
        .ok();

    tracing::debug!("Using site-packages from ty's environment");
    search_paths
}

#[derive(
    Debug,
    Default,
    Clone,
    Eq,
    PartialEq,
    Combine,
    Serialize,
    Deserialize,
    OptionsMetadata,
    get_size2::GetSize,
)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct EnvironmentOptions {
    /// The root paths of the project, used for finding first-party modules.
    ///
    /// Accepts a list of directory paths searched in priority order (first has highest priority).
    ///
    /// If left unspecified, ty will try to detect common project layouts and initialize `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`
    /// * `./<project-name>` (if a `./<project-name>/<project-name>` directory exists)
    /// * `./python`
    #[serde(skip_serializing_if = "Option::is_none")]
    #[option(
        default = r#"null"#,
        value_type = "list[str]",
        example = r#"
            # Multiple directories (priority order)
            root = ["./src", "./lib", "./vendor"]
        "#
    )]
    pub root: Option<Vec<RelativePathBuf>>,


Review comment (bug):
sounds like we won't necessarily actually "use" the `site-packages` from ty's environment in the latest version of this PR?

```suggestion
    tracing::debug!("Resolved site-packages from ty's environment");
```

Code after:
    existing_origin: Option<SysPrefixPathOrigin>,
    system: &dyn System,
) -> Option<(SitePackagesPaths, bool)> {
    if existing_origin.is_some_and(|origin| !origin.allows_concatenation_with_self_environment()) {
        return None;
    }

    let Ok(exe_path) = std::env::current_exe() else {
        return None;
    };
    let ty_path = SystemPath::from_std_path(exe_path.as_path())?;

    let environment = PythonEnvironment::new(ty_path, SysPrefixPathOrigin::SelfEnvironment, system)
        .inspect_err(|err| tracing::debug!("Failed to discover ty's environment: {err}"))
        .ok()?;

    let is_virtual_env = environment.is_virtual();

    let search_paths = environment
        .site_packages_paths(system)
        .inspect_err(|err| {
            tracing::debug!("Failed to discover site-packages in ty's environment: {err}");
        })
        .ok()?;

    tracing::debug!("Using site-packages from ty's environment");
    Some((search_paths, is_virtual_env))
}

#[derive(
    Debug,
    Default,
    Clone,
    Eq,
    PartialEq,
    Combine,
    Serialize,
    Deserialize,
    OptionsMetadata,
    get_size2::GetSize,
)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct EnvironmentOptions {
    /// The root paths of the project, used for finding first-party modules.
    ///
    /// Accepts a list of directory paths searched in priority order (first has highest priority).
    ///
    /// If left unspecified, ty will try to detect common project layouts and initialize `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):