Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add uv-workspace crate with settings discovery and deserialization #3007

Merged
merged 1 commit into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ uv-auth = { path = "crates/uv-auth" }
uv-build = { path = "crates/uv-build" }
uv-cache = { path = "crates/uv-cache" }
uv-client = { path = "crates/uv-client" }
uv-configuration = { path = "crates/uv-configuration" }
uv-dev = { path = "crates/uv-dev" }
uv-dispatch = { path = "crates/uv-dispatch" }
uv-distribution = { path = "crates/uv-distribution" }
Expand All @@ -43,13 +44,13 @@ uv-interpreter = { path = "crates/uv-interpreter" }
uv-normalize = { path = "crates/uv-normalize" }
uv-requirements = { path = "crates/uv-requirements" }
uv-resolver = { path = "crates/uv-resolver" }
uv-types = { path = "crates/uv-types" }
uv-configuration = { path = "crates/uv-configuration" }
uv-toolchain = { path = "crates/uv-toolchain" }
uv-trampoline = { path = "crates/uv-trampoline" }
uv-types = { path = "crates/uv-types" }
uv-version = { path = "crates/uv-version" }
uv-virtualenv = { path = "crates/uv-virtualenv" }
uv-warnings = { path = "crates/uv-warnings" }
uv-toolchain = { path = "crates/uv-toolchain" }
uv-workspace = { path = "crates/uv-workspace" }

anstream = { version = "0.6.13" }
anyhow = { version = "1.0.80" }
Expand Down Expand Up @@ -118,6 +119,7 @@ rmp-serde = { version = "1.1.2" }
rust-netrc = { version = "0.1.1" }
rustc-hash = { version = "1.1.0" }
same-file = { version = "1.0.6" }
schemars = { version = "0.8.16" }
seahash = { version = "4.1.0" }
serde = { version = "1.0.197" }
serde_json = { version = "1.0.114" }
Expand Down
3 changes: 2 additions & 1 deletion crates/install-wheel-rs/src/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use std::time::SystemTime;
use fs_err as fs;
use fs_err::{DirEntry, File};
use reflink_copy as reflink;
use serde::{Deserialize, Serialize};
use tempfile::tempdir_in;
use tracing::{debug, instrument};

Expand Down Expand Up @@ -201,7 +202,7 @@ fn parse_scripts(
scripts_from_ini(extras, python_minor, ini)
}

#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
pub enum LinkMode {
/// Clone (i.e., copy-on-write) packages from the wheel into the site packages.
Expand Down
1 change: 1 addition & 0 deletions crates/uv-auth/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ once_cell = { workspace = true }
reqwest = { workspace = true }
reqwest-middleware = { workspace = true }
rust-netrc = { workspace = true }
serde = { workspace = true, optional = true }
thiserror = { workspace = true }
tracing = { workspace = true }
url = { workspace = true }
Expand Down
1 change: 1 addition & 0 deletions crates/uv-configuration/src/authentication.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use uv_auth::{self, KeyringProvider};
/// Keyring provider type to use for credential lookup.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
pub enum KeyringProviderType {
/// Do not use keyring for credential lookup.
#[default]
Expand Down
1 change: 1 addition & 0 deletions crates/uv-configuration/src/build_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ impl NoBuild {

#[derive(Debug, Default, Clone, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
pub enum IndexStrategy {
/// Only use results from the first index that returns a match for a given package name.
///
Expand Down
81 changes: 71 additions & 10 deletions crates/uv-configuration/src/config_settings.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use serde::ser::SerializeMap;
use std::{
collections::{btree_map::Entry, BTreeMap},
str::FromStr,
Expand Down Expand Up @@ -35,12 +36,53 @@ enum ConfigSettingValue {
List(Vec<String>),
}

#[cfg(feature = "serde")]
impl serde::Serialize for ConfigSettingValue {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
ConfigSettingValue::String(value) => serializer.serialize_str(value),
ConfigSettingValue::List(values) => serializer.collect_seq(values.iter()),
}
}
}

#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for ConfigSettingValue {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct Visitor;

impl<'de> serde::de::Visitor<'de> for Visitor {
type Value = ConfigSettingValue;

fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a string or list of strings")
}

fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<Self::Value, E> {
Ok(ConfigSettingValue::String(value.to_string()))
}

fn visit_seq<A: serde::de::SeqAccess<'de>>(
self,
mut seq: A,
) -> Result<Self::Value, A::Error> {
let mut values = Vec::new();
while let Some(value) = seq.next_element()? {
values.push(value);
}
Ok(ConfigSettingValue::List(values))
}
}

deserializer.deserialize_any(Visitor)
}
}

