Skip to content

Commit 1530fca

Browse files
committed
feat: treat 4-component versions (e.g. pandas-stubs) as patch updates
1 parent 1e1b510 commit 1530fca

File tree

3 files changed

+111
-2
lines changed

3 files changed

+111
-2
lines changed

src/output/table.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,14 @@ fn color_updated_constraint(
216216
let colored = new_parts[2..].join(".").truecolor(r, g, b).to_string();
217217
format!("{}{}", plain, colored)
218218
}
219-
_ => latest.to_string(),
219+
_ => {
220+
// diff is at component 3+ (e.g. pandas-stubs 3.0.0 → 3.0.0.260204)
221+
// treat as patch: keep first two components plain, color the rest
222+
let (r, g, b) = p.patch;
223+
let plain = format!("{}.{}.", new_parts[0], new_parts[1]);
224+
let colored = new_parts[2..].join(".").truecolor(r, g, b).to_string();
225+
format!("{}{}", plain, colored)
226+
}
220227
};
221228

222229
// Append the upper bound dimmed if present
@@ -338,10 +345,27 @@ mod tests {
338345

339346
#[test]
340347
fn test_color_updated_constraint_four_component_version() {
348+
// 1.0.0.0 → 1.0.0.1: plain prefix "1.0." + patch-colored "0.1"
341349
let result =
342350
color_updated_constraint(">=1.0.0.0", "1.0.0.1", ">=1.0.0.1", &ColorScheme::Default);
343-
assert!(result.contains("1.0.0.1"));
344351
assert!(result.contains(">="));
352+
assert!(result.contains("1.0."));
353+
assert!(result.contains("0.1"));
354+
}
355+
356+
#[test]
357+
fn test_color_updated_constraint_three_to_four_component() {
358+
// pandas-stubs style: 3.0.0 → 3.0.0.260204 (new 4th component)
359+
// plain prefix "3.0." + patch-colored "0.260204"
360+
let result = color_updated_constraint(
361+
">=3.0.0",
362+
"3.0.0.260204",
363+
">=3.0.0.260204",
364+
&ColorScheme::Default,
365+
);
366+
assert!(result.contains(">="));
367+
assert!(result.contains("3.0."));
368+
assert!(result.contains("260204"));
345369
}
346370

347371
#[test]

src/version/compare.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,18 @@ mod tests {
171171
assert!(!is_newer("1.0.0", "not-a-version"));
172172
}
173173

174+
#[test]
175+
fn test_is_newer_four_component() {
176+
// pandas-stubs style: 3.0.0.260204 is newer than 3.0.0
177+
assert!(is_newer("3.0.0.260204", "3.0.0"));
178+
// and newer than a prior 4-component release
179+
assert!(is_newer("3.0.0.260204", "3.0.0.250204"));
180+
// same 4-component version is not newer
181+
assert!(!is_newer("3.0.0.260204", "3.0.0.260204"));
182+
// older 4-component is not newer than current
183+
assert!(!is_newer("3.0.0.250204", "3.0.0.260204"));
184+
}
185+
174186
#[test]
175187
fn test_classify_bump_major() {
176188
assert_eq!(classify_bump("1.0.0", "2.0.0"), BumpKind::Major);
@@ -188,6 +200,61 @@ mod tests {
188200
fn test_classify_bump_patch() {
189201
assert_eq!(classify_bump("1.0.0", "1.0.1"), BumpKind::Patch);
190202
assert_eq!(classify_bump("7.3.0", "7.3.1"), BumpKind::Patch);
203+
// 4-component versions (e.g. pandas-stubs 3.0.0 → 3.0.0.260204)
204+
assert_eq!(classify_bump("3.0.0", "3.0.0.260204"), BumpKind::Patch);
205+
assert_eq!(classify_bump("3.0.0.250204", "3.0.0.260204"), BumpKind::Patch);
206+
}
207+
208+
#[tokio::test]
209+
async fn test_check_dep_four_component_update() {
210+
// pandas-stubs pattern: current >=3.0.0, latest 3.0.0.260204
211+
use wiremock::matchers::{method, path};
212+
use wiremock::{Mock, MockServer, ResponseTemplate};
213+
214+
let server = MockServer::start().await;
215+
Mock::given(method("GET"))
216+
.and(path("/pypi/pandas-stubs/json"))
217+
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
218+
"info": { "version": "3.0.0.260204" }
219+
})))
220+
.mount(&server)
221+
.await;
222+
223+
let client = PypiClient::with_base_url(&server.uri()).unwrap();
224+
let dep = crate::parsers::Dependency {
225+
name: "pandas-stubs".to_string(),
226+
constraint: ">=3.0.0".to_string(),
227+
};
228+
let update = check_dep(&client, &dep).await.unwrap().unwrap();
229+
assert_eq!(update.latest, "3.0.0.260204");
230+
assert_eq!(update.bump_kind, BumpKind::Patch);
231+
assert_eq!(update.updated_constraint, ">=3.0.0.260204");
232+
}
233+
234+
#[tokio::test]
235+
async fn test_check_dep_four_component_to_four_component() {
236+
// pandas-stubs: current >=3.0.0.250204, latest 3.0.0.260204
237+
use wiremock::matchers::{method, path};
238+
use wiremock::{Mock, MockServer, ResponseTemplate};
239+
240+
let server = MockServer::start().await;
241+
Mock::given(method("GET"))
242+
.and(path("/pypi/pandas-stubs/json"))
243+
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
244+
"info": { "version": "3.0.0.260204" }
245+
})))
246+
.mount(&server)
247+
.await;
248+
249+
let client = PypiClient::with_base_url(&server.uri()).unwrap();
250+
let dep = crate::parsers::Dependency {
251+
name: "pandas-stubs".to_string(),
252+
constraint: ">=3.0.0.250204".to_string(),
253+
};
254+
let update = check_dep(&client, &dep).await.unwrap().unwrap();
255+
assert_eq!(update.latest, "3.0.0.260204");
256+
assert_eq!(update.bump_kind, BumpKind::Patch);
257+
assert_eq!(update.updated_constraint, ">=3.0.0.260204");
191258
}
192259

193260
// check_dep and find_updates - network paths covered via wiremock.

src/version/constraint.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,15 @@ mod tests {
176176
assert_eq!(extract_base_version(""), None);
177177
assert_eq!(extract_base_version(">=1.0,<2.0"), Some("1.0".to_string()));
178178
assert_eq!(extract_base_version("~7.3.0"), Some("7.3.0".to_string()));
179+
// 4-component (pandas-stubs style)
180+
assert_eq!(
181+
extract_base_version(">=3.0.0.250204"),
182+
Some("3.0.0.250204".to_string())
183+
);
184+
assert_eq!(
185+
extract_base_version("==3.0.0.260204"),
186+
Some("3.0.0.260204".to_string())
187+
);
179188
}
180189

181190
#[test]
@@ -194,6 +203,15 @@ mod tests {
194203
assert_eq!(update_constraint("^1.10.0", "2.6.0"), "^2.6.0");
195204
assert_eq!(update_constraint("0.1.6", "0.3.0"), "0.3.0");
196205
assert_eq!(update_constraint("*", "1.0.0"), "*");
206+
// 4-component new version (pandas-stubs style)
207+
assert_eq!(
208+
update_constraint(">=3.0.0", "3.0.0.260204"),
209+
">=3.0.0.260204"
210+
);
211+
assert_eq!(
212+
update_constraint(">=3.0.0.250204", "3.0.0.260204"),
213+
">=3.0.0.260204"
214+
);
197215
}
198216

199217
#[test]

0 commit comments

Comments
 (0)