1
0
forked from rosa/hakurei
Files
hakurei/internal/rosa/python.go
Ophestra 1caa051f4d internal/rosa/python: hatchling artifact
Required by many python packages.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-19 22:35:18 +09:00

470 lines
12 KiB
Go

package rosa
import (
"path"
"slices"
"strings"
"hakurei.app/internal/pkg"
)
func (t Toolchain) newPython() (pkg.Artifact, string) {
const (
version = "3.14.4"
checksum = "X0VRAAGOlCVldh4J9tRAE-YrJtDvqfQTJaqxKPXNX6YTPlwpR9GwA5WRIZDO-63s"
)
return t.NewPackage("python", version, newTar(
"https://www.python.org/ftp/python/"+version+
"/Python-"+version+".tgz",
checksum,
pkg.TarGzip,
), &PackageAttr{
// test_synopsis_sourceless assumes this is writable and checks __pycache__
Writable: true,
Chmod: true,
Patches: []KV{
{"zipfile-no-default-strict_timestamps", `diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py
index 19aea290b58..51603ba9510 100644
--- a/Lib/zipfile/__init__.py
+++ b/Lib/zipfile/__init__.py
@@ -617,7 +617,7 @@ def _decodeExtra(self, filename_crc):
extra = extra[ln+4:]
@classmethod
- def from_file(cls, filename, arcname=None, *, strict_timestamps=True):
+ def from_file(cls, filename, arcname=None, *, strict_timestamps=False):
"""Construct an appropriate ZipInfo for a file on the filesystem.
filename should be the path to a file or directory on the filesystem.
@@ -1412,7 +1412,7 @@ class ZipFile:
_windows_illegal_name_trans_table = None
def __init__(self, file, mode="r", compression=ZIP_STORED, allowZip64=True,
- compresslevel=None, *, strict_timestamps=True, metadata_encoding=None):
+ compresslevel=None, *, strict_timestamps=False, metadata_encoding=None):
"""Open the ZIP file with mode read 'r', write 'w', exclusive create 'x',
or append 'a'."""
if mode not in ('r', 'w', 'x', 'a'):
`},
},
Env: []string{
"EXTRATESTOPTS=-j0 -x " + strings.Join([]string{
// requires internet access (http://www.pythontest.net/)
"test_asyncio",
"test_socket",
"test_urllib2",
"test_urllibnet",
"test_urllib2net",
// makes assumptions about uid_map/gid_map
"test_os",
"test_subprocess",
// patched out insane strict_timestamps default
"test_zipfile",
// requires gcc
"test_ctypes",
// breaks on llvm
"test_dbm_gnu",
}, " -x "),
// _ctypes appears to infer something from the linker name
"LDFLAGS=-Wl,--dynamic-linker=/system/lib/" +
"ld-musl-" + linuxArch() + ".so.1",
},
}, &MakeHelper{
Check: []string{"test"},
},
Zlib,
Bzip2,
Libffi,
OpenSSL,
PkgConfig,
XZ,
), version
}
func init() {
artifactsM[Python] = Metadata{
f: Toolchain.newPython,
Name: "python",
Description: "the Python programming language interpreter",
Website: "https://www.python.org/",
Dependencies: P{
Zlib,
Bzip2,
Libffi,
OpenSSL,
},
ID: 13254,
}
}
// PipHelper is the [Python] pip packaging helper.
type PipHelper struct {
// Path elements joined with source.
Append []string
// Whether to omit --no-build-isolation.
BuildIsolation bool
// Whether to enter source after install.
EnterSource bool
// Runs after install.
Script string
}
var _ Helper = new(PipHelper)
// extra returns python.
func (*PipHelper) extra(int) P { return P{Python} }
// wantsChmod returns true.
func (*PipHelper) wantsChmod() bool { return true }
// wantsWrite is equivalent to wantsChmod.
func (attr *PipHelper) wantsWrite() bool { return attr.wantsChmod() }
// scriptEarly is a noop.
func (*PipHelper) scriptEarly() string { return "" }
// createDir returns false.
func (*PipHelper) createDir() bool { return false }
// wantsDir requests a new directory in TMPDIR.
func (*PipHelper) wantsDir() string { return `"$(mktemp -d)"` }
// script generates the pip3 install command.
func (attr *PipHelper) script(name string) string {
if attr == nil {
attr = new(PipHelper)
}
var extra string
if !attr.BuildIsolation {
extra += `
--no-build-isolation \`
}
script := attr.Script
if attr.EnterSource {
script = "cd '/usr/src/" + name + "'\n" + script
}
return `
pip3 install \
--no-index \
--prefix=/system \
--root=/work \` + extra + `
'` + AbsUsrSrc.Append(name).Append(attr.Append...).String() + `'
` + script
}
// newPythonPackage creates [Metadata] for a [Python] package.
func newPythonPackage(
name string, id int, description, website, version string,
source pkg.Artifact, attrP *PackageAttr, attr *PipHelper,
build P, extra ...PArtifact,
) Metadata {
name = "python-" + name
return Metadata{
f: func(t Toolchain) (pkg.Artifact, string) {
return t.NewPackage(name, version, source, attrP, attr, slices.Concat(
P{Python},
extra,
build,
)...), version
},
Name: name,
Description: description,
Website: website,
Dependencies: slices.Concat(P{Python}, extra),
ID: id,
}
}
// newViaPip installs a pip wheel from a url.
func (t Toolchain) newViaPip(
name, version, url, checksum string,
extra ...PArtifact,
) pkg.Artifact {
return t.New(name+"-"+version, 0, t.AppendPresets(nil,
slices.Concat(P{Python}, extra)...,
), nil, nil, `
pip3 install \
--no-index \
--prefix=/system \
--root=/work \
'/usr/src/`+path.Base(url)+`'
`, pkg.Path(AbsUsrSrc.Append(path.Base(url)), false, pkg.NewHTTPGet(
nil, url,
mustDecode(checksum),
)))
}
// newPypi creates [Metadata] for a [pypi] package.
//
// [pypi]: https://pypi.org/
func newPypi(
name string, id int,
description, version, interpreter, abi, platform, checksum string,
extra ...PArtifact,
) Metadata {
return Metadata{
f: func(t Toolchain) (pkg.Artifact, string) {
return t.newViaPip(name, version, "https://files.pythonhosted.org/"+path.Join(
"packages",
interpreter,
string(name[0]),
name,
name+"-"+version+"-"+interpreter+"-"+abi+"-"+platform+".whl",
), checksum, extra...), version
},
Name: "python-" + name,
Description: description,
Website: "https://pypi.org/project/" + name + "/",
Dependencies: slices.Concat(P{Python}, extra),
ID: id,
}
}
func init() {
const (
version = "82.0.1"
checksum = "nznP46Tj539yqswtOrIM4nQgwLA1h-ApKX7z7ghazROCpyF5swtQGwsZoI93wkhc"
)
artifactsM[PythonSetuptools] = newPythonPackage(
"setuptools", 4021,
"the autotools of the Python ecosystem",
"https://pypi.org/project/setuptools/",
version, newFromGitHub(
"pypa/setuptools",
"v"+version, checksum,
), nil, &PipHelper{
BuildIsolation: true,
}, nil)
}
func init() {
const (
version = "1.1.1"
checksum = "rXZixTsZcRcIoUC1LvWrjySsiXSv5uhW6ng2P-yXZrbdj7FrSrDeJLCfC2b-ladV"
)
artifactsM[PythonVCSVersioning] = newPythonPackage(
"vcs-versioning", 389421,
"core VCS versioning functionality extracted as a standalone library",
"https://setuptools-scm.readthedocs.io/en/latest/",
version, newFromGitHub(
"pypa/setuptools-scm",
"vcs-versioning-v"+version, checksum,
), &PackageAttr{
Env: []string{
"SETUPTOOLS_SCM_PRETEND_VERSION=" + version,
},
}, &PipHelper{
Append: []string{"vcs-versioning"},
}, nil,
PythonSetuptools,
PythonPackaging,
)
}
func init() {
const (
version = "10.0.5"
checksum = "vTN_TPd-b4Wbsw5WmAcsWjrs-FNXXznOeVTDnb54NtXve9Oy-eb2HPy-RG3FzNqp"
)
artifactsM[PythonSetuptoolsSCM] = newPythonPackage(
"setuptools-scm", 7874,
"extracts Python package versions from Git or Mercurial metadata",
"https://setuptools-scm.readthedocs.io/en/latest/",
version, newFromGitHub(
"pypa/setuptools-scm",
"setuptools-scm-v"+version, checksum,
), &PackageAttr{
Env: []string{
"SETUPTOOLS_SCM_PRETEND_VERSION=" + version,
},
}, &PipHelper{
Append: []string{"setuptools-scm"},
}, nil,
PythonSetuptools,
PythonVCSVersioning,
)
}
func init() {
const (
version = "3.12.0"
checksum = "VcTsiGiDU1aPLbjSPe38f9OjJDCLcxFz9loObJqUI1ZxDHXAaQMxBpNyLz_G1Rff"
)
artifactsM[PythonFlitCore] = newPythonPackage(
"flit-core", 44841,
"a PEP 517 build backend for packages using Flit",
"https://flit.pypa.io/",
version, newFromGitHub(
"pypa/flit",
version, checksum,
), nil, &PipHelper{
Append: []string{"flit_core"},
}, nil,
)
}
func init() {
const (
version = "26.1"
checksum = "AOX4RBYPCMs2-vv8zSxQWANCK4XUbACRZWuR0ZHSiZ-fz_43IUXpMs_1-SZl8AVP"
)
artifactsM[PythonPackaging] = newPythonPackage(
"packaging", 60461,
"reusable core utilities for various Python Packaging interoperability specifications",
"https://packaging.pypa.io/",
version, newFromGitHub(
"pypa/packaging",
version, checksum,
), nil, nil, P{PythonFlitCore},
)
}
func init() {
const (
version = "1.0.4"
checksum = "zAZbcIO-JnNhb-xMg76W2j0tn5b2MtavWjUpGpPjBmbrcRZDLoXBn8o8yJ3DUgCT"
)
artifactsM[PythonPathspec] = newPythonPackage(
"pathspec", 23424,
"utility library for gitignore style pattern matching of file paths",
"https://github.com/cpburnz/python-pathspec",
version, newFromGitHub(
"cpburnz/python-pathspec",
"v"+version, checksum,
), nil, nil, P{PythonFlitCore},
)
}
func init() {
const (
version = "2026.1.14.14"
checksum = "ADfyOvGq7wfOhW10xTVvTmcuY7ZXw8Xlqhz7AM6KULOEm42rpk_45hfcO2PgxOIe"
)
artifactsM[PythonTroveClassifiers] = newPythonPackage(
"trove-classifiers", 88298,
"canonical source for classifiers on PyPI",
"https://pypi.org/p/trove-classifiers/",
version, newFromGitHub(
"pypa/trove-classifiers",
version, checksum,
), nil, nil, P{PythonSetuptools},
)
}
func init() {
const (
version = "1.6.0"
checksum = "GiUgDkKjF8Xn1cmq6iMhTGXzcPIYeaJrvQpHBSAJapNVx4UyuiTXqd5eVlxSClJu"
)
artifactsM[PythonPluggy] = newPythonPackage(
"pluggy", 7500,
"the core framework used by the pytest, tox, and devpi projects",
"https://pluggy.readthedocs.io/en/latest/",
version, newFromGitHub(
"pytest-dev/pluggy",
version, checksum,
), &PackageAttr{
Env: []string{
"SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PLUGGY=" + version,
},
}, nil, P{PythonSetuptoolsSCM},
)
}
func init() {
const (
version = "1.16.5"
checksum = "V2eREtqZLZeV85yb4O-bfAJCUluHcQP76Qfs0QH5s7RF_Oc8xIP8jD0jl85qFyWk"
)
artifactsM[PythonHatchling] = newPythonPackage(
"hatchling", 16137,
"the extensible, standards compliant build backend used by Hatch",
"https://hatch.pypa.io/latest/",
version, newFromGitHub(
"pypa/hatch",
"hatch-v"+version, checksum,
), nil, &PipHelper{
Append: []string{"backend"},
}, nil,
PythonPackaging,
PythonPathspec,
PythonTroveClassifiers,
PythonPluggy,
)
}
func init() {
artifactsM[PythonPygments] = newPypi(
"pygments", 3986,
" a syntax highlighting package written in Python",
"2.20.0", "py3", "none", "any",
"qlyqX2YSXcV0Z8XgGaPttc_gkq-xsu_nYs6NFOcYnk-CX7qmcj45gG-h6DpwPIcO",
)
artifactsM[PythonIniConfig] = newPypi(
"iniconfig", 114778,
"a small and simple INI-file parser module",
"2.3.0", "py3", "none", "any",
"SDgs4S5bXi77aVOeKTPv2TUrS3M9rduiK4DpU0hCmDsSBWqnZcWInq9lsx6INxut",
)
artifactsM[PythonPyTest] = newPypi(
"pytest", 3765,
"the pytest framework",
"9.0.3", "py3", "none", "any",
"57WLrIVOfyoRDjt5qD6LGOaDcDCtzQnKDSTUb7GzHyJDtry_nGHHs4-0tW0tiIJr",
PythonIniConfig,
PythonPackaging,
PythonPluggy,
PythonPygments,
)
artifactsM[PythonMarkupSafe] = newPypi(
"markupsafe", 3918,
"implements a text object that escapes characters so it is safe to use in HTML and XML",
"3.0.3", "cp314", "cp314", "musllinux_1_2_"+linuxArch(),
perArch[string]{
"amd64": "E2mo9ig_FKgTpGon_8qqviSEULwhnmxTIqd9vfyNxNpK4yofVYM7eLW_VE-LKbtO",
"arm64": "iG_hqsncOs8fA7bCaAg0x9XenXWlo9sqblyPcSG7yA9sfGLvM9KZznCpwWfOCwFC",
"riscv64": "7DI7U0M3jvr7U4uZml25GLw3m3EvMubCtNukZmss1gkVJ_DVkhV5DgX3Wt_sztbv",
}.unwrap(),
)
artifactsM[PythonMako] = newPypi(
"mako", 3915,
"a template library written in Python",
"1.3.11", "py3", "none", "any",
"WJ_hxYI-nNiuDiM6QhfAG84uO5U-M2aneB0JS9AQ2J2Oi6YXAbBxIdOeOEng6CoS",
PythonMarkupSafe,
)
artifactsM[PythonPyYAML] = newPypi(
"pyyaml", 4123,
"a YAML parser and emitter for Python",
"6.0.3", "cp314", "cp314", "musllinux_1_2_"+linuxArch(),
perArch[string]{
"amd64": "4_jhCFpUNtyrFp2HOMqUisR005u90MHId53eS7rkUbcGXkoaJ7JRsY21dREHEfGN",
"arm64": "sQ818ZYSmC7Vj9prIPx3sEYqSDhZlWvLbgHV9w4GjxsfQ63ZSzappctKM7Lb0Whw",
}.unwrap(),
)
}