Skip to content

Commit 24acf6a

Browse files
committed
Add uv build
1 parent f5d2f7c commit 24acf6a

File tree

15 files changed

+958
-167
lines changed

15 files changed

+958
-167
lines changed

Cargo.lock

Lines changed: 2 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/uv-cli/src/lib.rs

Lines changed: 104 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,21 @@ pub enum Commands {
335335
after_long_help = ""
336336
)]
337337
Venv(VenvArgs),
338+
/// Build Python packages into source distributions and wheels.
339+
///
340+
/// By default, `uv build` will build a source distribution ("sdist")
341+
/// from the source directory, and a binary distribution ("wheel") from
342+
/// the source distribution.
343+
///
344+
/// `uv build --sdist` can be used to build only the source distribution,
345+
/// `uv build --wheel` can be used to build only the binary distribution,
346+
/// and `uv build --sdist --wheel` can be used to build both distributions
347+
/// from source.
348+
#[command(
349+
after_help = "Use `uv help build` for more details.",
350+
after_long_help = ""
351+
)]
352+
Build(BuildArgs),
338353
/// Manage uv's cache.
339354
#[command(
340355
after_help = "Use `uv help cache` for more details.",
@@ -1125,7 +1140,7 @@ pub struct PipSyncArgs {
11251140

11261141
/// The Python interpreter into which packages should be installed.
11271142
///
1128-
/// By default, syncing requires a virtual environment. An path to an
1143+
/// By default, syncing requires a virtual environment. A path to an
11291144
/// alternative Python can be provided, but it is only recommended in
11301145
/// continuous integration (CI) environments and should be used with
11311146
/// caution, as it can modify the system Python installation.
@@ -1407,7 +1422,7 @@ pub struct PipInstallArgs {
14071422

14081423
/// The Python interpreter into which packages should be installed.
14091424
///
1410-
/// By default, installation requires a virtual environment. An path to an
1425+
/// By default, installation requires a virtual environment. A path to an
14111426
/// alternative Python can be provided, but it is only recommended in
14121427
/// continuous integration (CI) environments and should be used with
14131428
/// caution, as it can modify the system Python installation.
@@ -1572,7 +1587,7 @@ pub struct PipUninstallArgs {
15721587

15731588
/// The Python interpreter from which packages should be uninstalled.
15741589
///
1575-
/// By default, uninstallation requires a virtual environment. An path to an
1590+
/// By default, uninstallation requires a virtual environment. A path to an
15761591
/// alternative Python can be provided, but it is only recommended in
15771592
/// continuous integration (CI) environments and should be used with
15781593
/// caution, as it can modify the system Python installation.
@@ -1923,6 +1938,49 @@ pub struct PipTreeArgs {
19231938
pub compat_args: compat::PipGlobalCompatArgs,
19241939
}
19251940

1941+
#[derive(Args)]
1942+
#[allow(clippy::struct_excessive_bools)]
1943+
pub struct BuildArgs {
1944+
/// The directory from which source distributions and/or wheels should be built.
1945+
///
1946+
/// Defaults to the current working directory.
1947+
#[arg(value_parser = parse_file_path)]
1948+
pub src_dir: Option<PathBuf>,
1949+
1950+
/// Build a source distribution ("sdist") from the given directory.
1951+
#[arg(long)]
1952+
pub sdist: bool,
1953+
1954+
/// Build a built distribution ("wheel") from the given directory.
1955+
#[arg(long)]
1956+
pub wheel: bool,
1957+
1958+
/// The Python interpreter to use for the build environment.
1959+
///
1960+
/// By default, builds are executed in isolated virtual environments. The
1961+
/// discovered interpreter will be used to create those environments, and
1962+
/// will be symlinked or copied in depending on the platform.
1963+
///
1964+
/// See `uv help python` to view supported request formats.
1965+
#[arg(
1966+
long,
1967+
short,
1968+
env = "UV_PYTHON",
1969+
verbatim_doc_comment,
1970+
help_heading = "Python options"
1971+
)]
1972+
pub python: Option<String>,
1973+
1974+
#[command(flatten)]
1975+
pub resolver: ResolverArgs,
1976+
1977+
#[command(flatten)]
1978+
pub build: BuildOptionsArgs,
1979+
1980+
#[command(flatten)]
1981+
pub refresh: RefreshArgs,
1982+
}
1983+
19261984
#[derive(Args)]
19271985
#[allow(clippy::struct_excessive_bools)]
19281986
pub struct VenvArgs {
@@ -2298,7 +2356,7 @@ pub struct RunArgs {
22982356
pub installer: ResolverInstallerArgs,
22992357

23002358
#[command(flatten)]
2301-
pub build: BuildArgs,
2359+
pub build: BuildOptionsArgs,
23022360

23032361
#[command(flatten)]
23042362
pub refresh: RefreshArgs,
@@ -2426,7 +2484,7 @@ pub struct SyncArgs {
24262484
pub installer: ResolverInstallerArgs,
24272485

24282486
#[command(flatten)]
2429-
pub build: BuildArgs,
2487+
pub build: BuildOptionsArgs,
24302488

24312489
#[command(flatten)]
24322490
pub refresh: RefreshArgs,
@@ -2479,7 +2537,7 @@ pub struct LockArgs {
24792537
pub resolver: ResolverArgs,
24802538

24812539
#[command(flatten)]
2482-
pub build: BuildArgs,
2540+
pub build: BuildOptionsArgs,
24832541

24842542
#[command(flatten)]
24852543
pub refresh: RefreshArgs,
@@ -2593,7 +2651,7 @@ pub struct AddArgs {
25932651
pub installer: ResolverInstallerArgs,
25942652

25952653
#[command(flatten)]
2596-
pub build: BuildArgs,
2654+
pub build: BuildOptionsArgs,
25972655

25982656
#[command(flatten)]
25992657
pub refresh: RefreshArgs,
@@ -2662,7 +2720,7 @@ pub struct RemoveArgs {
26622720
pub installer: ResolverInstallerArgs,
26632721

26642722
#[command(flatten)]
2665-
pub build: BuildArgs,
2723+
pub build: BuildOptionsArgs,
26662724

26672725
#[command(flatten)]
26682726
pub refresh: RefreshArgs,
@@ -2722,7 +2780,7 @@ pub struct TreeArgs {
27222780
pub frozen: bool,
27232781

27242782
#[command(flatten)]
2725-
pub build: BuildArgs,
2783+
pub build: BuildOptionsArgs,
27262784

27272785
#[command(flatten)]
27282786
pub resolver: ResolverArgs,
@@ -2819,7 +2877,7 @@ pub struct ExportArgs {
28192877
pub resolver: ResolverArgs,
28202878

28212879
#[command(flatten)]
2822-
pub build: BuildArgs,
2880+
pub build: BuildOptionsArgs,
28232881

28242882
#[command(flatten)]
28252883
pub refresh: RefreshArgs,
@@ -2844,6 +2902,38 @@ pub struct ExportArgs {
28442902
pub python: Option<String>,
28452903
}
28462904

2905+
#[derive(Args)]
2906+
#[allow(clippy::struct_excessive_bools)]
2907+
pub struct BuildNamespace {
2908+
#[command(subcommand)]
2909+
pub command: BuildCommand,
2910+
}
2911+
2912+
#[derive(Subcommand)]
2913+
pub enum BuildCommand {
2914+
/// Run a command provided by a Python package.
2915+
///
2916+
/// By default, the package to install is assumed to match the command name.
2917+
///
2918+
/// The name of the command can include an exact version in the format
2919+
/// `<package>@<version>`, e.g., `uv tool run [email protected]`. If more complex
2920+
/// version specification is desired or if the command is provided by a
2921+
/// different package, use `--from`.
2922+
///
2923+
/// If the tool was previously installed, i.e., via `uv tool install`, the
2924+
/// installed version will be used unless a version is requested or the
2925+
/// `--isolated` flag is used.
2926+
///
2927+
/// `uvx` is provided as a convenient alias for `uv tool run`, their
2928+
/// behavior is identical.
2929+
///
2930+
/// If no command is provided, the installed tools are displayed.
2931+
///
2932+
/// Packages are installed into an ephemeral virtual environment in the uv
2933+
/// cache directory.
2934+
Run(BuildOptionsArgs),
2935+
}
2936+
28472937
#[derive(Args)]
28482938
#[allow(clippy::struct_excessive_bools)]
28492939
pub struct ToolNamespace {
@@ -2966,7 +3056,7 @@ pub struct ToolRunArgs {
29663056
pub installer: ResolverInstallerArgs,
29673057

29683058
#[command(flatten)]
2969-
pub build: BuildArgs,
3059+
pub build: BuildOptionsArgs,
29703060

29713061
#[command(flatten)]
29723062
pub refresh: RefreshArgs,
@@ -3018,7 +3108,7 @@ pub struct ToolInstallArgs {
30183108
pub installer: ResolverInstallerArgs,
30193109

30203110
#[command(flatten)]
3021-
pub build: BuildArgs,
3111+
pub build: BuildOptionsArgs,
30223112

30233113
#[command(flatten)]
30243114
pub refresh: RefreshArgs,
@@ -3103,7 +3193,7 @@ pub struct ToolUpgradeArgs {
31033193
pub installer: ResolverInstallerArgs,
31043194

31053195
#[command(flatten)]
3106-
pub build: BuildArgs,
3196+
pub build: BuildOptionsArgs,
31073197
}
31083198

31093199
#[derive(Args)]
@@ -3407,7 +3497,7 @@ pub struct RefreshArgs {
34073497

34083498
#[derive(Args)]
34093499
#[allow(clippy::struct_excessive_bools)]
3410-
pub struct BuildArgs {
3500+
pub struct BuildOptionsArgs {
34113501
/// Don't build source distributions.
34123502
///
34133503
/// When enabled, resolving will not run arbitrary Python code. The cached wheels of

crates/uv-cli/src/options.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ use uv_resolver::PrereleaseMode;
44
use uv_settings::{PipOptions, ResolverInstallerOptions, ResolverOptions};
55

66
use crate::{
7-
BuildArgs, IndexArgs, InstallerArgs, Maybe, RefreshArgs, ResolverArgs, ResolverInstallerArgs,
7+
BuildOptionsArgs, IndexArgs, InstallerArgs, Maybe, RefreshArgs, ResolverArgs,
8+
ResolverInstallerArgs,
89
};
910

1011
/// Given a boolean flag pair (like `--upgrade` and `--no-upgrade`), resolve the value of the flag.
@@ -206,8 +207,11 @@ impl From<IndexArgs> for PipOptions {
206207
}
207208
}
208209

209-
/// Construct the [`ResolverOptions`] from the [`ResolverArgs`] and [`BuildArgs`].
210-
pub fn resolver_options(resolver_args: ResolverArgs, build_args: BuildArgs) -> ResolverOptions {
210+
/// Construct the [`ResolverOptions`] from the [`ResolverArgs`] and [`BuildOptionsArgs`].
211+
pub fn resolver_options(
212+
resolver_args: ResolverArgs,
213+
build_args: BuildOptionsArgs,
214+
) -> ResolverOptions {
211215
let ResolverArgs {
212216
index_args,
213217
upgrade,
@@ -228,7 +232,7 @@ pub fn resolver_options(resolver_args: ResolverArgs, build_args: BuildArgs) -> R
228232
no_sources,
229233
} = resolver_args;
230234

231-
let BuildArgs {
235+
let BuildOptionsArgs {
232236
no_build,
233237
build,
234238
no_build_package,
@@ -281,10 +285,10 @@ pub fn resolver_options(resolver_args: ResolverArgs, build_args: BuildArgs) -> R
281285
}
282286
}
283287

284-
/// Construct the [`ResolverInstallerOptions`] from the [`ResolverInstallerArgs`] and [`BuildArgs`].
288+
/// Construct the [`ResolverInstallerOptions`] from the [`ResolverInstallerArgs`] and [`BuildOptionsArgs`].
285289
pub fn resolver_installer_options(
286290
resolver_installer_args: ResolverInstallerArgs,
287-
build_args: BuildArgs,
291+
build_args: BuildOptionsArgs,
288292
) -> ResolverInstallerOptions {
289293
let ResolverInstallerArgs {
290294
index_args,
@@ -311,7 +315,7 @@ pub fn resolver_installer_options(
311315
no_sources,
312316
} = resolver_installer_args;
313317

314-
let BuildArgs {
318+
let BuildOptionsArgs {
315319
no_build,
316320
build,
317321
no_build_package,

crates/uv-client/src/base_client.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ impl<'a> BaseClientBuilder<'a> {
191191
) -> Client {
192192
// Configure the builder.
193193
let client_builder = ClientBuilder::new()
194+
.http1_title_case_headers()
194195
.user_agent(user_agent)
195196
.pool_max_idle_per_host(20)
196197
.read_timeout(std::time::Duration::from_secs(timeout))

crates/uv-dev/Cargo.toml

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,16 @@ workspace = true
1818
[dependencies]
1919
distribution-filename = { workspace = true }
2020
distribution-types = { workspace = true }
21-
install-wheel-rs = { workspace = true }
2221
pep508_rs = { workspace = true }
2322
pypi-types = { workspace = true }
24-
uv-build = { workspace = true }
2523
uv-cache = { workspace = true, features = ["clap"] }
2624
uv-cli = { workspace = true }
2725
uv-client = { workspace = true }
28-
uv-configuration = { workspace = true }
29-
uv-dispatch = { workspace = true }
30-
uv-git = { workspace = true }
3126
uv-installer = { workspace = true }
3227
uv-macros = { workspace = true }
3328
uv-options-metadata = { workspace = true }
3429
uv-python = { workspace = true }
35-
uv-resolver = { workspace = true }
3630
uv-settings = { workspace = true, features = ["schemars"] }
37-
uv-types = { workspace = true }
3831
uv-workspace = { workspace = true, features = ["schemars"] }
3932

4033
# Any dependencies that are exclusively used in `uv-dev` should be listed as non-workspace
@@ -44,12 +37,11 @@ anyhow = { workspace = true }
4437
clap = { workspace = true, features = ["derive", "wrap_help"] }
4538
fs-err = { workspace = true, features = ["tokio"] }
4639
itertools = { workspace = true }
47-
markdown = "0.3.0"
40+
markdown = { version = "0.3.0" }
4841
owo-colors = { workspace = true }
4942
poloto = { version = "19.1.2", optional = true }
5043
pretty_assertions = { version = "1.4.0" }
5144
resvg = { version = "0.29.0", optional = true }
52-
rustc-hash = { workspace = true }
5345
schemars = { workspace = true }
5446
serde = { workspace = true }
5547
serde_json = { workspace = true }

0 commit comments

Comments
 (0)