Skip to content

Commit

Permalink
Add uv-workspace crate with settings discovery and deserialization
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Apr 15, 2024
1 parent f6b1580 commit 87b0f7f
Show file tree
Hide file tree
Showing 21 changed files with 398 additions and 18 deletions.
66 changes: 66 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 @@ -12,6 +12,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-auth/src/keyring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::store::{BasicAuthData, Credential};
/// See <https://pip.pypa.io/en/stable/topics/authentication/#keyring-support>
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
pub enum KeyringProvider {
/// Will not use keyring for authentication
#[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

0 comments on commit 87b0f7f

Please sign in to comment.