mirror of
https://github.com/hanzoai/pack.git
synced 2026-09-30 23:43:13 +00:00
171 lines
4.1 KiB
Go
171 lines
4.1 KiB
Go
package python
|
|
|
|
import (
|
|
"regexp"
|
|
|
|
"github.com/railwayapp/railpack-go/core/generate"
|
|
"github.com/railwayapp/railpack-go/core/plan"
|
|
)
|
|
|
|
const (
|
|
DEFAULT_PYTHON_VERSION = "3.13"
|
|
)
|
|
|
|
type PythonProvider struct{}
|
|
|
|
func (p *PythonProvider) Name() string {
|
|
return "python"
|
|
}
|
|
|
|
func (p *PythonProvider) Plan(ctx *generate.GenerateContext) (bool, error) {
|
|
hasPython := ctx.App.HasMatch("main.py") ||
|
|
p.hasRequirements(ctx) ||
|
|
p.hasPyproject(ctx) ||
|
|
p.hasPoetry(ctx) ||
|
|
p.hasPdm(ctx)
|
|
|
|
if !hasPython {
|
|
return false, nil
|
|
}
|
|
|
|
if err := p.packages(ctx); err != nil {
|
|
return false, err
|
|
}
|
|
|
|
if err := p.install(ctx); err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
func (p *PythonProvider) install(ctx *generate.GenerateContext) error {
|
|
install := ctx.NewProviderStep("install")
|
|
|
|
hasRequirements := p.hasRequirements(ctx)
|
|
hasPyproject := p.hasPyproject(ctx)
|
|
hasPipfile := p.hasPipfile(ctx)
|
|
hasPoetry := p.hasPoetry(ctx)
|
|
hasPdm := p.hasPdm(ctx)
|
|
hasUv := p.hasUv(ctx)
|
|
|
|
if hasRequirements {
|
|
install.AddCommands([]plan.Command{
|
|
plan.NewCopyCommand("requirements.txt"),
|
|
plan.NewExecCommand("pip install -r requirements.txt"),
|
|
})
|
|
} else if hasPyproject && hasPoetry {
|
|
install.AddCommands([]plan.Command{
|
|
plan.NewCopyCommand("pyproject.toml"),
|
|
plan.NewCopyCommand("poetry.lock"),
|
|
plan.NewExecCommand("poetry install --no-dev --no-interaction --no-ansi"),
|
|
})
|
|
} else if hasPyproject && hasPdm {
|
|
install.AddCommands([]plan.Command{
|
|
plan.NewCopyCommand("pyproject.toml"),
|
|
plan.NewCopyCommand("pdm.lock"),
|
|
plan.NewExecCommand("pdm install --prod"),
|
|
})
|
|
} else if hasPyproject && hasUv {
|
|
install.AddCommands([]plan.Command{
|
|
plan.NewCopyCommand("pyproject.toml"),
|
|
plan.NewCopyCommand("uv.lock"),
|
|
plan.NewExecCommand("uv sync --no-dev --frozen"),
|
|
})
|
|
} else if hasPipfile {
|
|
install.AddCommands([]plan.Command{
|
|
plan.NewCopyCommand("Pipfile"),
|
|
})
|
|
|
|
if ctx.App.HasMatch("Pipfile.lock") {
|
|
install.AddCommands([]plan.Command{
|
|
plan.NewCopyCommand("Pipfile.lock"),
|
|
plan.NewExecCommand("pipenv install --deploy"),
|
|
})
|
|
} else {
|
|
install.AddCommands([]plan.Command{
|
|
plan.NewExecCommand("pipenv install --skip-lock"),
|
|
})
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *PythonProvider) packages(ctx *generate.GenerateContext) error {
|
|
packages := ctx.NewPackageStep("packages")
|
|
|
|
python := packages.Default("python", DEFAULT_PYTHON_VERSION)
|
|
|
|
if envVersion := ctx.Env.GetConfigVariable("PYTHON_VERSION"); envVersion != "" {
|
|
packages.Version(python, envVersion, "RAILPACK_PYTHON_VERSION")
|
|
}
|
|
|
|
if versionFile, err := ctx.App.ReadFile(".python-version"); err == nil {
|
|
packages.Version(python, string(versionFile), ".python-version")
|
|
}
|
|
|
|
if runtimeFile, err := ctx.App.ReadFile("runtime.txt"); err == nil {
|
|
packages.Version(python, string(runtimeFile), "runtime.txt")
|
|
}
|
|
|
|
if pipfileVersion := parseVersionFromPipfile(ctx); pipfileVersion != "" {
|
|
packages.Version(python, pipfileVersion, "Pipfile")
|
|
}
|
|
|
|
if p.hasPoetry(ctx) {
|
|
packages.Default("poetry", "latest")
|
|
}
|
|
|
|
if p.hasUv(ctx) {
|
|
packages.Default("uv", "latest")
|
|
}
|
|
|
|
if p.hasPdm(ctx) {
|
|
packages.Default("pdm", "latest")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
var pipfileVersionRegex = regexp.MustCompile(`(python_version|python_full_version)\s*=\s*['"]([0-9.]*)"?`)
|
|
|
|
func parseVersionFromPipfile(ctx *generate.GenerateContext) string {
|
|
pipfile, err := ctx.App.ReadFile("Pipfile")
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
matches := pipfileVersionRegex.FindStringSubmatch(string(pipfile))
|
|
|
|
if len(matches) > 2 {
|
|
return matches[2]
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func (p *PythonProvider) hasRequirements(ctx *generate.GenerateContext) bool {
|
|
return ctx.App.HasMatch("requirements.txt")
|
|
}
|
|
|
|
func (p *PythonProvider) hasPyproject(ctx *generate.GenerateContext) bool {
|
|
return ctx.App.HasMatch("pyproject.toml")
|
|
}
|
|
|
|
func (p *PythonProvider) hasPipfile(ctx *generate.GenerateContext) bool {
|
|
return ctx.App.HasMatch("Pipfile")
|
|
}
|
|
|
|
func (p *PythonProvider) hasPoetry(ctx *generate.GenerateContext) bool {
|
|
return ctx.App.HasMatch("poetry.lock")
|
|
}
|
|
|
|
func (p *PythonProvider) hasPdm(ctx *generate.GenerateContext) bool {
|
|
return ctx.App.HasMatch("pdm.lock")
|
|
}
|
|
|
|
func (p *PythonProvider) hasUv(ctx *generate.GenerateContext) bool {
|
|
return ctx.App.HasMatch("uv.lock")
|
|
}
|