Skip to content

Commit ee82a51

Browse files
committed
[#16] Moved PackageVersion to version.rs (#21)
- Moved PackageVersion to version.rs - Fixed some doc stuff
1 parent d51fd8a commit ee82a51

File tree

2 files changed

+268
-261
lines changed

2 files changed

+268
-261
lines changed

src/lib.rs

Lines changed: 6 additions & 261 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*!
22
# Handling of `PEP-440`
3-
This library implements Pythons Package versioning system.
3+
This library implements Python's Package versioning system.
44
55
Read more at <https://peps.python.org/pep-0440/>
66
@@ -32,273 +32,18 @@ assert!(
3232
);
3333
```
3434
*/
35-
use anyhow::Result;
36-
use serde::{Deserialize, Serialize};
37-
use std::fmt;
3835

3936
#[macro_use]
4037
extern crate derivative;
4138

4239
mod validator;
40+
// Expose validate_440_version function
4341
pub use validator::validate_440_version;
4442

4543
/// Identifiers (i.e. the components of a version string)
44+
// Expose Ids Module
4645
pub mod ids;
47-
use ids::{DevHead, PostHead, PostHeader, PreHeader, ReleaseHeader};
4846

49-
/// `PEP-440` Compliant versioning system
50-
///
51-
//# This struct is sorted so that PartialOrd
52-
//# correctly interprets priority
53-
//# Lower == More important
54-
///
55-
/// # Example Usage
56-
/// ```
57-
///# use pyver::PackageVersion;
58-
/// let _ = PackageVersion::new("v1.0");
59-
/// ```
60-
#[derive(Derivative, Debug, Serialize, Deserialize)]
61-
#[derivative(PartialOrd, PartialEq)]
62-
pub struct PackageVersion {
63-
/// ## Original String
64-
/// Just holds the original string passed in when creating
65-
/// the `PackageVersion` as some formating data is lost
66-
/// when parsing the string
67-
#[derivative(PartialOrd = "ignore", PartialEq = "ignore")]
68-
pub original: String,
69-
70-
/// ## `PEP-440` Local version identifier
71-
/// Local version sorting will have to be it's own issue
72-
/// since there are no limits to what a local version can be
73-
///
74-
/// For those who can read regex here it is for the local version:
75-
/// `[a-z0-9]+(?:(?:[\-_.][a-z0-9]+)+)?`
76-
///
77-
/// Here in Rulex:
78-
/// ```toml
79-
/// ['a'-'z' '0'-'9']+
80-
/// ((["-" "_" "."] ['a'-'z' '0'-'9']+)+)?
81-
/// ```
82-
#[derivative(PartialOrd = "ignore", PartialEq = "ignore")]
83-
pub local: Option<String>,
84-
85-
/// ## `PEP-440` Developmental release identifier
86-
pub dev: Option<DevHead>,
87-
88-
/// ## `PEP-440` Post-Release identifier
89-
pub post: Option<PostHeader>,
90-
91-
/// ## `PEP-440` Pre-Release identifier
92-
pub pre: Option<PreHeader>,
93-
94-
/// ## `PEP-440` Release number
95-
pub release: ReleaseHeader,
96-
97-
/// ## `PEP-440` Version-Epoch
98-
pub epoch: Option<u32>,
99-
}
100-
101-
impl PackageVersion {
102-
pub fn new(version: &str) -> Result<Self> {
103-
let version_match = validate_440_version(version)?;
104-
105-
let epoch: Option<u32> = match version_match.name("epoch") {
106-
// Convert Epoch String to Epoch Number
107-
Some(v) => Some(v.as_str().parse::<u32>()?),
108-
None => None,
109-
};
110-
111-
let release: ReleaseHeader = match version_match.name("release") {
112-
Some(v) => {
113-
// Does Release String contain minor version
114-
if v.as_str().contains('.') {
115-
let split: Vec<&str> = v.as_str().split('.').into_iter().collect();
116-
ReleaseHeader {
117-
major: split[0].parse::<u32>()?,
118-
minor: split[1].parse::<u32>()?,
119-
}
120-
} else {
121-
ReleaseHeader {
122-
major: v.as_str().parse::<u32>()?,
123-
minor: 0,
124-
}
125-
}
126-
}
127-
// There always has to be at least a major version
128-
None => anyhow::bail!("Failed to decode version {}", version),
129-
};
130-
131-
let pre: Option<PreHeader> = match version_match.name("pre") {
132-
Some(_) => {
133-
let pre_n = match version_match.name("pre_n") {
134-
Some(v) => Some(v.as_str().parse::<u32>()?),
135-
None => None,
136-
};
137-
138-
// Should be safe to unwrap since we already checked if pre has a value
139-
// since pre_n has to exist
140-
match version_match.name("pre_l").unwrap().as_str() {
141-
"alpha" => Some(PreHeader::Alpha(pre_n)),
142-
"a" => Some(PreHeader::Alpha(pre_n)),
143-
"beta" => Some(PreHeader::Beta(pre_n)),
144-
"b" => Some(PreHeader::Beta(pre_n)),
145-
"rc" => Some(PreHeader::ReleaseCandidate(pre_n)),
146-
"c" => Some(PreHeader::ReleaseCandidate(pre_n)),
147-
"preview" => Some(PreHeader::Preview(pre_n)),
148-
"pre" => Some(PreHeader::Preview(pre_n)),
149-
_ => None,
150-
}
151-
}
152-
None => None,
153-
};
154-
155-
let post: Option<PostHeader> = match version_match.name("post") {
156-
Some(_) => {
157-
let post_num: Option<u32> = match version_match.name("post_n1") {
158-
Some(v) => Some(v.as_str().parse::<u32>()?),
159-
None => match version_match.name("post_n2") {
160-
Some(v) => Some(v.as_str().parse::<u32>()?),
161-
_ => None,
162-
},
163-
};
164-
165-
let post_head: Option<PostHead> = match version_match.name("post_l") {
166-
Some(v) => {
167-
match v.as_str() {
168-
"post" => Some(PostHead::Post),
169-
"rev" => Some(PostHead::Rev),
170-
"r" => Some(PostHead::Rev),
171-
// This branch Should be impossible (see regex-group post_l)
172-
_ => None,
173-
}
174-
}
175-
None => None,
176-
};
177-
178-
Some(PostHeader {
179-
post_head,
180-
post_num,
181-
})
182-
}
183-
None => None,
184-
};
185-
186-
let dev: Option<DevHead> = match version_match.name("dev") {
187-
Some(_) => {
188-
let dev_num = match version_match.name("dev_n") {
189-
Some(v) => Some(v.as_str().parse::<u32>()?),
190-
None => None,
191-
};
192-
Some(DevHead { dev_num })
193-
}
194-
None => None,
195-
};
196-
197-
let local: Option<String> =
198-
version_match.name("local").map(|v| v.as_str().to_string());
199-
200-
Ok(Self {
201-
original: version.to_string(),
202-
epoch,
203-
release,
204-
pre,
205-
post,
206-
dev,
207-
local,
208-
})
209-
}
210-
}
211-
212-
impl fmt::Display for PackageVersion {
213-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
214-
write!(f, "{}", self.original)
215-
}
216-
}
217-
218-
#[cfg(test)]
219-
mod tests {
220-
use crate::PackageVersion;
221-
use anyhow::Result;
222-
223-
#[test]
224-
fn test_pep440_ordering() -> Result<()> {
225-
assert!(
226-
PackageVersion::new(
227-
"v1!1.0-preview-921.post-516.dev-241+yeah.this.is.the.problem.with.local.versions",
228-
)?
229-
>
230-
PackageVersion::new("1.0")?
231-
);
232-
Ok(())
233-
}
234-
235-
#[test]
236-
fn test_pep440_equality() -> Result<()> {
237-
assert_eq!(
238-
PackageVersion::new("1.0a1")?,
239-
PackageVersion::new("1.0alpha1")?
240-
);
241-
assert_eq!(
242-
PackageVersion::new("1.0b")?,
243-
PackageVersion::new("1.0beta")?
244-
);
245-
assert_eq!(PackageVersion::new("1.0r")?, PackageVersion::new("1.0rev")?);
246-
assert_eq!(PackageVersion::new("1.0c")?, PackageVersion::new("1.0rc")?);
247-
assert_eq!(PackageVersion::new("v1.0")?, PackageVersion::new("1.0")?);
248-
Ok(())
249-
}
250-
251-
#[test]
252-
fn test_pep440() {
253-
// list of every example mentioned in pep-440
254-
let versions = vec![
255-
"1.0",
256-
"v1.1",
257-
"2.0",
258-
"2013.10",
259-
"2014.04",
260-
"1!1.0",
261-
"1!1.1",
262-
"1!2.0",
263-
"2!1.0.pre0",
264-
"1.0.dev456",
265-
"1.0a1",
266-
"1.0a2.dev456",
267-
"1.0a12.dev456",
268-
"1.0a12",
269-
"1.0b1.dev456",
270-
"1.0b2",
271-
"1.0b2.post345.dev456",
272-
"1.0b2.post345",
273-
"1.0rc1.dev456",
274-
"1.0rc1",
275-
"1.0",
276-
"1.0+abc.5",
277-
"1.0+abc.7",
278-
"1.0+5",
279-
"1.0.post456.dev34",
280-
"1.0.post456",
281-
"1.0.15",
282-
"1.1.dev1",
283-
];
284-
285-
for version in versions {
286-
match PackageVersion::new(version) {
287-
Ok(_v) => continue,
288-
Err(e) => panic!("Oh no {}", e),
289-
}
290-
}
291-
}
292-
293-
#[test]
294-
fn test_pep440_negative() {
295-
let versions = vec!["not a version"];
296-
297-
for version in versions {
298-
match PackageVersion::new(version) {
299-
Ok(v) => panic!("Oh no {}", v),
300-
Err(_e) => continue,
301-
}
302-
}
303-
}
304-
}
47+
mod version;
48+
// Expose PackageVersion Struct
49+
pub use version::PackageVersion;

0 commit comments

Comments
 (0)