Skip to content

Commit c6da04d

Browse files
committed
feat: add support for Python metadata version 2.5
1 parent fd1948c commit c6da04d

2 files changed

Lines changed: 166 additions & 0 deletions

File tree

internal/distributions/distribution.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ var HeaderAttrs2_4 = append(HeaderAttrs2_3, []HeaderAttr{ // PEP 639
124124
{"License-File", "license_file", false},
125125
}...)
126126

127+
var HeaderAttrs2_5 = HeaderAttrs2_4 // PEP 639 finalized
128+
127129
var HeaderAttrs = map[string][]HeaderAttr{
128130
"1.0": HeaderAttrs1_0,
129131
"1.1": HeaderAttrs1_1,
@@ -133,6 +135,7 @@ var HeaderAttrs = map[string][]HeaderAttr{
133135
"2.2": HeaderAttrs2_2,
134136
"2.3": HeaderAttrs2_3,
135137
"2.4": HeaderAttrs2_4,
138+
"2.5": HeaderAttrs2_5,
136139
}
137140

138141
type Distribution interface {
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
package distributions
2+
3+
import (
4+
"strings"
5+
"testing"
6+
)
7+
8+
func TestHeaderAttrsVersions(t *testing.T) {
9+
expectedVersions := []string{"1.0", "1.1", "1.2", "2.0", "2.1", "2.2", "2.3", "2.4", "2.5"}
10+
11+
for _, version := range expectedVersions {
12+
t.Run("version_"+version, func(t *testing.T) {
13+
attrs, exists := HeaderAttrs[version]
14+
if !exists {
15+
t.Errorf("metadata version %s not found in HeaderAttrs map", version)
16+
return
17+
}
18+
if len(attrs) == 0 {
19+
t.Errorf("metadata version %s has no header attributes", version)
20+
}
21+
})
22+
}
23+
}
24+
25+
func TestGetHeaderAttrs(t *testing.T) {
26+
tests := []struct {
27+
version string
28+
expectError bool
29+
}{
30+
{"1.0", false},
31+
{"1.1", false},
32+
{"1.2", false},
33+
{"2.0", false},
34+
{"2.1", false},
35+
{"2.2", false},
36+
{"2.3", false},
37+
{"2.4", false},
38+
{"2.5", false},
39+
{"9.9", true},
40+
}
41+
42+
for _, tt := range tests {
43+
t.Run("version_"+tt.version, func(t *testing.T) {
44+
bd := &BaseDistribution{MetadataVersion: tt.version}
45+
attrs, err := bd.GetHeaderAttrs()
46+
47+
if tt.expectError {
48+
if err == nil {
49+
t.Errorf("expected error for version %s, got nil", tt.version)
50+
}
51+
} else {
52+
if err != nil {
53+
t.Errorf("unexpected error for version %s: %v", tt.version, err)
54+
}
55+
if len(attrs) == 0 {
56+
t.Errorf("expected non-empty attrs for version %s", tt.version)
57+
}
58+
}
59+
})
60+
}
61+
}
62+
63+
func TestHeaderAttrs2_5HasLicenseExpression(t *testing.T) {
64+
attrs := HeaderAttrs2_5
65+
found := false
66+
for _, attr := range attrs {
67+
if attr.HeaderName == "License-Expression" {
68+
found = true
69+
break
70+
}
71+
}
72+
if !found {
73+
t.Error("HeaderAttrs2_5 should include License-Expression header")
74+
}
75+
}
76+
77+
func TestParseMetadataVersion2_5(t *testing.T) {
78+
metadata := `Metadata-Version: 2.5
79+
Name: test-package
80+
Version: 1.0.0
81+
Summary: A test package
82+
License-Expression: MIT
83+
84+
`
85+
bd := &BaseDistribution{}
86+
err := bd.Parse([]byte(metadata))
87+
if err != nil {
88+
t.Fatalf("failed to parse metadata version 2.5: %v", err)
89+
}
90+
91+
if bd.MetadataVersion != "2.5" {
92+
t.Errorf("expected metadata version 2.5, got %s", bd.MetadataVersion)
93+
}
94+
if bd.Name != "test-package" {
95+
t.Errorf("expected name test-package, got %s", bd.Name)
96+
}
97+
if bd.Version != "1.0.0" {
98+
t.Errorf("expected version 1.0.0, got %s", bd.Version)
99+
}
100+
if bd.LicenseExpression != "MIT" {
101+
t.Errorf("expected license expression MIT, got %s", bd.LicenseExpression)
102+
}
103+
}
104+
105+
func TestParseMetadataWithDescription(t *testing.T) {
106+
metadata := `Metadata-Version: 2.5
107+
Name: test-package
108+
Version: 1.0.0
109+
110+
This is the description body.
111+
It can have multiple lines.`
112+
113+
bd := &BaseDistribution{}
114+
err := bd.Parse([]byte(metadata))
115+
if err != nil {
116+
t.Fatalf("failed to parse metadata: %v", err)
117+
}
118+
119+
if !strings.Contains(bd.Description, "This is the description body") {
120+
t.Errorf("description not parsed correctly: %s", bd.Description)
121+
}
122+
}
123+
124+
func TestHeaderAttrsInheritance(t *testing.T) {
125+
hasAttr := func(attrs []HeaderAttr, name string) bool {
126+
for _, a := range attrs {
127+
if a.HeaderName == name {
128+
return true
129+
}
130+
}
131+
return false
132+
}
133+
134+
t.Run("2.1_has_provides_extra", func(t *testing.T) {
135+
if !hasAttr(HeaderAttrs2_1, "Provides-Extra") {
136+
t.Error("2.1 should have Provides-Extra")
137+
}
138+
})
139+
140+
t.Run("2.2_has_dynamic", func(t *testing.T) {
141+
if !hasAttr(HeaderAttrs2_2, "Dynamic") {
142+
t.Error("2.2 should have Dynamic")
143+
}
144+
})
145+
146+
t.Run("2.4_has_license_expression", func(t *testing.T) {
147+
if !hasAttr(HeaderAttrs2_4, "License-Expression") {
148+
t.Error("2.4 should have License-Expression")
149+
}
150+
})
151+
152+
t.Run("2.5_inherits_from_2.4", func(t *testing.T) {
153+
if !hasAttr(HeaderAttrs2_5, "License-Expression") {
154+
t.Error("2.5 should inherit License-Expression from 2.4")
155+
}
156+
if !hasAttr(HeaderAttrs2_5, "Dynamic") {
157+
t.Error("2.5 should inherit Dynamic from 2.2")
158+
}
159+
if !hasAttr(HeaderAttrs2_5, "Provides-Extra") {
160+
t.Error("2.5 should inherit Provides-Extra from 2.1")
161+
}
162+
})
163+
}

0 commit comments

Comments
 (0)