/// Settings to pass to a PEP 517 build backend, structured as a map from (string) key to string or
/// list of strings.
///
/// See: <https://peps.python.org/pep-0517/#config-settings>
#[derive(Debug, Default, Clone)]
#[cfg_attr(not(feature = "serde"), allow(dead_code))]
pub struct ConfigSettings(BTreeMap<String, ConfigSettingValue>);

impl FromIterator<ConfigSettingEntry> for ConfigSettings {
Expand Down Expand Up @@ -77,20 +119,39 @@ impl ConfigSettings {
#[cfg(feature = "serde")]
impl serde::Serialize for ConfigSettings {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
use serde::ser::SerializeMap;

let mut map = serializer.serialize_map(Some(self.0.len()))?;
for (key, value) in &self.0 {
match value {
ConfigSettingValue::String(value) => {
map.serialize_entry(&key, &value)?;
}
ConfigSettingValue::List(values) => {
map.serialize_entry(&key, &values)?;
map.serialize_entry(key, value)?;
}
map.end()
}
}

#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for ConfigSettings {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct Visitor;

impl<'de> serde::de::Visitor<'de> for Visitor {
type Value = ConfigSettings;

fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a map from string to string or list of strings")
}

fn visit_map<A: serde::de::MapAccess<'de>>(
self,
mut map: A,
) -> Result<Self::Value, A::Error> {
let mut config = BTreeMap::default();
while let Some((key, value)) = map.next_entry()? {
config.insert(key, value);
}
Ok(ConfigSettings(config))
}
}
map.end()

deserializer.deserialize_map(Visitor)
}
}

Expand Down
38 changes: 38 additions & 0 deletions crates/uv-configuration/src/name_specifiers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,44 @@ impl FromStr for PackageNameSpecifier {
}
}

#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for PackageNameSpecifier {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct Visitor;

impl<'de> serde::de::Visitor<'de> for Visitor {
type Value = PackageNameSpecifier;

fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a package name or `:all:` or `:none:`")
}

fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
// Accept the special values `:all:` and `:none:`.
match value {
":all:" => Ok(PackageNameSpecifier::All),
":none:" => Ok(PackageNameSpecifier::None),
_ => {
// Otherwise, parse the value as a package name.
match PackageName::from_str(value) {
Ok(name) => Ok(PackageNameSpecifier::Package(name)),
Err(err) => Err(E::custom(err)),
}
}
}
}
}

deserializer.deserialize_str(Visitor)
}
}

/// Package name specification.
///
/// Consumes both package names and selection directives for compatibility with pip flags
Expand Down
1 change: 1 addition & 0 deletions crates/uv-resolver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ petgraph = { workspace = true }
pubgrub = { workspace = true }
rkyv = { workspace = true }
rustc-hash = { workspace = true }
serde = { workspace = true, optional = true }
textwrap = { workspace = true }
thiserror = { workspace = true }
tokio = { workspace = true, features = ["macros"] }
Expand Down
1 change: 1 addition & 0 deletions crates/uv-resolver/src/exclude_newer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use chrono::{DateTime, Days, NaiveDate, NaiveTime, Utc};

/// A timestamp that excludes files newer than it.
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct ExcludeNewer(DateTime<Utc>);

impl ExcludeNewer {
Expand Down
1 change: 1 addition & 0 deletions crates/uv-resolver/src/prerelease_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::Manifest;

#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
pub enum PreReleaseMode {
/// Disallow all pre-release versions.
Disallow,
Expand Down
1 change: 1 addition & 0 deletions crates/uv-resolver/src/resolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use crate::{Manifest, ResolveError};
/// package.
#[derive(Debug, Default, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
pub enum AnnotationStyle {
/// Render the annotations on a single, comma-separated line.
Line,
Expand Down
1 change: 1 addition & 0 deletions crates/uv-resolver/src/resolution_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::Manifest;

#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
pub enum ResolutionMode {
/// Resolve the highest compatible version of each package.
#[default]
Expand Down
Loading
Loading