Repository: astral-sh/uv
File: crates/uv-build-backend/src/lib.rs (Rust)

Code before:
use uv_warnings::warn_user_once;
pub use wheel::{build_editable, build_wheel, list_wheel, metadata};

use std::collections::HashSet;
use std::ffi::OsStr;
use std::io;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use thiserror::Error;
use tracing::debug;
use walkdir::DirEntry;

use uv_fs::Simplified;
use uv_globfilter::PortableGlobError;
use uv_normalize::PackageName;
use uv_pypi_types::{Identifier, IdentifierParseError};

use crate::metadata::ValidationError;
use crate::settings::ModuleName;

#[derive(Debug, Error)]
pub enum Error {
    #[error(transparent)]
    Io(#[from] io::Error),
    #[error("Failed to persist temporary file to {}", _0.user_display())]
    Persist(PathBuf, #[source] tempfile::PersistError),
    #[error("Invalid metadata format in: {}", _0.user_display())]
    Toml(PathBuf, #[source] toml::de::Error),
    #[error("Invalid project metadata")]
    Validation(#[from] ValidationError),
    #[error("Invalid module name: {0}")]
    InvalidModuleName(String, #[source] IdentifierParseError),
    #[error("Unsupported glob expression in: {field}")]
    PortableGlob {
        field: String,
        #[source]
        source: PortableGlobError,
    },
    /// <https://github.com/BurntSushi/ripgrep/discussions/2927>
    #[error("Glob expressions caused to large regex in: {field}")]
    GlobSetTooLarge {
        field: String,
        #[source]
        source: globset::Error,
    },
    #[error("`pyproject.toml` must not be excluded from source distribution build")]
    PyprojectTomlExcluded,
    #[error("Failed to walk source tree: {}", root.user_display())]
    WalkDir {
        root: PathBuf,
        #[source]

Review comment (bug):
I think having a custom error here is probably a good idea, but just a small request:

`tempfile::PersistError` contains both the `io::Error` and the `NamedTempFile` we failed to persist. We're not making use of the whole `NamedTempFile` and don't want to keep it around unnecessarily while we do error handling, we just need the `io::Error` inside.

Code after:
use uv_warnings::warn_user_once;
pub use wheel::{build_editable, build_wheel, list_wheel, metadata};

use std::collections::HashSet;
use std::ffi::OsStr;
use std::io;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use thiserror::Error;
use tracing::debug;
use walkdir::DirEntry;

use uv_fs::Simplified;
use uv_globfilter::PortableGlobError;
use uv_normalize::PackageName;
use uv_pypi_types::{Identifier, IdentifierParseError};

use crate::metadata::ValidationError;
use crate::settings::ModuleName;

#[derive(Debug, Error)]
pub enum Error {
    #[error(transparent)]
    Io(#[from] io::Error),
    #[error("Failed to persist temporary file to {}", _0.user_display())]
    Persist(PathBuf, #[source] io::Error),
    #[error("Invalid metadata format in: {}", _0.user_display())]
    Toml(PathBuf, #[source] toml::de::Error),
    #[error("Invalid project metadata")]
    Validation(#[from] ValidationError),
    #[error("Invalid module name: {0}")]
    InvalidModuleName(String, #[source] IdentifierParseError),
    #[error("Unsupported glob expression in: {field}")]
    PortableGlob {
        field: String,
        #[source]
        source: PortableGlobError,
    },
    /// <https://github.com/BurntSushi/ripgrep/discussions/2927>
    #[error("Glob expressions caused to large regex in: {field}")]
    GlobSetTooLarge {
        field: String,
        #[source]
        source: globset::Error,
    },
    #[error("`pyproject.toml` must not be excluded from source distribution build")]
    PyprojectTomlExcluded,
    #[error("Failed to walk source tree: {}", root.user_display())]
    WalkDir {
        root: PathBuf,
        #[source]