Repository: starship/starship
File: src/modules/package.rs (Rust)

Code before:
        .map(|s| s.to_owned())
}

fn parse_file_version_for_hatchling(context: &Context, path: &str) -> Option<String> {
    let file_contents = read_file(context.current_dir.join(path)).ok()?;
    // https://hatch.pypa.io/latest/version/
    let re = Regex::new(r#"(__version__|VERSION)\s*=\s*["']([^"']+)["']"#).ok()?;
    Some(
        re.captures(&file_contents)
            .and_then(|cap| cap.get(2))?
            .as_str()
            .to_owned(),
    )
}

fn parse_hatchling_dynamic_version(context: &Context, pyproject: &toml::Table) -> Option<String> {
    let version_path = pyproject
        .get("tool")?
        .get("hatch")?
        .get("version")?
        .get("path")?
        .as_str()?;

    parse_file_version_for_hatchling(context, version_path)
        .and_then(|s| Version::new(s.as_str()))
        .map(|v| v.to_string())
}

fn parse_pep621_dynamic_version(context: &Context, pyproject: &toml::Table) -> Option<String> {
    // TODO: Flit, PDM, Setuptools
    // https://packaging.python.org/en/latest/discussions/single-source-version#build-system-version-handling
    parse_hatchling_dynamic_version(context, pyproject)
}

fn get_pep621_dynamic_version(context: &Context, pyproject: &toml::Table) -> Option<String> {
    pyproject
        .get("project")?
        .get("dynamic")?
        .as_array()?
        .iter()
        .any(|v| v.as_str() == Some("version"))
        .then(|| parse_pep621_dynamic_version(context, pyproject))?
}

fn get_pep621_static_version(pyproject: &toml::Table) -> Option<String> {
    pyproject
        .get("project")?
        .get("version")?
        .as_str()
        .map(|s| s.to_owned())
}

Review comment (suggestion):
Apart from that LGTM if tests pass once `master` is fixed.

```suggestion
        .filter(|s| Version::new(s.as_str()).is_some())
```

Code after:
        .map(|s| s.to_owned())
}

fn parse_file_version_for_hatchling(context: &Context, path: &str) -> Option<String> {
    let file_contents = read_file(context.current_dir.join(path)).ok()?;
    // https://hatch.pypa.io/latest/version/
    let re = Regex::new(r#"(__version__|VERSION)\s*=\s*["']([^"']+)["']"#).ok()?;
    Some(
        re.captures(&file_contents)
            .and_then(|cap| cap.get(2))?
            .as_str()
            .to_owned(),
    )
}

fn parse_hatchling_dynamic_version(context: &Context, pyproject: &toml::Table) -> Option<String> {
    let version_path = pyproject
        .get("tool")?
        .get("hatch")?
        .get("version")?
        .get("path")?
        .as_str()?;

    parse_file_version_for_hatchling(context, version_path)
        .filter(|s| Version::new(s.as_str()).is_some())
}

fn parse_pep621_dynamic_version(context: &Context, pyproject: &toml::Table) -> Option<String> {
    // TODO: Flit, PDM, Setuptools
    // https://packaging.python.org/en/latest/discussions/single-source-version#build-system-version-handling
    parse_hatchling_dynamic_version(context, pyproject)
}

fn get_pep621_dynamic_version(context: &Context, pyproject: &toml::Table) -> Option<String> {
    pyproject
        .get("project")?
        .get("dynamic")?
        .as_array()?
        .iter()
        .any(|v| v.as_str() == Some("version"))
        .then(|| parse_pep621_dynamic_version(context, pyproject))?
}

fn get_pep621_static_version(pyproject: &toml::Table) -> Option<String> {
    pyproject
        .get("project")?
        .get("version")?
        .as_str()
        .map(|s| s.to_owned())
}