From a653670d04370fa69e0950133b5be861726f9fe0 Mon Sep 17 00:00:00 2001 From: konsti Date: Wed, 24 Apr 2024 13:16:10 +0200 Subject: [PATCH] Move RequirementsTxtRequirement to its own module (#3235) Small refactoring, no functional changes. --- crates/requirements-txt/src/lib.rs | 116 ++------------------- crates/requirements-txt/src/requirement.rs | 116 +++++++++++++++++++++ 2 files changed, 122 insertions(+), 110 deletions(-) create mode 100644 crates/requirements-txt/src/requirement.rs diff --git a/crates/requirements-txt/src/lib.rs b/crates/requirements-txt/src/lib.rs index 005a1c65d..b9e4d8878 100644 --- a/crates/requirements-txt/src/lib.rs +++ b/crates/requirements-txt/src/lib.rs @@ -46,10 +46,10 @@ use unscanny::{Pattern, Scanner}; use url::Url; use pep508_rs::{ - expand_env_vars, split_scheme, strip_host, Extras, MarkerEnvironment, MarkerTree, Pep508Error, - Pep508ErrorSource, Requirement, Scheme, UnnamedRequirement, VerbatimUrl, VersionOrUrl, - VersionOrUrlRef, + expand_env_vars, split_scheme, strip_host, Extras, Pep508Error, Pep508ErrorSource, Requirement, + Scheme, VerbatimUrl, }; +pub use requirement::RequirementsTxtRequirement; #[cfg(feature = "http")] use uv_client::BaseClient; use uv_client::BaseClientBuilder; @@ -58,6 +58,8 @@ use uv_fs::{normalize_url_path, Simplified}; use uv_normalize::ExtraName; use uv_warnings::warn_user; +mod requirement; + /// We emit one of those for each requirements.txt entry enum RequirementsTxtStatement { /// `-r` inclusion filename @@ -1281,6 +1283,7 @@ mod test { use tempfile::tempdir; use test_case::test_case; use unscanny::Scanner; + use uv_client::BaseClientBuilder; use uv_fs::Simplified; @@ -2184,110 +2187,3 @@ mod test { assert_eq!(line_column, expected, "Issues with input: {input}"); } } - -/// A requirement specifier in a `requirements.txt` file. -#[derive(Hash, Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] -pub enum RequirementsTxtRequirement { - /// A PEP 508-compliant dependency specifier. - Pep508(Requirement), - /// A PEP 508-like, direct URL dependency specifier. - Unnamed(UnnamedRequirement), -} - -impl Display for RequirementsTxtRequirement { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - match self { - Self::Pep508(requirement) => write!(f, "{requirement}"), - Self::Unnamed(requirement) => write!(f, "{requirement}"), - } - } -} - -impl RequirementsTxtRequirement { - /// Returns whether the markers apply for the given environment - pub fn evaluate_markers(&self, env: &MarkerEnvironment, extras: &[ExtraName]) -> bool { - match self { - Self::Pep508(requirement) => requirement.evaluate_markers(env, extras), - Self::Unnamed(requirement) => requirement.evaluate_markers(env, extras), - } - } - - /// Returns the extras for the requirement. - pub fn extras(&self) -> &[ExtraName] { - match self { - Self::Pep508(requirement) => requirement.extras.as_slice(), - Self::Unnamed(requirement) => requirement.extras.as_slice(), - } - } - - /// Returns the markers for the requirement. - pub fn markers(&self) -> Option<&MarkerTree> { - match self { - Self::Pep508(requirement) => requirement.marker.as_ref(), - Self::Unnamed(requirement) => requirement.marker.as_ref(), - } - } - - /// Return the version specifier or URL for the requirement. - pub fn version_or_url(&self) -> Option { - match self { - Self::Pep508(requirement) => match requirement.version_or_url.as_ref() { - Some(VersionOrUrl::VersionSpecifier(specifiers)) => { - Some(VersionOrUrlRef::VersionSpecifier(specifiers)) - } - Some(VersionOrUrl::Url(url)) => Some(VersionOrUrlRef::Url(url)), - None => None, - }, - Self::Unnamed(requirement) => Some(VersionOrUrlRef::Url(&requirement.url)), - } - } -} - -impl From for RequirementsTxtRequirement { - fn from(requirement: Requirement) -> Self { - Self::Pep508(requirement) - } -} - -impl From for RequirementsTxtRequirement { - fn from(requirement: UnnamedRequirement) -> Self { - Self::Unnamed(requirement) - } -} - -impl FromStr for RequirementsTxtRequirement { - type Err = Pep508Error; - - /// Parse a requirement as seen in a `requirements.txt` file. - fn from_str(input: &str) -> Result { - match Requirement::from_str(input) { - Ok(requirement) => Ok(Self::Pep508(requirement)), - Err(err) => match err.message { - Pep508ErrorSource::UnsupportedRequirement(_) => { - Ok(Self::Unnamed(UnnamedRequirement::from_str(input)?)) - } - _ => Err(err), - }, - } - } -} - -impl RequirementsTxtRequirement { - /// Parse a requirement as seen in a `requirements.txt` file. - pub fn parse(input: &str, working_dir: impl AsRef) -> Result { - // Attempt to parse as a PEP 508-compliant requirement. - match Requirement::parse(input, &working_dir) { - Ok(requirement) => Ok(Self::Pep508(requirement)), - Err(err) => match err.message { - Pep508ErrorSource::UnsupportedRequirement(_) => { - // If that fails, attempt to parse as a direct URL requirement. - Ok(Self::Unnamed(UnnamedRequirement::parse( - input, - &working_dir, - )?)) - } - _ => Err(err), - }, - } - } -} diff --git a/crates/requirements-txt/src/requirement.rs b/crates/requirements-txt/src/requirement.rs new file mode 100644 index 000000000..0382b4958 --- /dev/null +++ b/crates/requirements-txt/src/requirement.rs @@ -0,0 +1,116 @@ +use pep508_rs::{ + MarkerEnvironment, MarkerTree, Pep508Error, Pep508ErrorSource, Requirement, UnnamedRequirement, + VersionOrUrl, VersionOrUrlRef, +}; +use serde::{Deserialize, Serialize}; +use std::fmt::{Display, Formatter}; +use std::path::Path; +use std::str::FromStr; +use uv_normalize::ExtraName; + +/// A requirement specifier in a `requirements.txt` file. +#[derive(Hash, Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] +pub enum RequirementsTxtRequirement { + /// A PEP 508-compliant dependency specifier. + Pep508(Requirement), + /// A PEP 508-like, direct URL dependency specifier. + Unnamed(UnnamedRequirement), +} + +impl Display for RequirementsTxtRequirement { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + Self::Pep508(requirement) => write!(f, "{requirement}"), + Self::Unnamed(requirement) => write!(f, "{requirement}"), + } + } +} + +impl RequirementsTxtRequirement { + /// Returns whether the markers apply for the given environment + pub fn evaluate_markers(&self, env: &MarkerEnvironment, extras: &[ExtraName]) -> bool { + match self { + Self::Pep508(requirement) => requirement.evaluate_markers(env, extras), + Self::Unnamed(requirement) => requirement.evaluate_markers(env, extras), + } + } + + /// Returns the extras for the requirement. + pub fn extras(&self) -> &[ExtraName] { + match self { + Self::Pep508(requirement) => requirement.extras.as_slice(), + Self::Unnamed(requirement) => requirement.extras.as_slice(), + } + } + + /// Returns the markers for the requirement. + pub fn markers(&self) -> Option<&MarkerTree> { + match self { + Self::Pep508(requirement) => requirement.marker.as_ref(), + Self::Unnamed(requirement) => requirement.marker.as_ref(), + } + } + + /// Return the version specifier or URL for the requirement. + pub fn version_or_url(&self) -> Option { + match self { + Self::Pep508(requirement) => match requirement.version_or_url.as_ref() { + Some(VersionOrUrl::VersionSpecifier(specifiers)) => { + Some(VersionOrUrlRef::VersionSpecifier(specifiers)) + } + Some(VersionOrUrl::Url(url)) => Some(VersionOrUrlRef::Url(url)), + None => None, + }, + Self::Unnamed(requirement) => Some(VersionOrUrlRef::Url(&requirement.url)), + } + } +} + +impl From for RequirementsTxtRequirement { + fn from(requirement: Requirement) -> Self { + Self::Pep508(requirement) + } +} + +impl From for RequirementsTxtRequirement { + fn from(requirement: UnnamedRequirement) -> Self { + Self::Unnamed(requirement) + } +} + +impl FromStr for RequirementsTxtRequirement { + type Err = Pep508Error; + + /// Parse a requirement as seen in a `requirements.txt` file. + fn from_str(input: &str) -> Result { + match Requirement::from_str(input) { + Ok(requirement) => Ok(Self::Pep508(requirement)), + Err(err) => match err.message { + Pep508ErrorSource::UnsupportedRequirement(_) => { + Ok(Self::Unnamed(UnnamedRequirement::from_str(input)?)) + } + _ => Err(err), + }, + } + } +} + +impl RequirementsTxtRequirement { + /// Parse a requirement as seen in a `requirements.txt` file. + pub fn parse(input: &str, working_dir: impl AsRef) -> Result { + // Attempt to parse as a PEP 508-compliant requirement. + match Requirement::parse(input, &working_dir) { + Ok(requirement) => Ok(Self::Pep508(requirement)), + Err(err) => match err.message { + Pep508ErrorSource::UnsupportedRequirement(_) => { + // If that fails, attempt to parse as a direct URL requirement. + Ok(Self::Unnamed(UnnamedRequirement::parse( + input, + &working_dir, + )?)) + } + _ => Err(err), + }, + } + } +}