mirror of https://github.com/databricks/cli.git
extract parse.go
This commit is contained in:
parent
97109ec438
commit
c3b659c5e3
|
@ -0,0 +1,45 @@
|
||||||
|
package patchwheel
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WheelInfo contains information extracted from a wheel filename
|
||||||
|
type WheelInfo struct {
|
||||||
|
Distribution string // Package distribution name
|
||||||
|
Version string // Package version
|
||||||
|
Tags []string // Python tags (python_tag, abi_tag, platform_tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseWheelFilename parses a wheel filename and extracts its components.
|
||||||
|
// Wheel filenames follow the pattern: {distribution}-{version}-{python_tag}-{abi_tag}-{platform_tag}.whl
|
||||||
|
func ParseWheelFilename(filename string) (*WheelInfo, error) {
|
||||||
|
base := filepath.Base(filename)
|
||||||
|
parts := strings.Split(base, "-")
|
||||||
|
if len(parts) < 5 || !strings.HasSuffix(parts[len(parts)-1], ".whl") {
|
||||||
|
return nil, fmt.Errorf("invalid wheel filename format: %s", filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The last three parts are always tags
|
||||||
|
tagStartIdx := len(parts) - 3
|
||||||
|
|
||||||
|
// Everything before the tags except the version is the distribution
|
||||||
|
versionIdx := tagStartIdx - 1
|
||||||
|
|
||||||
|
// Distribution may contain hyphens, so join all parts before the version
|
||||||
|
distribution := strings.Join(parts[:versionIdx], "-")
|
||||||
|
version := parts[versionIdx]
|
||||||
|
|
||||||
|
// Extract tags (remove .whl from the last one)
|
||||||
|
tags := make([]string, 3)
|
||||||
|
copy(tags, parts[tagStartIdx:])
|
||||||
|
tags[2] = strings.TrimSuffix(tags[2], ".whl")
|
||||||
|
|
||||||
|
return &WheelInfo{
|
||||||
|
Distribution: distribution,
|
||||||
|
Version: version,
|
||||||
|
Tags: tags,
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
package patchwheel
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestParseWheelFilename tests the ParseWheelFilename function.
|
||||||
|
func TestParseWheelFilename(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
filename string
|
||||||
|
wantDistribution string
|
||||||
|
wantVersion string
|
||||||
|
wantTags []string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
filename: "myproj-0.1.0-py3-none-any.whl",
|
||||||
|
wantDistribution: "myproj",
|
||||||
|
wantVersion: "0.1.0",
|
||||||
|
wantTags: []string{"py3", "none", "any"},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
filename: "myproj-0.1.0+20240303123456-py3-none-any.whl",
|
||||||
|
wantDistribution: "myproj",
|
||||||
|
wantVersion: "0.1.0+20240303123456",
|
||||||
|
wantTags: []string{"py3", "none", "any"},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
filename: "my-proj-with-hyphens-0.1.0-py3-none-any.whl",
|
||||||
|
wantDistribution: "my-proj-with-hyphens",
|
||||||
|
wantVersion: "0.1.0",
|
||||||
|
wantTags: []string{"py3", "none", "any"},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
filename: "invalid-filename.txt",
|
||||||
|
wantDistribution: "",
|
||||||
|
wantVersion: "",
|
||||||
|
wantTags: nil,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
filename: "not-enough-parts-py3.whl",
|
||||||
|
wantDistribution: "",
|
||||||
|
wantVersion: "",
|
||||||
|
wantTags: nil,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.filename, func(t *testing.T) {
|
||||||
|
info, err := ParseWheelFilename(tt.filename)
|
||||||
|
if tt.wantErr {
|
||||||
|
require.Error(t, err)
|
||||||
|
} else {
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, tt.wantDistribution, info.Distribution)
|
||||||
|
require.Equal(t, tt.wantVersion, info.Version)
|
||||||
|
require.Equal(t, tt.wantTags, info.Tags)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -125,44 +125,6 @@ func readFile(file *zip.File) ([]byte, error) {
|
||||||
return io.ReadAll(rc)
|
return io.ReadAll(rc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WheelInfo contains information extracted from a wheel filename
|
|
||||||
type WheelInfo struct {
|
|
||||||
Distribution string // Package distribution name
|
|
||||||
Version string // Package version
|
|
||||||
Tags []string // Python tags (python_tag, abi_tag, platform_tag)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseWheelFilename parses a wheel filename and extracts its components.
|
|
||||||
// Wheel filenames follow the pattern: {distribution}-{version}-{python_tag}-{abi_tag}-{platform_tag}.whl
|
|
||||||
func ParseWheelFilename(filename string) (*WheelInfo, error) {
|
|
||||||
base := filepath.Base(filename)
|
|
||||||
parts := strings.Split(base, "-")
|
|
||||||
if len(parts) < 5 || !strings.HasSuffix(parts[len(parts)-1], ".whl") {
|
|
||||||
return nil, fmt.Errorf("invalid wheel filename format: %s", filename)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The last three parts are always tags
|
|
||||||
tagStartIdx := len(parts) - 3
|
|
||||||
|
|
||||||
// Everything before the tags except the version is the distribution
|
|
||||||
versionIdx := tagStartIdx - 1
|
|
||||||
|
|
||||||
// Distribution may contain hyphens, so join all parts before the version
|
|
||||||
distribution := strings.Join(parts[:versionIdx], "-")
|
|
||||||
version := parts[versionIdx]
|
|
||||||
|
|
||||||
// Extract tags (remove .whl from the last one)
|
|
||||||
tags := make([]string, 3)
|
|
||||||
copy(tags, parts[tagStartIdx:])
|
|
||||||
tags[2] = strings.TrimSuffix(tags[2], ".whl")
|
|
||||||
|
|
||||||
return &WheelInfo{
|
|
||||||
Distribution: distribution,
|
|
||||||
Version: version,
|
|
||||||
Tags: tags,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PatchWheel patches a Python wheel file by updating its version in METADATA and RECORD.
|
// PatchWheel patches a Python wheel file by updating its version in METADATA and RECORD.
|
||||||
// It returns the path to the new wheel.
|
// It returns the path to the new wheel.
|
||||||
// The function is idempotent: repeated calls with the same input will produce the same output.
|
// The function is idempotent: repeated calls with the same input will produce the same output.
|
||||||
|
|
|
@ -105,67 +105,6 @@ func getWheel(t *testing.T, dir string) string {
|
||||||
return matches[0]
|
return matches[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestParseWheelFilename tests the ParseWheelFilename function.
|
|
||||||
func TestParseWheelFilename(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
filename string
|
|
||||||
wantDistribution string
|
|
||||||
wantVersion string
|
|
||||||
wantTags []string
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
filename: "myproj-0.1.0-py3-none-any.whl",
|
|
||||||
wantDistribution: "myproj",
|
|
||||||
wantVersion: "0.1.0",
|
|
||||||
wantTags: []string{"py3", "none", "any"},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
filename: "myproj-0.1.0+20240303123456-py3-none-any.whl",
|
|
||||||
wantDistribution: "myproj",
|
|
||||||
wantVersion: "0.1.0+20240303123456",
|
|
||||||
wantTags: []string{"py3", "none", "any"},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
filename: "my-proj-with-hyphens-0.1.0-py3-none-any.whl",
|
|
||||||
wantDistribution: "my-proj-with-hyphens",
|
|
||||||
wantVersion: "0.1.0",
|
|
||||||
wantTags: []string{"py3", "none", "any"},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
filename: "invalid-filename.txt",
|
|
||||||
wantDistribution: "",
|
|
||||||
wantVersion: "",
|
|
||||||
wantTags: nil,
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
filename: "not-enough-parts-py3.whl",
|
|
||||||
wantDistribution: "",
|
|
||||||
wantVersion: "",
|
|
||||||
wantTags: nil,
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.filename, func(t *testing.T) {
|
|
||||||
info, err := ParseWheelFilename(tt.filename)
|
|
||||||
if tt.wantErr {
|
|
||||||
require.Error(t, err)
|
|
||||||
} else {
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, tt.wantDistribution, info.Distribution)
|
|
||||||
require.Equal(t, tt.wantVersion, info.Version)
|
|
||||||
require.Equal(t, tt.wantTags, info.Tags)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPatchWheel(t *testing.T) {
|
func TestPatchWheel(t *testing.T) {
|
||||||
pythonVersions := []string{"python3.9", "python3.10", "python3.11", "python3.12"}
|
pythonVersions := []string{"python3.9", "python3.10", "python3.11", "python3.12"}
|
||||||
for _, py := range pythonVersions {
|
for _, py := range pythonVersions {
|
||||||
|
|
Loading…
Reference in New Issue