Skip to content

Commit 6e8b8df

Browse files
committed
Fix schema
1 parent 097d08e commit 6e8b8df

19 files changed

Lines changed: 240 additions & 151 deletions

File tree

crates/uv-cli/src/lib.rs

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use uv_configuration::{
1414
ConfigSettingEntry, ExportFormat, IndexStrategy, KeyringProviderType, PackageNameSpecifier,
1515
TargetTriple, TrustedHost, TrustedPublishing, VersionControlSystem,
1616
};
17-
use uv_distribution_types::{Index, IndexUrl, Origin};
17+
use uv_distribution_types::{Index, IndexUrl, Origin, PipExtraIndex, PipFindLinks, PipIndex};
1818
use uv_normalize::{ExtraName, PackageName};
1919
use uv_pep508::Requirement;
2020
use uv_pypi_types::VerbatimParsedUrl;
@@ -772,48 +772,54 @@ impl<T> Maybe<T> {
772772
}
773773
}
774774

775-
/// Parse an `--index-url` argument into an [`Index`], mapping the empty string to `None`.
776-
fn parse_index_url(input: &str) -> Result<Maybe<Index>, String> {
775+
/// Parse an `--index-url` argument into an [`PipIndex`], mapping the empty string to `None`.
776+
fn parse_index_url(input: &str) -> Result<Maybe<PipIndex>, String> {
777777
if input.is_empty() {
778778
Ok(Maybe::None)
779779
} else {
780-
match IndexUrl::from_str(input).map(Index::from_index_url) {
781-
Ok(index) => Ok(Maybe::Some(Index {
780+
IndexUrl::from_str(input)
781+
.map(Index::from_index_url)
782+
.map(|index| Index {
782783
origin: Some(Origin::Cli),
783784
..index
784-
})),
785-
Err(err) => Err(err.to_string()),
786-
}
785+
})
786+
.map(PipIndex::from)
787+
.map(Maybe::Some)
788+
.map_err(|err| err.to_string())
787789
}
788790
}
789791

790-
/// Parse an `--extra-index-url` argument into an [`Index`], mapping the empty string to `None`.
791-
fn parse_extra_index_url(input: &str) -> Result<Maybe<Index>, String> {
792+
/// Parse an `--extra-index-url` argument into an [`PipExtraIndex`], mapping the empty string to `None`.
793+
fn parse_extra_index_url(input: &str) -> Result<Maybe<PipExtraIndex>, String> {
792794
if input.is_empty() {
793795
Ok(Maybe::None)
794796
} else {
795-
match IndexUrl::from_str(input).map(Index::from_extra_index_url) {
796-
Ok(index) => Ok(Maybe::Some(Index {
797+
IndexUrl::from_str(input)
798+
.map(Index::from_extra_index_url)
799+
.map(|index| Index {
797800
origin: Some(Origin::Cli),
798801
..index
799-
})),
800-
Err(err) => Err(err.to_string()),
801-
}
802+
})
803+
.map(PipExtraIndex::from)
804+
.map(Maybe::Some)
805+
.map_err(|err| err.to_string())
802806
}
803807
}
804808

805-
/// Parse a `--find-links` argument into an [`Index`], mapping the empty string to `None`.
806-
fn parse_find_links(input: &str) -> Result<Maybe<Index>, String> {
809+
/// Parse a `--find-links` argument into an [`PipFindLinks`], mapping the empty string to `None`.
810+
fn parse_find_links(input: &str) -> Result<Maybe<PipFindLinks>, String> {
807811
if input.is_empty() {
808812
Ok(Maybe::None)
809813
} else {
810-
match IndexUrl::from_str(input).map(Index::from_find_links) {
811-
Ok(index) => Ok(Maybe::Some(Index {
814+
IndexUrl::from_str(input)
815+
.map(Index::from_find_links)
816+
.map(|index| Index {
812817
origin: Some(Origin::Cli),
813818
..index
814-
})),
815-
Err(err) => Err(err.to_string()),
816-
}
819+
})
820+
.map(PipFindLinks::from)
821+
.map(Maybe::Some)
822+
.map_err(|err| err.to_string())
817823
}
818824
}
819825

@@ -3800,7 +3806,7 @@ pub struct IndexArgs {
38003806
/// The index given by this flag is given lower priority than all other
38013807
/// indexes specified via the `--extra-index-url` flag.
38023808
#[arg(long, short, env = "UV_INDEX_URL", value_parser = parse_index_url, help_heading = "Index options")]
3803-
pub index_url: Option<Maybe<Index>>,
3809+
pub index_url: Option<Maybe<PipIndex>>,
38043810

38053811
/// (Deprecated: use `--index` instead) Extra URLs of package indexes to use, in addition to `--index-url`.
38063812
///
@@ -3811,7 +3817,7 @@ pub struct IndexArgs {
38113817
/// `--index-url` (which defaults to PyPI). When multiple `--extra-index-url` flags are
38123818
/// provided, earlier values take priority.
38133819
#[arg(long, env = "UV_EXTRA_INDEX_URL", value_delimiter = ' ', value_parser = parse_extra_index_url, help_heading = "Index options")]
3814-
pub extra_index_url: Option<Vec<Maybe<Index>>>,
3820+
pub extra_index_url: Option<Vec<Maybe<PipExtraIndex>>>,
38153821

38163822
/// Locations to search for candidate distributions, in addition to those found in the registry
38173823
/// indexes.
@@ -3822,7 +3828,7 @@ pub struct IndexArgs {
38223828
/// If a URL, the page must contain a flat list of links to package files adhering to the
38233829
/// formats described above.
38243830
#[arg(long, short, value_parser = parse_find_links, help_heading = "Index options")]
3825-
pub find_links: Option<Vec<Maybe<Index>>>,
3831+
pub find_links: Option<Vec<Maybe<PipFindLinks>>>,
38263832

38273833
/// Ignore the registry index (e.g., PyPI), instead relying on direct URL dependencies and those
38283834
/// provided via `--find-links`.

crates/uv-cli/src/options.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use uv_cache::Refresh;
22
use uv_configuration::ConfigSettings;
3+
use uv_distribution_types::{PipExtraIndex, PipFindLinks, PipIndex};
34
use uv_resolver::PrereleaseMode;
45
use uv_settings::{Combine, PipOptions, ResolverInstallerOptions, ResolverOptions};
56

@@ -201,18 +202,20 @@ impl From<IndexArgs> for PipOptions {
201202
.combine(
202203
index.map(|index| index.into_iter().filter_map(Maybe::into_option).collect()),
203204
),
204-
index_url: index_url.and_then(Maybe::into_option),
205+
index_url: index_url.and_then(Maybe::into_option).map(PipIndex::from),
205206
extra_index_url: extra_index_url.map(|extra_index_urls| {
206207
extra_index_urls
207208
.into_iter()
208209
.filter_map(Maybe::into_option)
210+
.map(PipExtraIndex::from)
209211
.collect()
210212
}),
211213
no_index: if no_index { Some(true) } else { None },
212214
find_links: find_links.map(|find_links| {
213215
find_links
214216
.into_iter()
215217
.filter_map(Maybe::into_option)
218+
.map(PipFindLinks::from)
216219
.collect()
217220
}),
218221
..PipOptions::default()

crates/uv-dispatch/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ impl<'a> BuildContext for BuildDispatch<'a> {
156156
self.sources
157157
}
158158

159-
fn index_locations(&self) -> &IndexLocations {
159+
fn locations(&self) -> &IndexLocations {
160160
self.index_locations
161161
}
162162

crates/uv-distribution-types/src/index.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use std::str::FromStr;
2-
32
use thiserror::Error;
43
use url::Url;
54
use uv_auth::Credentials;
@@ -113,6 +112,7 @@ impl Index {
113112
}
114113
}
115114

115+
/// Set the [`Origin`] of the index.
116116
#[must_use]
117117
pub fn with_origin(mut self, origin: Origin) -> Self {
118118
self.origin = Some(origin);

crates/uv-distribution-types/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ pub use crate::index::*;
6161
pub use crate::index_url::*;
6262
pub use crate::installed::*;
6363
pub use crate::origin::*;
64+
pub use crate::pip_index::*;
6465
pub use crate::prioritized_distribution::*;
6566
pub use crate::resolution::*;
6667
pub use crate::resolved::*;
@@ -81,6 +82,7 @@ mod index;
8182
mod index_url;
8283
mod installed;
8384
mod origin;
85+
mod pip_index;
8486
mod prioritized_distribution;
8587
mod resolution;
8688
mod resolved;
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//! Compatibility structs for converting between [`IndexUrl`] and [`Index`]. These structs are
2+
//! parsed and deserialized as [`IndexUrl`], but are stored as [`Index`] with the appropriate
3+
//! flags set.
4+
5+
use serde::{Deserialize, Deserializer, Serialize};
6+
7+
use crate::{Index, IndexUrl};
8+
9+
macro_rules! impl_index {
10+
($name:ident, $from:expr) => {
11+
#[derive(Debug, Clone, Eq, PartialEq)]
12+
pub struct $name(Index);
13+
14+
impl From<$name> for Index {
15+
fn from(value: $name) -> Self {
16+
value.0
17+
}
18+
}
19+
20+
impl From<Index> for $name {
21+
fn from(value: Index) -> Self {
22+
Self(value)
23+
}
24+
}
25+
26+
impl Serialize for $name {
27+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
28+
where
29+
S: serde::Serializer,
30+
{
31+
self.0.url().serialize(serializer)
32+
}
33+
}
34+
35+
impl<'de> Deserialize<'de> for $name {
36+
fn deserialize<D>(deserializer: D) -> Result<$name, D::Error>
37+
where
38+
D: Deserializer<'de>,
39+
{
40+
IndexUrl::deserialize(deserializer).map($from).map(Self)
41+
}
42+
}
43+
44+
#[cfg(feature = "schemars")]
45+
impl schemars::JsonSchema for $name {
46+
fn schema_name() -> String {
47+
IndexUrl::schema_name()
48+
}
49+
50+
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
51+
IndexUrl::json_schema(gen)
52+
}
53+
}
54+
};
55+
}
56+
57+
impl_index!(PipIndex, Index::from_index_url);
58+
impl_index!(PipExtraIndex, Index::from_extra_index_url);
59+
impl_index!(PipFindLinks, Index::from_find_links);

crates/uv-distribution/src/metadata/lowering.rs

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use thiserror::Error;
66
use url::Url;
77

88
use uv_distribution_filename::DistExtension;
9-
use uv_distribution_types::Index;
9+
use uv_distribution_types::{Index, IndexLocations, Origin};
1010
use uv_git::GitReference;
1111
use uv_normalize::PackageName;
1212
use uv_pep440::VersionSpecifiers;
@@ -20,7 +20,7 @@ use uv_workspace::Workspace;
2020
pub struct LoweredRequirement(Requirement);
2121

2222
#[derive(Debug, Clone, Copy)]
23-
enum Origin {
23+
enum RequirementOrigin {
2424
/// The `tool.uv.sources` were read from the project.
2525
Project,
2626
/// The `tool.uv.sources` were read from the workspace root.
@@ -35,14 +35,15 @@ impl LoweredRequirement {
3535
project_dir: &'data Path,
3636
project_sources: &'data BTreeMap<PackageName, Sources>,
3737
project_indexes: &'data [Index],
38+
locations: &'data IndexLocations,
3839
workspace: &'data Workspace,
39-
) -> impl Iterator<Item = Result<LoweredRequirement, LoweringError>> + 'data {
40+
) -> impl Iterator<Item = Result<Self, LoweringError>> + 'data {
4041
let (source, origin) = if let Some(source) = project_sources.get(&requirement.name) {
41-
(Some(source), Origin::Project)
42+
(Some(source), RequirementOrigin::Project)
4243
} else if let Some(source) = workspace.sources().get(&requirement.name) {
43-
(Some(source), Origin::Workspace)
44+
(Some(source), RequirementOrigin::Workspace)
4445
} else {
45-
(None, Origin::Project)
46+
(None, RequirementOrigin::Project)
4647
};
4748
let source = source.cloned();
4849

@@ -152,16 +153,14 @@ impl LoweredRequirement {
152153
Source::Registry { index, marker } => {
153154
// Identify the named index from either the project indexes or the workspace indexes,
154155
// in that order.
155-
let Some(index) = project_indexes
156-
.iter()
156+
let Some(index) = locations
157+
.indexes()
158+
.filter(|index| matches!(index.origin, Some(Origin::Cli)))
159+
.chain(project_indexes.iter())
160+
.chain(workspace.indexes().iter())
157161
.find(|Index { name, .. }| {
158162
name.as_ref().is_some_and(|name| *name == index)
159163
})
160-
.or_else(|| {
161-
workspace.indexes().iter().find(|Index { name, .. }| {
162-
name.as_ref().is_some_and(|name| *name == index)
163-
})
164-
})
165164
.map(|Index { url: index, .. }| index.clone())
166165
else {
167166
return Err(LoweringError::MissingIndex(
@@ -257,7 +256,8 @@ impl LoweredRequirement {
257256
dir: &'data Path,
258257
sources: &'data BTreeMap<PackageName, Sources>,
259258
indexes: &'data [Index],
260-
) -> impl Iterator<Item = Result<LoweredRequirement, LoweringError>> + 'data {
259+
locations: &'data IndexLocations,
260+
) -> impl Iterator<Item = Result<Self, LoweringError>> + 'data {
261261
let source = sources.get(&requirement.name).cloned();
262262

263263
let Some(source) = source else {
@@ -329,16 +329,18 @@ impl LoweredRequirement {
329329
}
330330
let source = path_source(
331331
PathBuf::from(path),
332-
Origin::Project,
332+
RequirementOrigin::Project,
333333
dir,
334334
dir,
335335
editable.unwrap_or(false),
336336
)?;
337337
(source, marker)
338338
}
339339
Source::Registry { index, marker } => {
340-
let Some(index) = indexes
341-
.iter()
340+
let Some(index) = locations
341+
.indexes()
342+
.filter(|index| matches!(index.origin, Some(Origin::Cli)))
343+
.chain(indexes.iter())
342344
.find(|Index { name, .. }| {
343345
name.as_ref().is_some_and(|name| *name == index)
344346
})
@@ -505,15 +507,15 @@ fn registry_source(
505507
/// Convert a path string to a file or directory source.
506508
fn path_source(
507509
path: impl AsRef<Path>,
508-
origin: Origin,
510+
origin: RequirementOrigin,
509511
project_dir: &Path,
510512
workspace_root: &Path,
511513
editable: bool,
512514
) -> Result<RequirementSource, LoweringError> {
513515
let path = path.as_ref();
514516
let base = match origin {
515-
Origin::Project => project_dir,
516-
Origin::Workspace => workspace_root,
517+
RequirementOrigin::Project => project_dir,
518+
RequirementOrigin::Workspace => workspace_root,
517519
};
518520
let url = VerbatimUrl::from_path(path, base)?.with_given(path.to_string_lossy());
519521
let install_path = url.to_file_path().map_err(|()| {

crates/uv-distribution/src/metadata/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::path::Path;
44
use thiserror::Error;
55

66
use uv_configuration::SourceStrategy;
7+
use uv_distribution_types::IndexLocations;
78
use uv_normalize::{ExtraName, GroupName, PackageName};
89
use uv_pep440::{Version, VersionSpecifiers};
910
use uv_pypi_types::{HashDigest, ResolutionMetadata};
@@ -61,6 +62,7 @@ impl Metadata {
6162
pub async fn from_workspace(
6263
metadata: ResolutionMetadata,
6364
install_path: &Path,
65+
locations: &IndexLocations,
6466
sources: SourceStrategy,
6567
) -> Result<Self, MetadataError> {
6668
// Lower the requirements.
@@ -76,6 +78,7 @@ impl Metadata {
7678
provides_extras: metadata.provides_extras,
7779
},
7880
install_path,
81+
locations,
7982
sources,
8083
)
8184
.await?;

0 commit comments

Comments
 (0)